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 // Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = true); 00122 00124 ~Signal(); 00125 00127 void connect(Base_Slot<DataType>* slot); 00128 00130 void disconnect(Base_Slot<DataType>* slot = NULL); 00131 00132 // Base_Event* arm(const Ttype delta_time, DataType signal); // Signal will trigger in 'delta_time' time units carrying data signal. 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 // virtual void exec(DataType signal) = 0; 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 //void exec(DataType signal); 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; // TODO: Added this myself. Didn't work otherwise. 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; // Used internally 00370 Slot<TTimer, double> slot; // Used internally 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) // Cancel a possibly pending event since we are about to die! 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) { // Multiple connections is meaningless. 00434 connected_slots.push_back(slot); 00435 slot->_connect(this); // Needed if a connected slot is deleted during run time. 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 // Signal will trigger in 'delta_time' time units. 00462 if (single) { // We are operating in single-shot mode. 00463 if (armed) { // Cancel and schedule again with the new 'delta_time'. 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 { // Continious mode (cancel() has no effect). 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++) { // Execute all the functions of the connected slots. 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 { // Notify all signals connect that we are being deleted ... 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 { // A signal is being connected to us. 00557 connected_signals.push_back(signal); 00558 } 00559 00560 template<class DataType> 00561 void Base_Slot<DataType>::_disconnect(Signal<DataType>* signal) 00562 { // A signal is being disconnected from us. 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 // template<class ObjectType, class DataType> 00594 // void Slot<ObjectType, DataType>::exec(DataType signal){ 00595 // if(pm&&po) 00596 // (*po.*pm)(signal); 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 } // namespace itpp 00609 00610 #endif // #ifndef SIGNAL_SLOT_H 00611
Generated on Sat Jul 9 2011 15:21:32 for IT++ by Doxygen 1.7.4