IT++ Logo
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/itexports.h>
33 
34 #if (defined(_MSC_VER) && defined(ITPP_SHARED_LIB) && !(defined(itpp_EXPORTS) || defined(itpp_debug_EXPORTS)))
35 
36 #ifndef ITPP_PROTOCOL_EXCLUDED
37 #define ITPP_PROTOCOL_EXCLUDED
38 #pragma message( "PROTOCOL definitions are not available for MSVC shared builds" )
39 #endif
40 
41 #else
42 
43 #include <itpp/protocol/events.h>
44 #include <list>
45 #include <iostream>
46 
47 
48 namespace itpp
49 {
50 
52 
53 
54 class Base_Signal;
55 template<class DataType> class Signal;
56 template<class DataType> class Base_Slot;
57 template<class ObjectType, class DataType> class Slot;
58 
59 
123 template<class DataType>
124 class Signal
125 {
126 public:
127  friend class Base_Slot<DataType>;
128 
130  Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = false);
131 
132  // Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = true);
133 
136 
139 
141  void disconnect(Base_Slot<DataType>* slot = NULL);
142 
143  // Base_Event* arm(const Ttype delta_time, DataType signal); // Signal will trigger in 'delta_time' time units carrying data signal.
144 
145 
147  Base_Event* operator()(DataType signal, const Ttype delta_time = 0);
148 
150  void cancel();
151 
153  void set_name(const std::string &signal_name);
154 
156  void set_debug(const bool enable_debug = true);
157 
159  void trigger(DataType u);
160 
161 protected:
163  typedef typename std::list<Base_Slot<DataType>*, std::allocator< Base_Slot<DataType>* > >::iterator Base_Slot_Iterator;
167  std::list<Base_Slot<DataType>*, std::allocator<Base_Slot<DataType>* > > connected_slots;
169  std::string name;
170 
171 private:
172  bool armed;
173  bool debug;
174  bool single;
176 };
177 
178 
183 template<class DataType>
185 {
186 public:
187  friend class Signal<DataType>;
188 
190  Base_Slot(const std::string slot_name = "Unamed Base_Slot");
191 
193  virtual ~Base_Slot();
194 
196  void set_name(const std::string &slot_name);
197 
199  virtual void operator()(DataType signal) = 0;
200 
201 protected:
202  // virtual void exec(DataType signal) = 0;
204  typedef typename std::list<Signal<DataType>*, std::allocator< Signal<DataType>* > >::iterator Signal_Iterator;
206  std::string name;
208  void _connect(Signal<DataType>* signal);
210  void _disconnect(Signal<DataType>* signal);
212  std::list<Signal<DataType>*, std::allocator<Signal<DataType>* > > connected_signals;
213 };
214 
219 template<class ObjectType, class DataType>
220 class Slot : public Base_Slot<DataType>
221 {
222 public:
224  Slot(const std::string _name = "Unamed Slot");
225 
227  void forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u));
228 
230  ~Slot();
231 
233  void operator()(DataType u);
234 
235  //void exec(DataType signal);
236 
237 private:
238  ObjectType *po;
239  void(ObjectType::*pm)(DataType signal);
240 };
241 
242 
246 template<class ObjectType, class DataType>
247 class ATimer
248 {
249 public:
251  ATimer(const std::string Name = "Unamed ATimer") {
252  time_out_signal = new Signal<DataType>(Name, true);
253  time_out_slot = new Slot<ObjectType, DataType>(Name);
254  time_out_signal->connect(time_out_slot);
255  set_name(Name);
256  }
257 
259  void forward(ObjectType *po, void(ObjectType::*pm)(DataType u)) { time_out_slot->forward(po, pm); }
260 
262  void set(DataType u, const Ttype delta_t) {
263  time_out_signal->operator()(u, delta_t);
264  }
265 
267  void cancel() { time_out_signal->cancel(); }
268 
270  void set_name(const std::string Name) {
271  name = Name;
272  time_out_signal->set_name(name);
273  time_out_slot->set_name(name);
274  }
275 
276 protected:
278  std::string name;
279 
280 private:
281  Signal<DataType> *time_out_signal;
282  Slot<ObjectType, DataType> *time_out_slot;
283 };
284 
285 
286 
295 template <class THandler>
296 class TTimer
297 {
298 public:
300  TTimer(THandler & handler, void (THandler::*handlerFunction)(Ttype time)) :
301  signal("timer_signal", true) {
302  fPending = false;
303  fExpirationTime = 0;
304 
305  registered_handler = &handler;
306  registered_handler_function = handlerFunction;
307 
308  slot.forward(this, &TTimer<THandler>::HandleProcessEvent);
309  slot.set_name("timer_slot");
310  signal.set_debug(false);
311  signal.connect(&slot);
312  }
313 
315  virtual ~TTimer() {
316  if (fPending)
317  signal.cancel();
318  }
319 
321  void Set(Ttype time, bool relative = true) {
322  if (fPending)
323  signal.cancel();
324 
325  fPending = true;
326  double current_time = Event_Queue::now();
327  double delta_time;
328  if (relative) {
329  fExpirationTime = current_time + time;
330  delta_time = time;
331  }
332  else {
333  fExpirationTime = time;
334  delta_time = time - current_time;
335  }
336  signal(fExpirationTime, delta_time);
337  }
338 
340  void Reset() {
341  if (fPending) {
342  signal.cancel();
343  fPending = false; // TODO: Added this myself. Didn't work otherwise.
344  }
345  }
346 
349  it_assert(fPending, "TTimer<>::ExpirationTime: timer not set");
350  return fExpirationTime;
351  }
352 
354  bool IsPending() const { return fPending; }
355 
356 protected:
358  virtual void HandleProcessEvent(Ttype currentTime) {
359  fPending = false;
360  (*registered_handler.*registered_handler_function)(currentTime);
361  }
362 
364  virtual void HandleCancelEvent(Ttype) {
365  if (fPending)
366  signal.cancel();
367 
368  fPending = false;
369  }
370 
372  bool fPending;
375 
376 private:
377  THandler *registered_handler;
378  void(THandler::*registered_handler_function)(Ttype expiry_time);
379 
380  Signal<double> signal; // Used internally
381  Slot<TTimer, double> slot; // Used internally
382 };
383 
384 
385 
386 
387 
388 
389 // -----------------------------------------------------------------------------------------------
390 
391 template<class DataType>
392 Signal<DataType>::Signal(const std::string signal_name, const bool single_shot, const bool enable_debug)
393 {
394  armed = false;
395  e = NULL;
396  single = single_shot;
397  set_name(signal_name);
398  set_debug(enable_debug);
399 }
400 
401 template<class DataType>
403 {
405  begin = connected_slots.begin(),
406  end = connected_slots.end(),
407  i;
408 
409  for (i = begin; i != end; i++)
410  (*i)->_disconnect(this);
411 
412  connected_slots.clear();
413 
414  if (e != NULL) // Cancel a possibly pending event since we are about to die!
415  e->cancel();
416 }
417 
418 template<class DataType>
419 void Signal<DataType>::set_name(const std::string &signal_name)
420 {
421  name = signal_name;
422 }
423 
424 template<class DataType>
425 void Signal<DataType>::set_debug(const bool enable_debug)
426 {
427  debug = enable_debug;
428 }
429 
430 template<class DataType>
432 {
434  begin = connected_slots.begin(),
435  end = connected_slots.end(),
436  i;
437 
438  bool is_already_connected = false;
439 
440  for (i = begin; i != end; i++)
441  if ((*i) == slot)
442  is_already_connected = true;
443 
444  if (!is_already_connected) { // Multiple connections is meaningless.
445  connected_slots.push_back(slot);
446  slot->_connect(this); // Needed if a connected slot is deleted during run time.
447  }
448  else {
449  std::cout << "Signal '" << name << "' and Slot '" << slot->name << "' are already connected. Multiple connections have no effect!" << std::endl;
450  }
451 }
452 
453 template<class DataType>
455 {
457  begin = connected_slots.begin(),
458  end = connected_slots.end(),
459  i;
460 
461  for (i = begin; i != end; i++)
462  if ((*i) == slot) {
463  (*i)->_disconnect(this);
464  connected_slots.erase(i);
465  break;
466  }
467 }
468 
469 template<class DataType>
470 Base_Event* Signal<DataType>::operator()(DataType signal, const Ttype delta_time)
471 {
472  // Signal will trigger in 'delta_time' time units.
473  if (single) { // We are operating in single-shot mode.
474  if (armed) { // Cancel and schedule again with the new 'delta_time'.
475  if (debug)
476  std::cout << "Warning: Changing time for Signal '" << name << "'." << std::endl;
477  cancel();
478  operator()(signal, delta_time);
479  }
480  else {
481  e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time);
482  armed = true;
483  Event_Queue::add(e);
484  }
485  }
486  else { // Continious mode (cancel() has no effect).
487  e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time);
488  armed = true;
489  Event_Queue::add(e);
490  }
491  return e;
492 }
493 
494 template<class DataType>
496 {
497  if (armed && single) {
498  e->cancel();
499  e = NULL;
500  armed = false;
501  }
502 }
503 
504 
505 template<class DataType>
507 {
508  armed = false;
509  e = NULL;
511  begin = connected_slots.begin(),
512  end = connected_slots.end(),
513  i;
514 
515  for (i = begin; i != end; i++) { // Execute all the functions of the connected slots.
516  if (debug)
517  std::cout << "Time = " << Event_Queue::now() << ". Signal '" << name << "' was sent to Slot '" << (*i)->name << "'." << std::endl;
518  (*i)->operator()(u);
519  }
520 }
521 
522 template<class DataType>
524 {
526  begin = connected_slots.begin(),
527  end = connected_slots.end(),
528  i;
529 
530  for (i = begin; i != end; i++)
531  if ((*i) == slot) {
532  connected_slots.erase(i);
533  break;
534  }
535 }
536 
537 
538 template<class DataType>
539 Base_Slot<DataType>::Base_Slot(const std::string slot_name)
540 {
541  set_name(slot_name);
542 }
543 
544 template<class DataType>
545 void Base_Slot<DataType>::set_name(const std::string &slot_name)
546 {
547  name = slot_name;
548 }
549 
550 template<class DataType>
552 { // Notify all signals connect that we are being deleted ...
553 
555  begin = connected_signals.begin(),
556  end = connected_signals.end(),
557  i;
558 
559  for (i = begin; i != end; i++)
560  (*i)->_disconnect(this);
561 
562  connected_signals.clear();
563 }
564 
565 template<class DataType>
567 { // A signal is being connected to us.
568  connected_signals.push_back(signal);
569 }
570 
571 template<class DataType>
573 { // A signal is being disconnected from us.
574 
576  begin = connected_signals.begin(),
577  end = connected_signals.end(),
578  i;
579 
580  for (i = begin; i != end; i++)
581  if ((*i) == signal) {
582  connected_signals.erase(i);
583  break;
584  }
585 }
586 
587 template<class ObjectType, class DataType>
588 Slot<ObjectType, DataType>::Slot(const std::string slot_name) : Base_Slot<DataType>(slot_name)
589 {
590  pm = NULL;
591  po = NULL;
592 }
593 
594 template<class ObjectType, class DataType>
596 
597 template<class ObjectType, class DataType>
598 void Slot<ObjectType, DataType>::forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u))
599 {
600  pm = object_function_pointer;
601  po = object_pointer;
602 }
603 
604 // template<class ObjectType, class DataType>
605 // void Slot<ObjectType, DataType>::exec(DataType signal){
606 // if(pm&&po)
607 // (*po.*pm)(signal);
608 // }
609 
610 template<class ObjectType, class DataType>
612 {
613  if (pm&&po)
614  (*po.*pm)(signal);
615 }
616 
618 
619 } // namespace itpp
620 
621 #endif
622 
623 #endif // #ifndef SIGNAL_SLOT_H
624 
Base Event Class.
Definition: events.h:69
Base Slot class.
void _connect(Signal< DataType > *signal)
ADD DOCUMENTATION HERE.
virtual void operator()(DataType signal)=0
ADD DOCUMENTATION HERE.
std::list< Signal< DataType > *, std::allocator< Signal< DataType > * > > connected_signals
ADD DOCUMENTATION HERE.
Base_Slot(const std::string slot_name="Unamed Base_Slot")
Default Constructor.
std::string name
ADD DOCUMENTATION HERE.
virtual ~Base_Slot()
Desctuctor.
void set_name(const std::string &slot_name)
set slot name
void _disconnect(Signal< DataType > *signal)
ADD DOCUMENTATION HERE.
std::list< Signal< DataType > *, std::allocator< Signal< DataType > * > >::iterator Signal_Iterator
ADD DOCUMENTATION HERE.
An Event class that executes a function with some data as input when the event expires.
Definition: events.h:190
static void add(Base_Event *e)
Add event to Queue.
Definition: events.cpp:45
static Ttype now()
Return current time.
Definition: events.h:139
Automatic naming when saving.
Definition: itfile.h:429
Signals and slots.
void set_name(const std::string &signal_name)
set name of signal
std::string name
ADD DOCUMENTATION HERE.
std::list< Base_Slot< DataType > *, std::allocator< Base_Slot< DataType > * > > connected_slots
ADD DOCUMENTATION HERE.
void connect(Base_Slot< DataType > *slot)
Connect a slot to the signal.
void cancel()
cancel signal
Signal(const std::string signal_name="Unamed Signal", const bool single_shot=false, const bool enable_debug=false)
Default constructor.
void set_debug(const bool enable_debug=true)
Set debug mode. If true all signals are printed to stdout.
~Signal()
Destructor.
Base_Event * operator()(DataType signal, const Ttype delta_time=0)
Issue a signal.
void disconnect(Base_Slot< DataType > *slot=NULL)
Disconnect the slot from the signal.
void _disconnect(Base_Slot< DataType > *slot)
ADD DOCUMENTATION HERE.
std::list< Base_Slot< DataType > *, std::allocator< Base_Slot< DataType > * > >::iterator Base_Slot_Iterator
ADD DOCUMENTATION HERE.
void trigger(DataType u)
ADD DOCUMENTATION HERE.
Slot Class.
~Slot()
Destructor.
void operator()(DataType u)
ADD DOCUMENTATION HERE.
void forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u))
ADD DOCUMENTATION HERE.
Slot(const std::string _name="Unamed Slot")
Default constructor.
bool IsPending() const
ADD DOCUMENTATION HERE.
Ttype fExpirationTime
ADD DOCUMENTATION HERE.
virtual ~TTimer()
Destructor.
void Set(Ttype time, bool relative=true)
ADD DOCUMENTATION HERE.
Ttype ExpirationTime() const
ADD DOCUMENTATION HERE.
TTimer(THandler &handler, void(THandler::*handlerFunction)(Ttype time))
Default constructor.
void Reset()
ADD DOCUMENTATION HERE.
bool fPending
Flag denoting if timer is set.
virtual void HandleProcessEvent(Ttype currentTime)
ADD DOCUMENTATION HERE.
virtual void HandleCancelEvent(Ttype)
ADD DOCUMENTATION HERE.
Definitions of an event-based simulation class.
#define it_assert(t, s)
Abort if t is not true.
Definition: itassert.h:94
itpp namespace
Definition: itmex.h:37
double Ttype
64-bit floating point time
Definition: events.h:54
SourceForge Logo

Generated on Thu Sep 23 2021 09:01:13 for IT++ by Doxygen 1.9.1