IT++ Logo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
signals_slots.h
Go to the documentation of this file.
1 
29 #ifndef SIGNAL_SLOT_H
30 #define SIGNAL_SLOT_H
31 
32 #include <itpp/protocol/events.h>
33 #include <list>
34 #include <iostream>
35 
36 
37 namespace itpp
38 {
39 
41 
42 
43 class Base_Signal;
44 template<class DataType> class Signal;
45 template<class DataType> class Base_Slot;
46 template<class ObjectType, class DataType> class Slot;
47 
48 
112 template<class DataType>
113 class Signal
114 {
115 public:
116  friend class Base_Slot<DataType>;
117 
119  Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = false);
120 
121  // Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = true);
122 
124  ~Signal();
125 
127  void connect(Base_Slot<DataType>* slot);
128 
130  void disconnect(Base_Slot<DataType>* slot = NULL);
131 
132  // Base_Event* arm(const Ttype delta_time, DataType signal); // Signal will trigger in 'delta_time' time units carrying data signal.
133 
134 
136  Base_Event* operator()(DataType signal, const Ttype delta_time = 0);
137 
139  void cancel();
140 
142  void set_name(const std::string &signal_name);
143 
145  void set_debug(const bool enable_debug = true);
146 
148  void trigger(DataType u);
149 
150 protected:
152  typedef typename std::list<Base_Slot<DataType>*, std::allocator< Base_Slot<DataType>* > >::iterator Base_Slot_Iterator;
154  void _disconnect(Base_Slot<DataType>* slot);
156  std::list<Base_Slot<DataType>*, std::allocator<Base_Slot<DataType>* > > connected_slots;
158  std::string name;
159 
160 private:
161  bool armed;
162  bool debug;
163  bool single;
165 };
166 
167 
172 template<class DataType>
174 {
175 public:
176  friend class Signal<DataType>;
177 
179  Base_Slot(const std::string slot_name = "Unamed Base_Slot");
180 
182  virtual ~Base_Slot();
183 
185  void set_name(const std::string &slot_name);
186 
188  virtual void operator()(DataType signal) = 0;
189 
190 protected:
191  // virtual void exec(DataType signal) = 0;
193  typedef typename std::list<Signal<DataType>*, std::allocator< Signal<DataType>* > >::iterator Signal_Iterator;
195  std::string name;
197  void _connect(Signal<DataType>* signal);
199  void _disconnect(Signal<DataType>* signal);
201  std::list<Signal<DataType>*, std::allocator<Signal<DataType>* > > connected_signals;
202 };
203 
208 template<class ObjectType, class DataType>
209 class Slot : public Base_Slot<DataType>
210 {
211 public:
213  Slot(const std::string _name = "Unamed Slot");
214 
216  void forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u));
217 
219  ~Slot();
220 
222  void operator()(DataType u);
223 
224  //void exec(DataType signal);
225 
226 private:
227  ObjectType *po;
228  void(ObjectType::*pm)(DataType signal);
229 };
230 
231 
235 template<class ObjectType, class DataType>
236 class ATimer
237 {
238 public:
240  ATimer(const std::string Name = "Unamed ATimer") {
241  time_out_signal = new Signal<DataType>(Name, true);
242  time_out_slot = new Slot<ObjectType, DataType>(Name);
243  time_out_signal->connect(time_out_slot);
244  set_name(Name);
245  }
246 
248  void forward(ObjectType *po, void(ObjectType::*pm)(DataType u)) { time_out_slot->forward(po, pm); }
249 
251  void set(DataType u, const Ttype delta_t) {
252  time_out_signal->operator()(u, delta_t);
253  }
254 
256  void cancel() { time_out_signal->cancel(); }
257 
259  void set_name(const std::string Name) {
260  name = Name;
261  time_out_signal->set_name(name);
262  time_out_slot->set_name(name);
263  }
264 
265 protected:
267  std::string name;
268 
269 private:
270  Signal<DataType> *time_out_signal;
271  Slot<ObjectType, DataType> *time_out_slot;
272 };
273 
274 
275 
284 template <class THandler>
285 class TTimer
286 {
287 public:
289  TTimer(THandler & handler, void (THandler::*handlerFunction)(Ttype time)) :
290  signal("timer_signal", true) {
291  fPending = false;
292  fExpirationTime = 0;
293 
294  registered_handler = &handler;
295  registered_handler_function = handlerFunction;
296 
298  slot.set_name("timer_slot");
299  signal.set_debug(false);
300  signal.connect(&slot);
301  }
302 
304  virtual ~TTimer() {
305  if (fPending)
306  signal.cancel();
307  }
308 
310  void Set(Ttype time, bool relative = true) {
311  if (fPending)
312  signal.cancel();
313 
314  fPending = true;
315  double current_time = Event_Queue::now();
316  double delta_time;
317  if (relative) {
318  fExpirationTime = current_time + time;
319  delta_time = time;
320  }
321  else {
322  fExpirationTime = time;
323  delta_time = time - current_time;
324  }
325  signal(fExpirationTime, delta_time);
326  }
327 
329  void Reset() {
330  if (fPending) {
331  signal.cancel();
332  fPending = false; // TODO: Added this myself. Didn't work otherwise.
333  }
334  }
335 
338  it_assert(fPending, "TTimer<>::ExpirationTime: timer not set");
339  return fExpirationTime;
340  }
341 
343  bool IsPending() const { return fPending; }
344 
345 protected:
347  virtual void HandleProcessEvent(Ttype currentTime) {
348  fPending = false;
349  (*registered_handler.*registered_handler_function)(currentTime);
350  }
351 
353  virtual void HandleCancelEvent(Ttype) {
354  if (fPending)
355  signal.cancel();
356 
357  fPending = false;
358  }
359 
361  bool fPending;
364 
365 private:
366  THandler *registered_handler;
367  void(THandler::*registered_handler_function)(Ttype expiry_time);
368 
369  Signal<double> signal; // Used internally
370  Slot<TTimer, double> slot; // Used internally
371 };
372 
373 
374 
375 
376 
377 
378 // -----------------------------------------------------------------------------------------------
379 
380 template<class DataType>
381 Signal<DataType>::Signal(const std::string signal_name, const bool single_shot, const bool enable_debug)
382 {
383  armed = false;
384  e = NULL;
385  single = single_shot;
386  set_name(signal_name);
387  set_debug(enable_debug);
388 }
389 
390 template<class DataType>
392 {
394  begin = connected_slots.begin(),
395  end = connected_slots.end(),
396  i;
397 
398  for (i = begin; i != end; i++)
399  (*i)->_disconnect(this);
400 
401  connected_slots.clear();
402 
403  if (e != NULL) // Cancel a possibly pending event since we are about to die!
404  e->cancel();
405 }
406 
407 template<class DataType>
408 void Signal<DataType>::set_name(const std::string &signal_name)
409 {
410  name = signal_name;
411 }
412 
413 template<class DataType>
414 void Signal<DataType>::set_debug(const bool enable_debug)
415 {
416  debug = enable_debug;
417 }
418 
419 template<class DataType>
421 {
423  begin = connected_slots.begin(),
424  end = connected_slots.end(),
425  i;
426 
427  bool is_already_connected = false;
428 
429  for (i = begin; i != end; i++)
430  if ((*i) == slot)
431  is_already_connected = true;
432 
433  if (!is_already_connected) { // Multiple connections is meaningless.
434  connected_slots.push_back(slot);
435  slot->_connect(this); // Needed if a connected slot is deleted during run time.
436  }
437  else {
438  std::cout << "Signal '" << name << "' and Slot '" << slot->name << "' are already connected. Multiple connections have no effect!" << std::endl;
439  }
440 }
441 
442 template<class DataType>
444 {
446  begin = connected_slots.begin(),
447  end = connected_slots.end(),
448  i;
449 
450  for (i = begin; i != end; i++)
451  if ((*i) == slot) {
452  (*i)->_disconnect(this);
453  connected_slots.erase(i);
454  break;
455  }
456 }
457 
458 template<class DataType>
459 Base_Event* Signal<DataType>::operator()(DataType signal, const Ttype delta_time)
460 {
461  // Signal will trigger in 'delta_time' time units.
462  if (single) { // We are operating in single-shot mode.
463  if (armed) { // Cancel and schedule again with the new 'delta_time'.
464  if (debug)
465  std::cout << "Warning: Changing time for Signal '" << name << "'." << std::endl;
466  cancel();
467  operator()(signal, delta_time);
468  }
469  else {
470  e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time);
471  armed = true;
472  Event_Queue::add(e);
473  }
474  }
475  else { // Continious mode (cancel() has no effect).
476  e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time);
477  armed = true;
478  Event_Queue::add(e);
479  }
480  return e;
481 }
482 
483 template<class DataType>
485 {
486  if (armed && single) {
487  e->cancel();
488  e = NULL;
489  armed = false;
490  }
491 }
492 
493 
494 template<class DataType>
496 {
497  armed = false;
498  e = NULL;
500  begin = connected_slots.begin(),
501  end = connected_slots.end(),
502  i;
503 
504  for (i = begin; i != end; i++) { // Execute all the functions of the connected slots.
505  if (debug)
506  std::cout << "Time = " << Event_Queue::now() << ". Signal '" << name << "' was sent to Slot '" << (*i)->name << "'." << std::endl;
507  (*i)->operator()(u);
508  }
509 }
510 
511 template<class DataType>
513 {
515  begin = connected_slots.begin(),
516  end = connected_slots.end(),
517  i;
518 
519  for (i = begin; i != end; i++)
520  if ((*i) == slot) {
521  connected_slots.erase(i);
522  break;
523  }
524 }
525 
526 
527 template<class DataType>
528 Base_Slot<DataType>::Base_Slot(const std::string slot_name)
529 {
530  set_name(slot_name);
531 }
532 
533 template<class DataType>
534 void Base_Slot<DataType>::set_name(const std::string &slot_name)
535 {
536  name = slot_name;
537 }
538 
539 template<class DataType>
541 { // Notify all signals connect that we are being deleted ...
542 
544  begin = connected_signals.begin(),
545  end = connected_signals.end(),
546  i;
547 
548  for (i = begin; i != end; i++)
549  (*i)->_disconnect(this);
550 
551  connected_signals.clear();
552 }
553 
554 template<class DataType>
556 { // A signal is being connected to us.
557  connected_signals.push_back(signal);
558 }
559 
560 template<class DataType>
562 { // A signal is being disconnected from us.
563 
565  begin = connected_signals.begin(),
566  end = connected_signals.end(),
567  i;
568 
569  for (i = begin; i != end; i++)
570  if ((*i) == signal) {
571  connected_signals.erase(i);
572  break;
573  }
574 }
575 
576 template<class ObjectType, class DataType>
577 Slot<ObjectType, DataType>::Slot(const std::string slot_name) : Base_Slot<DataType>(slot_name)
578 {
579  pm = NULL;
580  po = NULL;
581 }
582 
583 template<class ObjectType, class DataType>
585 
586 template<class ObjectType, class DataType>
587 void Slot<ObjectType, DataType>::forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u))
588 {
589  pm = object_function_pointer;
590  po = object_pointer;
591 }
592 
593 // template<class ObjectType, class DataType>
594 // void Slot<ObjectType, DataType>::exec(DataType signal){
595 // if(pm&&po)
596 // (*po.*pm)(signal);
597 // }
598 
599 template<class ObjectType, class DataType>
601 {
602  if (pm&&po)
603  (*po.*pm)(signal);
604 }
605 
607 
608 } // namespace itpp
609 
610 #endif // #ifndef SIGNAL_SLOT_H
611 
SourceForge Logo

Generated on Fri Mar 21 2014 17:14:13 for IT++ by Doxygen 1.8.1.2