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