00001
00029 #ifndef SIGNAL_SLOT_H
00030 #define SIGNAL_SLOT_H
00031
00032 #include <itpp/protocol/events.h>
00033 #include <list>
00034 #include <iostream>
00035
00036
00037 namespace itpp
00038 {
00039
00041
00042
00043 class Base_Signal;
00044 template<class DataType> class Signal;
00045 template<class DataType> class Base_Slot;
00046 template<class ObjectType, class DataType> class Slot;
00047
00048
00112 template<class DataType>
00113 class Signal
00114 {
00115 public:
00116 friend class Base_Slot<DataType>;
00117
00119 Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = false);
00120
00121
00122
00124 ~Signal();
00125
00127 void connect(Base_Slot<DataType>* slot);
00128
00130 void disconnect(Base_Slot<DataType>* slot = NULL);
00131
00132
00133
00134
00136 Base_Event* operator()(DataType signal, const Ttype delta_time = 0);
00137
00139 void cancel();
00140
00142 void set_name(const std::string &signal_name);
00143
00145 void set_debug(const bool enable_debug = true);
00146
00148 void trigger(DataType u);
00149
00150 protected:
00152 typedef typename std::list<Base_Slot<DataType>*, std::allocator< Base_Slot<DataType>* > >::iterator Base_Slot_Iterator;
00154 void _disconnect(Base_Slot<DataType>* slot);
00156 std::list<Base_Slot<DataType>*, std::allocator<Base_Slot<DataType>* > > connected_slots;
00158 std::string name;
00159
00160 private:
00161 bool armed;
00162 bool debug;
00163 bool single;
00164 Data_Event<Signal, DataType> *e;
00165 };
00166
00167
00172 template<class DataType>
00173 class Base_Slot
00174 {
00175 public:
00176 friend class Signal<DataType>;
00177
00179 Base_Slot(const std::string slot_name = "Unamed Base_Slot");
00180
00182 virtual ~Base_Slot();
00183
00185 void set_name(const std::string &slot_name);
00186
00188 virtual void operator()(DataType signal) = 0;
00189
00190 protected:
00191
00193 typedef typename std::list<Signal<DataType>*, std::allocator< Signal<DataType>* > >::iterator Signal_Iterator;
00195 std::string name;
00197 void _connect(Signal<DataType>* signal);
00199 void _disconnect(Signal<DataType>* signal);
00201 std::list<Signal<DataType>*, std::allocator<Signal<DataType>* > > connected_signals;
00202 };
00203
00208 template<class ObjectType, class DataType>
00209 class Slot : public Base_Slot<DataType>
00210 {
00211 public:
00213 Slot(const std::string _name = "Unamed Slot");
00214
00216 void forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u));
00217
00219 ~Slot();
00220
00222 void operator()(DataType u);
00223
00224
00225
00226 private:
00227 ObjectType *po;
00228 void(ObjectType::*pm)(DataType signal);
00229 };
00230
00231
00235 template<class ObjectType, class DataType>
00236 class ATimer
00237 {
00238 public:
00240 ATimer(const std::string Name = "Unamed ATimer") {
00241 time_out_signal = new Signal<DataType>(Name, true);
00242 time_out_slot = new Slot<ObjectType, DataType>(Name);
00243 time_out_signal->connect(time_out_slot);
00244 set_name(Name);
00245 }
00246
00248 void forward(ObjectType *po, void(ObjectType::*pm)(DataType u)) { time_out_slot->forward(po, pm); }
00249
00251 void set(DataType u, const Ttype delta_t) {
00252 time_out_signal->operator()(u, delta_t);
00253 }
00254
00256 void cancel() { time_out_signal->cancel(); }
00257
00259 void set_name(const std::string Name) {
00260 name = Name;
00261 time_out_signal->set_name(name);
00262 time_out_slot->set_name(name);
00263 }
00264
00265 protected:
00267 std::string name;
00268
00269 private:
00270 Signal<DataType> *time_out_signal;
00271 Slot<ObjectType, DataType> *time_out_slot;
00272 };
00273
00274
00275
00284 template <class THandler>
00285 class TTimer
00286 {
00287 public:
00289 TTimer(THandler & handler, void (THandler::*handlerFunction)(Ttype time)) :
00290 signal("timer_signal", true) {
00291 fPending = false;
00292 fExpirationTime = 0;
00293
00294 registered_handler = &handler;
00295 registered_handler_function = handlerFunction;
00296
00297 slot.forward(this, &TTimer<THandler>::HandleProcessEvent);
00298 slot.set_name("timer_slot");
00299 signal.set_debug(false);
00300 signal.connect(&slot);
00301 }
00302
00304 virtual ~TTimer() {
00305 if (fPending)
00306 signal.cancel();
00307 }
00308
00310 void Set(Ttype time, bool relative = true) {
00311 if (fPending)
00312 signal.cancel();
00313
00314 fPending = true;
00315 double current_time = Event_Queue::now();
00316 double delta_time;
00317 if (relative) {
00318 fExpirationTime = current_time + time;
00319 delta_time = time;
00320 }
00321 else {
00322 fExpirationTime = time;
00323 delta_time = time - current_time;
00324 }
00325 signal(fExpirationTime, delta_time);
00326 }
00327
00329 void Reset() {
00330 if (fPending) {
00331 signal.cancel();
00332 fPending = false;
00333 }
00334 }
00335
00337 Ttype ExpirationTime() const {
00338 it_assert(fPending, "TTimer<>::ExpirationTime: timer not set");
00339 return fExpirationTime;
00340 }
00341
00343 bool IsPending() const { return fPending; }
00344
00345 protected:
00347 virtual void HandleProcessEvent(Ttype currentTime) {
00348 fPending = false;
00349 (*registered_handler.*registered_handler_function)(currentTime);
00350 }
00351
00353 virtual void HandleCancelEvent(Ttype) {
00354 if (fPending)
00355 signal.cancel();
00356
00357 fPending = false;
00358 }
00359
00361 bool fPending;
00363 Ttype fExpirationTime;
00364
00365 private:
00366 THandler *registered_handler;
00367 void(THandler::*registered_handler_function)(Ttype expiry_time);
00368
00369 Signal<double> signal;
00370 Slot<TTimer, double> slot;
00371 };
00372
00373
00374
00375
00376
00377
00378
00379
00380 template<class DataType>
00381 Signal<DataType>::Signal(const std::string signal_name, const bool single_shot, const bool enable_debug)
00382 {
00383 armed = false;
00384 e = NULL;
00385 single = single_shot;
00386 set_name(signal_name);
00387 set_debug(enable_debug);
00388 }
00389
00390 template<class DataType>
00391 Signal<DataType>::~Signal()
00392 {
00393 Base_Slot_Iterator
00394 begin = connected_slots.begin(),
00395 end = connected_slots.end(),
00396 i;
00397
00398 for (i = begin; i != end; i++)
00399 (*i)->_disconnect(this);
00400
00401 connected_slots.clear();
00402
00403 if (e != NULL)
00404 e->cancel();
00405 }
00406
00407 template<class DataType>
00408 void Signal<DataType>::set_name(const std::string &signal_name)
00409 {
00410 name = signal_name;
00411 }
00412
00413 template<class DataType>
00414 void Signal<DataType>::set_debug(const bool enable_debug)
00415 {
00416 debug = enable_debug;
00417 }
00418
00419 template<class DataType>
00420 void Signal<DataType>::connect(Base_Slot<DataType>* slot)
00421 {
00422 Base_Slot_Iterator
00423 begin = connected_slots.begin(),
00424 end = connected_slots.end(),
00425 i;
00426
00427 bool is_already_connected = false;
00428
00429 for (i = begin; i != end; i++)
00430 if ((*i) == slot)
00431 is_already_connected = true;
00432
00433 if (!is_already_connected) {
00434 connected_slots.push_back(slot);
00435 slot->_connect(this);
00436 }
00437 else {
00438 std::cout << "Signal '" << name << "' and Slot '" << slot->name << "' are already connected. Multiple connections have no effect!" << std::endl;
00439 }
00440 }
00441
00442 template<class DataType>
00443 void Signal<DataType>::disconnect(Base_Slot<DataType>* slot)
00444 {
00445 Base_Slot_Iterator
00446 begin = connected_slots.begin(),
00447 end = connected_slots.end(),
00448 i;
00449
00450 for (i = begin; i != end; i++)
00451 if ((*i) == slot) {
00452 (*i)->_disconnect(this);
00453 connected_slots.erase(i);
00454 break;
00455 }
00456 }
00457
00458 template<class DataType>
00459 Base_Event* Signal<DataType>::operator()(DataType signal, const Ttype delta_time)
00460 {
00461
00462 if (single) {
00463 if (armed) {
00464 if (debug)
00465 std::cout << "Warning: Changing time for Signal '" << name << "'." << std::endl;
00466 cancel();
00467 operator()(signal, delta_time);
00468 }
00469 else {
00470 e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time);
00471 armed = true;
00472 Event_Queue::add(e);
00473 }
00474 }
00475 else {
00476 e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time);
00477 armed = true;
00478 Event_Queue::add(e);
00479 }
00480 return e;
00481 }
00482
00483 template<class DataType>
00484 void Signal<DataType>::cancel()
00485 {
00486 if (armed && single) {
00487 e->cancel();
00488 e = NULL;
00489 armed = false;
00490 }
00491 }
00492
00493
00494 template<class DataType>
00495 void Signal<DataType>::trigger(DataType u)
00496 {
00497 armed = false;
00498 e = NULL;
00499 Base_Slot_Iterator
00500 begin = connected_slots.begin(),
00501 end = connected_slots.end(),
00502 i;
00503
00504 for (i = begin; i != end; i++) {
00505 if (debug)
00506 std::cout << "Time = " << Event_Queue::now() << ". Signal '" << name << "' was sent to Slot '" << (*i)->name << "'." << std::endl;
00507 (*i)->operator()(u);
00508 }
00509 }
00510
00511 template<class DataType>
00512 void Signal<DataType>::_disconnect(Base_Slot<DataType>* slot)
00513 {
00514 Base_Slot_Iterator
00515 begin = connected_slots.begin(),
00516 end = connected_slots.end(),
00517 i;
00518
00519 for (i = begin; i != end; i++)
00520 if ((*i) == slot) {
00521 connected_slots.erase(i);
00522 break;
00523 }
00524 }
00525
00526
00527 template<class DataType>
00528 Base_Slot<DataType>::Base_Slot(const std::string slot_name)
00529 {
00530 set_name(slot_name);
00531 }
00532
00533 template<class DataType>
00534 void Base_Slot<DataType>::set_name(const std::string &slot_name)
00535 {
00536 name = slot_name;
00537 }
00538
00539 template<class DataType>
00540 Base_Slot<DataType>::~Base_Slot()
00541 {
00542
00543 Signal_Iterator
00544 begin = connected_signals.begin(),
00545 end = connected_signals.end(),
00546 i;
00547
00548 for (i = begin; i != end; i++)
00549 (*i)->_disconnect(this);
00550
00551 connected_signals.clear();
00552 }
00553
00554 template<class DataType>
00555 void Base_Slot<DataType>::_connect(Signal<DataType>* signal)
00556 {
00557 connected_signals.push_back(signal);
00558 }
00559
00560 template<class DataType>
00561 void Base_Slot<DataType>::_disconnect(Signal<DataType>* signal)
00562 {
00563
00564 Signal_Iterator
00565 begin = connected_signals.begin(),
00566 end = connected_signals.end(),
00567 i;
00568
00569 for (i = begin; i != end; i++)
00570 if ((*i) == signal) {
00571 connected_signals.erase(i);
00572 break;
00573 }
00574 }
00575
00576 template<class ObjectType, class DataType>
00577 Slot<ObjectType, DataType>::Slot(const std::string slot_name) : Base_Slot<DataType>(slot_name)
00578 {
00579 pm = NULL;
00580 po = NULL;
00581 }
00582
00583 template<class ObjectType, class DataType>
00584 Slot<ObjectType, DataType>::~Slot() {}
00585
00586 template<class ObjectType, class DataType>
00587 void Slot<ObjectType, DataType>::forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u))
00588 {
00589 pm = object_function_pointer;
00590 po = object_pointer;
00591 }
00592
00593
00594
00595
00596
00597
00598
00599 template<class ObjectType, class DataType>
00600 void Slot<ObjectType, DataType>::operator()(DataType signal)
00601 {
00602 if (pm&&po)
00603 (*po.*pm)(signal);
00604 }
00605
00607
00608 }
00609
00610 #endif // #ifndef SIGNAL_SLOT_H
00611