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
44#include <list>
45#include <iostream>
46
47
48namespace itpp
49{
50
52
53
54class Base_Signal;
55template<class DataType> class Signal;
56template<class DataType> class Base_Slot;
57template<class ObjectType, class DataType> class Slot;
58
59
123template<class DataType>
125{
126public:
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
161protected:
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
171private:
172 bool armed;
173 bool debug;
174 bool single;
176};
177
178
183template<class DataType>
185{
186public:
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
201protected:
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;
212 std::list<Signal<DataType>*, std::allocator<Signal<DataType>* > > connected_signals;
213};
214
219template<class ObjectType, class DataType>
220class Slot : public Base_Slot<DataType>
221{
222public:
224 Slot(const std::string _name = "Unamed Slot");
225
227 void forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u));
228
231
233 void operator()(DataType u);
234
235 //void exec(DataType signal);
236
237private:
238 ObjectType *po;
239 void(ObjectType::*pm)(DataType signal);
240};
241
242
246template<class ObjectType, class DataType>
247class ATimer
248{
249public:
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
276protected:
278 std::string name;
279
280private:
281 Signal<DataType> *time_out_signal;
282 Slot<ObjectType, DataType> *time_out_slot;
283};
284
285
286
295template <class THandler>
297{
298public:
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
356protected:
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
375
376private:
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
391template<class DataType>
392Signal<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
401template<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
418template<class DataType>
419void Signal<DataType>::set_name(const std::string &signal_name)
420{
421 name = signal_name;
422}
423
424template<class DataType>
425void Signal<DataType>::set_debug(const bool enable_debug)
426{
427 debug = enable_debug;
428}
429
430template<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
453template<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
469template<class DataType>
470Base_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;
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;
490 }
491 return e;
492}
493
494template<class DataType>
496{
497 if (armed && single) {
498 e->cancel();
499 e = NULL;
500 armed = false;
501 }
502}
503
504
505template<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
522template<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
538template<class DataType>
539Base_Slot<DataType>::Base_Slot(const std::string slot_name)
540{
541 set_name(slot_name);
542}
543
544template<class DataType>
545void Base_Slot<DataType>::set_name(const std::string &slot_name)
546{
547 name = slot_name;
548}
549
550template<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
565template<class DataType>
567{ // A signal is being connected to us.
568 connected_signals.push_back(signal);
569}
570
571template<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
587template<class ObjectType, class DataType>
588Slot<ObjectType, DataType>::Slot(const std::string slot_name) : Base_Slot<DataType>(slot_name)
589{
590 pm = NULL;
591 po = NULL;
592}
593
594template<class ObjectType, class DataType>
596
597template<class ObjectType, class DataType>
598void 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
610template<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.
std::list< Signal< DataType > *, std::allocator< Signal< DataType > * > >::iterator Signal_Iterator
ADD DOCUMENTATION HERE.
void set_name(const std::string &slot_name)
set slot name
void _disconnect(Signal< DataType > *signal)
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.
std::list< Base_Slot< DataType > *, std::allocator< Base_Slot< DataType > * > >::iterator Base_Slot_Iterator
ADD DOCUMENTATION HERE.
void disconnect(Base_Slot< DataType > *slot=NULL)
Disconnect the slot from the signal.
void _disconnect(Base_Slot< DataType > *slot)
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 Mon Apr 7 2025 07:53:18 for IT++ by Doxygen 1.11.0