luna-sysmgr-common
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SignalSlot.h
Go to the documentation of this file.
1 /* @@@LICENSE
2 *
3 * Copyright (c) 2008-2012 Hewlett-Packard Development Company, L.P.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * LICENSE@@@ */
18 
19 
20 
21 
22 #ifndef SIGNALSLOT_H
23 #define SIGNALSLOT_H
24 
25 #include "Common.h"
26 
27 #include <set>
28 #include <stdio.h>
29 
30 class Trackable;
31 
32 class Sender
33 {
34 public:
35 
36  virtual void disconnectTrackable(Trackable* recv) = 0;
37 };
38 
39 class Trackable {
40 public:
41 
42  virtual ~Trackable() {
43  for (std::set<Sender*>::iterator it = m_senders.begin();
44  it != m_senders.end(); ++it) {
45  (*it)->disconnectTrackable(this);
46  }
47  }
48 
49  void connected(Sender* sender) {
50  m_senders.insert(sender);
51  }
52 
53  void disconnected(Sender* sender) {
54  m_senders.erase(sender);
55  }
56 
57 private:
58 
59  std::set<Sender*> m_senders;
60 };
61 
62 
63 template <class Function>
65 {
66 public:
67 
68  inline Trackable* receiver() const {
69  return m_receiver;
70  }
71 
72 protected:
73 
75  Function m_function;
76 };
77 
78 
79 template <class Arg0=void, class Arg1=void, class Arg2=void, class Arg3=void, class Arg4=void>
80 class SlotBase
81 {
82 public:
83 
84  virtual void fire(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) = 0;
85 };
86 
87 template <>
88 class SlotBase<void, void, void, void, void>
89 {
90 public:
91 
92  virtual void fire() = 0;
93 };
94 
95 template <class Arg0>
96 class SlotBase<Arg0, void, void, void, void>
97 {
98 public:
99 
100  virtual void fire(Arg0 arg0) = 0;
101 };
102 
103 template <class Arg0, class Arg1>
104 class SlotBase<Arg0, Arg1, void, void, void>
105 {
106 public:
107 
108  virtual void fire(Arg0 arg0, Arg1 arg1) = 0;
109 };
110 
111 template <class Arg0, class Arg1, class Arg2>
112 class SlotBase<Arg0, Arg1, Arg2, void, void>
113 {
114 public:
115 
116  virtual void fire(Arg0 arg0, Arg1 arg1, Arg2 arg2) = 0;
117 };
118 
119 template <class Arg0, class Arg1, class Arg2, class Arg3>
120 class SlotBase<Arg0, Arg1, Arg2, Arg3, void>
121 {
122 public:
123 
124  virtual void fire(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) = 0;
125 };
126 
127 
128 
129 template <class Receiver, class Arg0=void, class Arg1=void, class Arg2=void, class Arg3=void, class Arg4=void>
130 class Slot : public SlotBase<Arg0, Arg1, Arg2, Arg3, Arg4>,
131  public FunctionWrapper<void (*)()>
132 {
133 public:
134 
135  typedef void (Receiver::*Function)(Arg0, Arg1, Arg2, Arg3, Arg4);
136 
137  Slot(Receiver* rec, Function func) {
138  this->m_receiver = rec;
139  this->m_function = func;
140  }
141 
142  void fire(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
143  (static_cast<Receiver*>(this->m_receiver)->*(this->m_function))(arg0, arg1, arg2, arg3, arg4);
144  }
145 };
146 
147 template <class Receiver>
148 class Slot<Receiver, void, void, void, void, void> : public SlotBase<>,
149  public FunctionWrapper<void (Receiver::*)()>
150 {
151 public:
152 
153  typedef void (Receiver::*Function)();
154 
155  Slot(Receiver* rec, Function func) {
156  this->m_receiver = rec;
157  this->m_function = func;
158  }
159 
160  void fire() {
161  (static_cast<Receiver*>(this->m_receiver)->*(this->m_function))();
162  }
163 };
164 
165 template <class Receiver, class Arg0>
166 class Slot<Receiver, Arg0, void, void, void, void> : public SlotBase<Arg0>,
167  public FunctionWrapper<void (Receiver::*)(Arg0)>
168 
169 {
170 public:
171 
172  typedef void (Receiver::*Function)(Arg0);
173 
174  Slot(Receiver* rec, Function func) {
175  Trackable* t = rec;
176  this->m_receiver = t;
177  this->m_function = func;
178  }
179 
180  void fire(Arg0 arg) {
181  (static_cast<Receiver*>(this->m_receiver)->*(this->m_function))(arg);
182  }
183 };
184 
185 template <class Receiver, class Arg0, class Arg1>
186 class Slot<Receiver, Arg0, Arg1, void, void, void> : public SlotBase<Arg0, Arg1>,
187  public FunctionWrapper<void (Receiver::*)(Arg0,Arg1)>
188 {
189 public:
190 
191  typedef void (Receiver::*Function)(Arg0, Arg1);
192 
193  Slot(Receiver* rec, Function func) {
194  this->m_receiver = rec;
195  this->m_function = func;
196  }
197 
198  void fire(Arg0 arg0, Arg1 arg1) {
199  (static_cast<Receiver*>(this->m_receiver)->*(this->m_function))(arg0, arg1);
200  }
201 };
202 
203 template <class Receiver, class Arg0, class Arg1, class Arg2>
204 class Slot<Receiver, Arg0, Arg1, Arg2, void, void> : public SlotBase<Arg0, Arg1, Arg2>,
205  public FunctionWrapper<void (Receiver::*)(Arg0,Arg1,Arg2)>
206 {
207 public:
208 
209  typedef void (Receiver::*Function)(Arg0, Arg1, Arg2);
210 
211  Slot(Receiver* rec, Function func) {
212  this->m_receiver = rec;
213  this->m_function = func;
214  }
215 
216  void fire(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
217  (static_cast<Receiver*>(this->m_receiver)->*(this->m_function))(arg0, arg1, arg2);
218  }
219 };
220 
221 template <class Receiver, class Arg0, class Arg1, class Arg2, class Arg3>
222 class Slot<Receiver, Arg0, Arg1, Arg2, Arg3, void> : public SlotBase<Arg0, Arg1, Arg2, Arg3>,
223  public FunctionWrapper<void (Receiver::*)(Arg0,Arg1,Arg2,Arg3)>
224 {
225 public:
226 
227  typedef void (Receiver::*Function)(Arg0, Arg1, Arg2, Arg3);
228 
229  Slot(Receiver* rec, Function func) {
230  this->m_receiver = rec;
231  this->m_function = func;
232  }
233 
234  void fire(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
235  (this->m_receiver->*(this->m_function))(arg0, arg1, arg2, arg3);
236  }
237 };
238 
239 
240 
241 
242 
243 template <class Arg0=void, class Arg1=void, class Arg2=void, class Arg3=void, class Arg4=void>
244 class SignalBase : public Sender
245 {
246 public:
247 
249 
250  virtual ~SignalBase() {
251  for (typename SlotSet::const_iterator it = this->m_slots.begin();
252  it != this->m_slots.end(); ++it) {
253  Sl* s = static_cast<Sl*>(*it);
254  s->receiver()->disconnected(this);
255  delete (*it);
256  }
257  }
258 
260  m_slots.insert(slot);
261  }
262 
264  m_slots.insert(slot);
265  recv->connected(this);
266  }
267 
268  void disconnect(Trackable* recv) {
269  typename SlotSet::iterator it = this->m_slots.begin();
270  typename SlotSet::iterator itEnd = this->m_slots.end();
271  while (it != itEnd) {
272  Sl* s = static_cast<Sl*>(*it);
273  if (s->receiver() == recv) {
274  delete (*it);
275  this->m_slots.erase(it++);
276  continue;
277  }
278 
279  ++it;
280  }
281  }
282 
283  virtual void disconnectTrackable(Trackable* recv) {
284  disconnect(recv);
285  }
286 
287 protected:
288 
289  typedef std::set<SlotBase<Arg0, Arg1, Arg2, Arg3, Arg4>* > SlotSet;
291 };
292 
293 template <class Arg0=void, class Arg1=void, class Arg2=void, class Arg3=void, class Arg4=void>
294 class Signal : public SignalBase<Arg0, Arg1, Arg2, Arg3, Arg4>
295 {
296 public:
297 
298  template <class Receiver>
299  void connect(Receiver* rec, void (Receiver::*func)(Arg0, Arg1, Arg2, Arg3, Arg4)) {
301  }
302 
303  void fire(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
304  typename std::set<SlotBase<Arg0, Arg1, Arg2, Arg3, Arg4>* >::iterator it = this->m_slots.begin();
305  while (it != this->m_slots.end()) {
306  (*it++)->fire(arg0, arg1, arg2, arg3, arg4);
307  }
308  }
309 };
310 
311 
312 template <>
313 class Signal<void, void, void, void, void> : public SignalBase<>
314 {
315 public:
316 
317  template <class Receiver>
318  void connect(Receiver* rec, void (Receiver::*func)()) {
319  SignalBase<>::connect(rec, new Slot<Receiver>(rec, func));
320  }
321 
322  void fire() {
323  std::set<SlotBase<>* >::iterator it = this->m_slots.begin();
324  while (it != this->m_slots.end()) {
325  (*it++)->fire();
326  }
327  }
328 };
329 
330 template <class Arg0>
331 class Signal<Arg0, void, void, void, void> : public SignalBase<Arg0>
332 {
333 public:
334 
335  template <class Receiver>
336  void connect(Receiver* rec, void (Receiver::*func)(Arg0)) {
337  SignalBase<Arg0>::connect(rec, new Slot<Receiver, Arg0>(rec, func));
338  }
339 
340  void fire(Arg0 arg0) {
341  typename std::set<SlotBase<Arg0>* >::iterator it = this->m_slots.begin();
342  while (it != this->m_slots.end()) {
343  (*it++)->fire(arg0);
344  }
345  }
346 };
347 
348 template <class Arg0, class Arg1>
349 class Signal<Arg0, Arg1, void, void, void> : public SignalBase<Arg0, Arg1>
350 {
351 public:
352 
353  template <class Receiver>
354  void connect(Receiver* rec, void (Receiver::*func)(Arg0, Arg1)) {
356  }
357 
358  void fire(Arg0 arg0, Arg1 arg1) {
359  typename std::set<SlotBase<Arg0, Arg1>* >::iterator it = this->m_slots.begin();
360  while (it != this->m_slots.end()) {
361  (*it++)->fire(arg0, arg1);
362  }
363  }
364 };
365 
366 template <class Arg0, class Arg1, class Arg2>
367 class Signal<Arg0, Arg1, Arg2, void, void> : public SignalBase<Arg0, Arg1, Arg2>
368 {
369 public:
370 
371  template <class Receiver>
372  void connect(Receiver* rec, void (Receiver::*func)(Arg0, Arg1, Arg2)) {
374  }
375 
376  void fire(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
377  typename std::set<SlotBase<Arg0, Arg1, Arg2>* >::iterator it = this->m_slots.begin();
378  while (it != this->m_slots.end()) {
379  (*it++)->fire(arg0, arg1, arg2);
380  }
381  }
382 };
383 
384 template <class Arg0, class Arg1, class Arg2, class Arg3>
385 class Signal<Arg0, Arg1, Arg2, Arg3, void> : public SignalBase<Arg0, Arg1, Arg2, Arg3>
386 {
387 public:
388 
389  template <class Receiver>
390  void connect(Receiver* rec, void (Receiver::*func)(Arg0, Arg1, Arg2, Arg3)) {
392  }
393 
394  void fire(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
395  typename std::set<SlotBase<Arg0, Arg1, Arg2, Arg3>* >::iterator it = this->m_slots.begin();
396  while (it != this->m_slots.end()) {
397  (*it++)->fire(arg0, arg1, arg2, arg3);
398  }
399  }
400 };
401 
402 /*
403  *
404  * Testing code
405 
406 class Rec : public Trackable {
407 public:
408 
409  void memFun0() {
410  printf("%s\n", __PRETTY_FUNCTION__);
411  }
412 
413  void memFun1(int a0) {
414  printf("%s: %d\n", __PRETTY_FUNCTION__, a0);
415  }
416 
417  void memFun2(int a0, double a1) {
418  printf("%s: %d, %g\n", __PRETTY_FUNCTION__, a0, a1);
419  }
420 
421  void memFun3(int a0, double a1, char a2) {
422  printf("%s: %d, %g, %d\n", __PRETTY_FUNCTION__, a0, a1, a2);
423  }
424 
425  void memFun4(int a0, double a1, char a2, float a3) {
426  printf("%s: %d, %g, %d, %f\n", __PRETTY_FUNCTION__, a0, a1, a2, a3);
427  }
428 };
429 
430 int main() {
431 
432  Signal<> sig0;
433  Signal<int> sig1;
434  Signal<int, double> sig2;
435  Signal<int, double, char> sig3;
436  Signal<int, double, char, float> sig4;
437 
438  {
439  Rec r;
440 
441  sig0.connect(&r, &Rec::memFun0);
442  sig1.connect(&r, &Rec::memFun1);
443  sig2.connect(&r, &Rec::memFun2);
444  sig3.connect(&r, &Rec::memFun3);
445  sig4.connect(&r, &Rec::memFun4);
446 
447  sig0.fire();
448  sig1.fire(1);
449  sig2.fire(1, 2.0);
450  sig3.fire(1, 2.0, 3);
451  sig4.fire(1, 2.0, 3, 4.0f);
452  }
453 
454  sig0.fire();
455  sig1.fire(1);
456  sig2.fire(1, 2.0);
457  sig3.fire(1, 2.0, 3);
458  sig4.fire(1, 2.0, 3, 4.0f);
459 }
460 
461 */
462 
463 #endif // SIGNALSLOT_H
464 
465