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