00001 00030 #ifndef SIGNAL_SLOT_H 00031 #define SIGNAL_SLOT_H 00032 00033 #include <itpp/protocol/events.h> 00034 #include <list> 00035 #include <iostream> 00036 00037 00038 namespace itpp { 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 public: 00115 friend class Base_Slot<DataType>; 00116 00118 Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = false); 00119 00120 // Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = true); 00121 00123 ~Signal(); 00124 00126 void connect(Base_Slot<DataType>* slot); 00127 00129 void disconnect(Base_Slot<DataType>* slot = NULL); 00130 00131 // Base_Event* arm(const Ttype delta_time, DataType signal); // Signal will trigger in 'delta_time' time units carrying data signal. 00132 00133 00135 Base_Event* operator()(DataType signal, const Ttype delta_time = 0); 00136 00138 void cancel(); 00139 00141 void set_name(const std::string &signal_name); 00142 00144 void set_debug(const bool enable_debug = true); 00145 00147 void trigger(DataType u); 00148 00149 protected: 00151 typedef typename std::list<Base_Slot<DataType>*, std::allocator< Base_Slot<DataType>* > >::iterator Base_Slot_Iterator; 00153 void _disconnect(Base_Slot<DataType>* slot); 00155 std::list<Base_Slot<DataType>*, std::allocator<Base_Slot<DataType>* > > connected_slots; 00157 std::string name; 00158 00159 private: 00160 bool armed; 00161 bool debug; 00162 bool single; 00163 Data_Event<Signal, DataType> *e; 00164 }; 00165 00166 00171 template<class DataType> 00172 class Base_Slot{ 00173 public: 00174 friend class Signal<DataType>; 00175 00177 Base_Slot(const std::string slot_name = "Unamed Base_Slot"); 00178 00180 virtual ~Base_Slot(); 00181 00183 void set_name(const std::string &slot_name); 00184 00186 virtual void operator()(DataType signal) = 0; 00187 00188 protected: 00189 // virtual void exec(DataType signal) = 0; 00191 typedef typename std::list<Signal<DataType>*, std::allocator< Signal<DataType>* > >::iterator Signal_Iterator; 00193 std::string name; 00195 void _connect(Signal<DataType>* signal); 00197 void _disconnect(Signal<DataType>* signal); 00199 std::list<Signal<DataType>*, std::allocator<Signal<DataType>* > > connected_signals; 00200 }; 00201 00206 template<class ObjectType, class DataType> 00207 class Slot : public Base_Slot<DataType> { 00208 public: 00210 Slot(const std::string _name = "Unamed Slot"); 00211 00213 void forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u)); 00214 00216 ~Slot(); 00217 00219 void operator()(DataType u); 00220 00221 //void exec(DataType signal); 00222 00223 private: 00224 ObjectType *po; 00225 void(ObjectType::*pm)(DataType signal); 00226 }; 00227 00228 00232 template<class ObjectType, class DataType> 00233 class ATimer { 00234 public: 00236 ATimer(const std::string Name = "Unamed ATimer") { 00237 time_out_signal = new Signal<DataType>(Name, true); 00238 time_out_slot = new Slot<ObjectType, DataType>(Name); 00239 time_out_signal->connect(time_out_slot); 00240 set_name(Name); 00241 } 00242 00244 void forward(ObjectType *po, void(ObjectType::*pm)(DataType u)) { time_out_slot->forward(po, pm); } 00245 00247 void set(DataType u, const Ttype delta_t) { 00248 time_out_signal->operator()(u, delta_t); 00249 } 00250 00252 void cancel() { time_out_signal->cancel(); } 00253 00255 void set_name(const std::string Name) { 00256 name = Name; 00257 time_out_signal->set_name(name); 00258 time_out_slot->set_name(name); 00259 } 00260 00261 protected: 00263 std::string name; 00264 00265 private: 00266 Signal<DataType> *time_out_signal; 00267 Slot<ObjectType, DataType> *time_out_slot; 00268 }; 00269 00270 00271 00280 template <class THandler> 00281 class TTimer { 00282 public: 00284 TTimer(THandler & handler, void (THandler::*handlerFunction) (Ttype time)) : 00285 signal("timer_signal", true) 00286 { 00287 fPending = false; 00288 fExpirationTime = 0; 00289 00290 registered_handler = &handler; 00291 registered_handler_function = handlerFunction; 00292 00293 slot.forward(this, &TTimer<THandler>::HandleProcessEvent); 00294 slot.set_name("timer_slot"); 00295 signal.set_debug(false); 00296 signal.connect(&slot); 00297 } 00298 00300 virtual ~TTimer() { 00301 if (fPending) 00302 signal.cancel(); 00303 } 00304 00306 void Set(Ttype time, bool relative = true) { 00307 if (fPending) 00308 signal.cancel(); 00309 00310 fPending = true; 00311 double current_time = Event_Queue::now(); 00312 double delta_time; 00313 if (relative) { 00314 fExpirationTime = current_time + time; 00315 delta_time = time; 00316 } else { 00317 fExpirationTime = time; 00318 delta_time = time - current_time; 00319 } 00320 signal(fExpirationTime, delta_time); 00321 } 00322 00324 void Reset() { 00325 if (fPending) { 00326 signal.cancel(); 00327 fPending = false; // TODO: Added this myself. Didn't work otherwise. 00328 } 00329 } 00330 00332 Ttype ExpirationTime() const 00333 { 00334 it_assert(fPending, "TTimer<>::ExpirationTime: timer not set"); 00335 return fExpirationTime; 00336 } 00337 00339 bool IsPending() const { return fPending; } 00340 00341 protected: 00343 virtual void HandleProcessEvent (Ttype currentTime) { 00344 fPending = false; 00345 (*registered_handler.*registered_handler_function)(currentTime); 00346 } 00347 00349 virtual void HandleCancelEvent (Ttype) { 00350 if (fPending) 00351 signal.cancel(); 00352 00353 fPending = false; 00354 } 00355 00357 bool fPending; 00359 Ttype fExpirationTime; 00360 00361 private: 00362 THandler *registered_handler; 00363 void(THandler::*registered_handler_function)(Ttype expiry_time); 00364 00365 Signal<double> signal; // Used internally 00366 Slot<TTimer, double> slot; // Used internally 00367 }; 00368 00369 00370 00371 00372 00373 00374 // ----------------------------------------------------------------------------------------------- 00375 00376 template<class DataType> 00377 Signal<DataType>::Signal(const std::string signal_name, const bool single_shot, const bool enable_debug) 00378 { 00379 armed = false; 00380 e = NULL; 00381 single = single_shot; 00382 set_name(signal_name); 00383 set_debug(enable_debug); 00384 } 00385 00386 template<class DataType> 00387 Signal<DataType>::~Signal() 00388 { 00389 Base_Slot_Iterator 00390 begin = connected_slots.begin(), 00391 end = connected_slots.end(), 00392 i; 00393 00394 for(i=begin; i!=end; i++) 00395 (*i)->_disconnect(this); 00396 00397 connected_slots.clear(); 00398 00399 if(e!=NULL) // Cancel a possibly pending event since we are about to die! 00400 e->cancel(); 00401 } 00402 00403 template<class DataType> 00404 void Signal<DataType>::set_name(const std::string &signal_name) 00405 { 00406 name = signal_name; 00407 } 00408 00409 template<class DataType> 00410 void Signal<DataType>::set_debug(const bool enable_debug) 00411 { 00412 debug = enable_debug; 00413 } 00414 00415 template<class DataType> 00416 void Signal<DataType>::connect(Base_Slot<DataType>* slot) 00417 { 00418 Base_Slot_Iterator 00419 begin = connected_slots.begin(), 00420 end = connected_slots.end(), 00421 i; 00422 00423 bool is_already_connected = false; 00424 00425 for(i=begin; i!=end; i++) 00426 if((*i) == slot) 00427 is_already_connected = true; 00428 00429 if(!is_already_connected) { // Multiple connections is meaningless. 00430 connected_slots.push_back(slot); 00431 slot->_connect(this); // Needed if a connected slot is deleted during run time. 00432 } else { 00433 std::cout<<"Signal '"<< name <<"' and Slot '"<< slot->name<<"' are already connected. Multiple connections have no effect!"<< std::endl; 00434 } 00435 } 00436 00437 template<class DataType> 00438 void Signal<DataType>::disconnect(Base_Slot<DataType>* slot) 00439 { 00440 Base_Slot_Iterator 00441 begin = connected_slots.begin(), 00442 end = connected_slots.end(), 00443 i; 00444 00445 for(i=begin; i!=end; i++) 00446 if((*i) == slot) { 00447 (*i)->_disconnect(this); 00448 connected_slots.erase(i); 00449 break; 00450 } 00451 } 00452 00453 template<class DataType> 00454 Base_Event* Signal<DataType>::operator()(DataType signal, const Ttype delta_time) 00455 { 00456 // Signal will trigger in 'delta_time' time units. 00457 if(single){ // We are operating in single-shot mode. 00458 if(armed){ // Cancel and schedule again with the new 'delta_time'. 00459 if(debug) 00460 std::cout<<"Warning: Changing time for Signal '"<<name<<"'."<< std::endl; 00461 cancel(); 00462 operator()(signal, delta_time); 00463 } else { 00464 e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time); 00465 armed = true; 00466 Event_Queue::add(e); 00467 } 00468 } else { // Continious mode (cancel() has no effect). 00469 e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time); 00470 armed = true; 00471 Event_Queue::add(e); 00472 } 00473 return e; 00474 } 00475 00476 template<class DataType> 00477 void Signal<DataType>::cancel() 00478 { 00479 if(armed&&single){ 00480 e->cancel(); 00481 e = NULL; 00482 armed = false; 00483 } 00484 } 00485 00486 00487 template<class DataType> 00488 void Signal<DataType>::trigger(DataType u) 00489 { 00490 armed = false; 00491 e = NULL; 00492 Base_Slot_Iterator 00493 begin = connected_slots.begin(), 00494 end = connected_slots.end(), 00495 i; 00496 00497 for(i=begin; i!=end; i++) { // Execute all the functions of the connected slots. 00498 if(debug) 00499 std::cout << "Time = " << Event_Queue::now() << ". Signal '" << name << "' was sent to Slot '" << (*i)->name<< "'." << std::endl; 00500 (*i)->operator()(u); 00501 } 00502 } 00503 00504 template<class DataType> 00505 void Signal<DataType>::_disconnect(Base_Slot<DataType>* slot) 00506 { 00507 Base_Slot_Iterator 00508 begin = connected_slots.begin(), 00509 end = connected_slots.end(), 00510 i; 00511 00512 for(i=begin; i!=end; i++) 00513 if((*i) == slot) { 00514 connected_slots.erase(i); 00515 break; 00516 } 00517 } 00518 00519 00520 template<class DataType> 00521 Base_Slot<DataType>::Base_Slot(const std::string slot_name) 00522 { 00523 set_name(slot_name); 00524 } 00525 00526 template<class DataType> 00527 void Base_Slot<DataType>::set_name(const std::string &slot_name) 00528 { 00529 name = slot_name; 00530 } 00531 00532 template<class DataType> 00533 Base_Slot<DataType>::~Base_Slot() 00534 { // Notify all signals connect that we are being deleted ... 00535 00536 Signal_Iterator 00537 begin = connected_signals.begin(), 00538 end = connected_signals.end(), 00539 i; 00540 00541 for(i=begin; i!=end; i++) 00542 (*i)->_disconnect(this); 00543 00544 connected_signals.clear(); 00545 } 00546 00547 template<class DataType> 00548 void Base_Slot<DataType>::_connect(Signal<DataType>* signal) 00549 { // A signal is being connected to us. 00550 connected_signals.push_back(signal); 00551 } 00552 00553 template<class DataType> 00554 void Base_Slot<DataType>::_disconnect(Signal<DataType>* signal) 00555 { // A signal is being disconnected from us. 00556 00557 Signal_Iterator 00558 begin = connected_signals.begin(), 00559 end = connected_signals.end(), 00560 i; 00561 00562 for(i=begin; i!=end; i++) 00563 if((*i) == signal) { 00564 connected_signals.erase(i); 00565 break; 00566 } 00567 } 00568 00569 template<class ObjectType, class DataType> 00570 Slot<ObjectType, DataType>::Slot(const std::string slot_name) : Base_Slot<DataType>(slot_name) 00571 { 00572 pm = NULL; 00573 po = NULL; 00574 } 00575 00576 template<class ObjectType, class DataType> 00577 Slot<ObjectType, DataType>::~Slot(){} 00578 00579 template<class ObjectType, class DataType> 00580 void Slot<ObjectType, DataType>::forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u)) 00581 { 00582 pm = object_function_pointer; 00583 po = object_pointer; 00584 } 00585 00586 // template<class ObjectType, class DataType> 00587 // void Slot<ObjectType, DataType>::exec(DataType signal){ 00588 // if(pm&&po) 00589 // (*po.*pm)(signal); 00590 // } 00591 00592 template<class ObjectType, class DataType> 00593 void Slot<ObjectType, DataType>::operator()(DataType signal) 00594 { 00595 if(pm&&po) 00596 (*po.*pm)(signal); 00597 } 00598 00600 00601 } // namespace itpp 00602 00603 #endif // #ifndef SIGNAL_SLOT_H 00604
Generated on Sat Apr 19 11:01:27 2008 for IT++ by Doxygen 1.5.5