| Homepage | Demos | Overview | Downloads | Tutorials | Reference | Credits |
EventRouter.hGo to the documentation of this file.00001 //-*-c++-*- 00002 #ifndef INCLUDED_EventRouter_h 00003 #define INCLUDED_EventRouter_h 00004 00005 #include <vector> 00006 #include <list> 00007 #include <map> 00008 #include <algorithm> 00009 #include "EventListener.h" 00010 #include "EventTrapper.h" 00011 #include "Shared/get_time.h" 00012 #include "Shared/debuget.h" 00013 #include <iostream> 00014 00015 //! This class will handle distribution of events as well as management of timers 00016 /*! Classes must inherit from EventListener and/or EventTrapper in order to 00017 * receive events. 00018 * 00019 * Use the global @c ::erouter EventRouter to post and subscribe to 00020 * events, except if you are posting from within a MotionCommand, in 00021 * which case you should use MotionCommand::postEvent() so that it 00022 * will automatically be sent from the Motion process to the Main 00023 * process. 00024 * 00025 * When multiple listeners are subscribed, the order in which an event is 00026 * distributed among them looks like this: 00027 * -# "Specific" listeners: any listener which specifies a particular source id. 00028 * (It doesn't matter if they specify a type id or not.) 00029 * - older listeners get events before younger listeners 00030 * -# "General" listeners: those that subscribe to an entire generator 00031 * - older listeners get events before younger listeners 00032 * 00033 * ...but if you're relying on that ordering, there should be a cleaner 00034 * way to do whatever you're doing. 00035 * 00036 * If one behaviors unsubscribes another one during a processEvent(), 00037 * that behavior may still get the "current" event before the 00038 * unsubscription takes place. This is not a prescribed behavior, 00039 * and also should not be relied on one way or the other. 00040 * 00041 * Timer events are only sent to the generator which requested them. So if 00042 * EventListener @e A requests a timer with ID 0 at two second intervals, 00043 * and EventListener @e B requests a timer with ID 0 at three second intervals, 00044 * each will still only receive the timers they requested - no cross talk. 00045 * The timer generator is unique in this regard, which is why it is built in 00046 * as an integral component of the EventRouter. All other events are broadcast. 00047 * 00048 * If an EventListener/EventTrapper subscribes to the same event source multiple 00049 * times, it will receive multiple copies of the event. However, the first call 00050 * to removeListener for a source will remove all subscriptions to that source.\n 00051 * Example: EventListener @e A subscribes to (buttonEGID,*,*), and twice to 00052 * (buttonEGID,0,*). 00053 * - If button 0 is pressed, @e A will get three copies of the event. 00054 * - If button 1 is pressed, @e A will get one copy. 00055 * - If removeListener(&A,buttonEGID) is called, the (buttonEGID,*,*) is 00056 * removed, <em>as well as</em> both of (buttonEGID,0,*). 00057 * - If removeListener(&A,buttonEGID,0) is called, both of (buttonEGID,0,*) 00058 * are removed, but (buttonEGID,*,*) would be untouched. 00059 * 00060 * The buffered event distribution has not been tested thoroughly, 00061 * and should be considered deprecated. 00062 * 00063 * @see EventBase::EventGeneratorID_t for a complete listing of all generators, 00064 * as well as instructions on how to add new generators. 00065 */ 00066 class EventRouter : public EventListener { 00067 public: 00068 EventRouter(); //!< Constructs the router, #buffertime defaults to 1 00069 virtual ~EventRouter() { reset(); removeAllTimers(); } //!< just calls reset and removeAllTimers() 00070 void reset() { listeners.clear(); trappers.clear(); removeAllTimers(); } //!< erases all listeners, trappers and timers, resets EventRouter 00071 00072 void setBufferTime(unsigned int t) { buffertime=t; } /*!< @brief sets the time to wait between buffer clears, see EventRouter::buffertime. @param t time to wait between buffer clears @see buffertime */ 00073 unsigned int getBufferTime() { return buffertime; } /*!< @brief returns the time to wait between buffer clears, see EventRouter::buffertime. @return time to wait between buffer clears @see buffertime */ 00074 00075 //!@name Posting/Processing Events 00076 /*!@brief recommended to create and post an event using current buffer setting */ 00077 void postEvent(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid, unsigned int dur) { if(buffertime>0) events.push_back(new EventBase(egid,sid,etid,dur)); else processEvent(EventBase(egid,sid,etid,dur)); } 00078 void postEvent(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid, unsigned int dur, const std::string& n, float m) { if(buffertime>0) events.push_back(new EventBase(egid,sid,etid,dur,n,m)); else processEvent(EventBase(egid,sid,etid,dur,n,m)); } 00079 void postEvent(EventBase* e) { if(buffertime>0) events.push_back(e); else { processEvent(*e); delete e; } } 00080 00081 //! determines if timers need to be posted, and posts them if so. 00082 /*! Call this often to ensure accurate timers. Also, will clear event buffer before sending 00083 timer events in order to ensure correct ordering of event reception */ 00084 void processTimers(); 00085 void processEventBuffer(); //!< clears the event buffer, deletes events as it does so. 00086 void processEvent(const EventBase& e); //!< forces unbuffered - sends event *now*. Will clear the buffer first if needed to ensure proper event ordering 00087 //@} 00088 00089 //!@name Listener/Trapper Recall 00090 //! returns true if the specified listener/trapper would receive any events that match the specified criteria 00091 bool isListeningAny(EventListener* el, EventBase::EventGeneratorID_t egid) { return listeners.verifyMappingAny(el,egid); } 00092 bool isListeningAny(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { return listeners.verifyMappingAny(el,egid,sid); } 00093 bool isListeningAll(EventListener* el, EventBase::EventGeneratorID_t egid) { return listeners.verifyMappingAll(el,egid); } 00094 bool isListeningAll(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { return listeners.verifyMappingAll(el,egid,sid); } 00095 bool isListening(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { return listeners.verifyMapping(el,egid,sid,etid); } 00096 bool isListening(EventListener* el, const EventBase& e) { return listeners.verifyMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } 00097 bool isTrappingAny(EventTrapper* el, EventBase::EventGeneratorID_t egid) { return trappers.verifyMappingAny(el,egid); } 00098 bool isTrappingAny(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { return trappers.verifyMappingAny(el,egid,sid); } 00099 bool isTrappingAll(EventTrapper* el, EventBase::EventGeneratorID_t egid) { return trappers.verifyMappingAll(el,egid); } 00100 bool isTrappingAll(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { return trappers.verifyMappingAll(el,egid,sid); } 00101 bool isTrapping(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { return trappers.verifyMapping(el,egid,sid,etid); } 00102 bool isTrapping(EventTrapper* el, const EventBase& e) { return trappers.verifyMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } 00103 //@} 00104 00105 //!@name Listener/Trapper Detection 00106 /*!@brief <b>counts both listeners and trappers</b>, so generators can tell if it even needs to bother generating an event...*/ 00107 /* Generators can also subscribe to the EventBase::erouterEGID event stream if 00108 * they wish to be notified when they gain or lose listeners (particularly the 00109 * first or last).\n 00110 * ... if a tree falls in a forest, and there's no one around to see it, does 00111 * it make a sound?\n 00112 * ... if Vision sees a ball in an image, and there's no listeners, does it 00113 * make an event? ;) */ 00114 bool hasListeners(EventBase::EventGeneratorID_t egid) { return (egid==EventBase::timerEGID) ? timers.size()>0 : trappers.hasMapping(egid) || listeners.hasMapping(egid); } 00115 bool hasListeners(EventBase::EventGeneratorID_t egid, unsigned int sid) { return (egid==EventBase::timerEGID) ? timers.size()>0 : trappers.hasMapping(egid,sid) || listeners.hasMapping(egid,sid); } 00116 bool hasListeners(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { return (egid==EventBase::timerEGID) ? timers.size()>0 : trappers.hasMapping(egid,sid,etid) || listeners.hasMapping(egid,sid,etid); } 00117 bool hasListeners(const EventBase& e) { return (e.getGeneratorID()==EventBase::timerEGID) ? timers.size()>0 : hasListeners(e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } 00118 //@} 00119 00120 //!@name Timer Management 00121 void addTimer(EventListener* el, unsigned int sid, unsigned int delay, bool repeat=true); //!< adds a timer if it doesn't exist, or resets the timer if it already exists. 00122 void addTimer(EventListener* el, const EventBase& e, bool repeat=true) { addTimer(el,e.getSourceID(),e.getDuration(),repeat); } //!< calls the other addTimer() with the event's source id and duration, doesn't check to see if the generator is timerEGID 00123 void removeTimer(EventListener* el); //!< clears all pending timers for listener @a el 00124 void removeTimer(EventListener* el, unsigned int sid); //!< clears any pending timers with source id @a sid for listener @a el 00125 void removeAllTimers(); //!< clears all timers for all listeners 00126 //@} 00127 00128 //!@name Listener Management 00129 //! Adds a listener for all events from a given event generator 00130 void addListener(EventListener* el, EventBase::EventGeneratorID_t egid); 00131 void addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< Adds a listener for all types from a specific source and generator 00132 void addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< Adds a listener for a specific source id and type from a given event generator 00133 //! Adds a listener for a specific source id and type from a given event generator, adding a Timer event will invoke addTimer(@a el, @a e.getSourceID(), @a e.getDuration(), @c true) 00134 void addListener(EventListener* el, const EventBase& e); 00135 00136 //! stops sending ALL events to the listener, including timers 00137 void removeListener(EventListener* el); 00138 //! stops sending specified events from the generator to the listener. 00139 void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid); 00140 void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< stops sending specified events from the generator to the listener. 00141 void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< stops sending specified events from the generator to the listener. 00142 //! stops sending specified events from the generator to the listener. If a timer is passed it will invoke removeTimer(@a el, @a e.getSourceID()) 00143 void removeListener(EventListener* el, const EventBase& e); 00144 00145 /*! @deprecated use removeListener(EventListener* el) instead 00146 * @brief deprecated, you should call removeListener(EventListener* el) instead */ 00147 void forgetListener(EventListener* el) __attribute__((deprecated)); 00148 //@} 00149 00150 //!@name Trapper Management 00151 //! Adds a trapper for a specific source id and type from a given event generator 00152 /*! Note that since timers are not broadcast, they cannot be trapped. Only the EventListener which requested the timer will receive that timer. */ 00153 void addTrapper(EventTrapper* el, const EventBase& e); 00154 void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid); //!< Adds a trapper for all events from a given event generator 00155 void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< Adds a trapper for all types from a specific source and generator 00156 void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< Adds a trapper for a specific source id and type from a given event generator 00157 00158 void addTrapper(EventTrapper* el); //!< adds a trapper for ALL events 00159 00160 //! stops sending specified events from the generator to the trapper. 00161 void removeTrapper(EventTrapper* el, const EventBase& e); 00162 void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid); //!< stops sending specified events from the generator to the trapper. 00163 void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< stops sending specified events from the generator to the trapper. 00164 void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< stops sending specified events from the generator to the trapper. 00165 00166 void removeTrapper(EventTrapper* el); //!< stops sending ALL events to the trapper 00167 //@} 00168 00169 protected: 00170 void doSendBuffer(); //!< does the work of clearing the buffer (calls doSendEvent() ) 00171 00172 //! does the work of sending an event 00173 /*! Be aware this is an O(n^2) where n is the number of listeners for a particular event. 00174 * This is because after each call to processEvent, the list of listeners could have changed 00175 * so each listener much be verified before it is sent an event. New listeners won't get the 00176 * current event, but neither should listeners which have just be removed */ 00177 void doSendEvent(const EventBase& e); 00178 00179 //! Contains all the information needed to maintain a timer by the EventRouter 00180 struct TimerEntry { 00181 //! constructors an entry using the given value for next - useful for with TimerEntryPtrCmp 00182 explicit TimerEntry(unsigned int nxt) : el(NULL), sid(0), delay(0), next(nxt), repeat(false) {} 00183 //! constructs with the given values, sets next field automatically; see next 00184 TimerEntry(EventListener* e, unsigned int s, unsigned int d, bool r) : el(e), sid(s), delay(d), next(get_time()+delay), repeat(r) {} 00185 //! just does the default, i'm just being explicit since there's a pointer (no deep copy!) 00186 TimerEntry(const TimerEntry& t) : el(t.el), sid(t.sid), delay(t.delay), next(t.next), repeat(t.repeat) {} 00187 //! just does the default, i'm just being explicit since there's a pointer (no deep copy!) 00188 TimerEntry operator=(const TimerEntry& t) { el=t.el; sid=t.sid; delay=t.delay; next=t.next; repeat=t.repeat; return *this; } 00189 //! will reset timer 00190 /*! @param d the time from now when the timer should go off (in milliseconds) 00191 * @param r true if the timer should automatically repeat */ 00192 void Set(unsigned int d, bool r) { delay=d; repeat=r; next=get_time()+delay; } 00193 EventListener* el; //!< the listener to fire at 00194 unsigned int sid; //!< the source id to fire with 00195 unsigned int delay; //!< the delay until firing 00196 unsigned int next; //!< the time at which this timer will go off next 00197 bool repeat; //!< if true, will reset after firing, else will be deleted 00198 }; 00199 /*! @brief Used by STL to sort the timer list in order of activation time 00200 * @see EventRouter::timers */ 00201 class TimerEntryPtrCmp { 00202 public: 00203 //! Used by STL to sort the timer list in order of activation time; see timers 00204 /*! Since we remove NULLs before sorting, shouldn't need to check here (and I want to know if i'm wrong) 00205 * @return (a->next<b->next) */ 00206 bool operator()(const TimerEntry* const a, const TimerEntry* const b) const { return (a->next<b->next); } 00207 }; 00208 typedef std::vector<TimerEntry*>::iterator timer_it_t; //!< makes code more readable 00209 std::vector<TimerEntry*> timers; //!< the list of timer entries being maintained, kept sorted by time they go active 00210 00211 //! just for debugging 00212 void chkTimers() { 00213 unsigned int last=0; 00214 for(timer_it_t it=timers.begin(); it!=timers.end(); it++) { 00215 if(last>(*it)->next) { 00216 dispTimers(); 00217 return; 00218 } 00219 last=(*it)->next; 00220 } 00221 } 00222 //! just for debugging 00223 void dispTimers() { 00224 std::cout << "out of order timers " << get_time() << " :\t"; 00225 unsigned int last=0; 00226 for(timer_it_t it=timers.begin(); it!=timers.end(); it++) { 00227 if(last>(*it)->next) 00228 std::cout << "##"; 00229 std::cout << (last=(*it)->next) << '\t'; 00230 } 00231 std::cout << std::endl; 00232 } 00233 00234 std::vector<EventBase*> events; //!< used to store buffered events 00235 bool doSendBufferLock; //!< in case of recursive calls to processEventBuffer()/doSendBuffer() 00236 unsigned int lastBufClear; //!< time of last event buffer clear 00237 unsigned int buffertime; //!< The time between clearings of the buffer 00238 /*!< <li>0 will not use the buffer, events are routed upon posting 00239 * <li>1 will clear the buffer at next call to processTimers() or processEventBuffer() 00240 * <li>a larger value will cause a delay of that number of milliseconds since the last clearing */ 00241 00242 //! Does the actual storage of the mapping between EventBase's and the EventListeners/EventTrappers who should receive them 00243 /*! Actually only stores void*'s, so it's more general than just Listeners or Trappers */ 00244 class EventMapper { 00245 public: 00246 //! constructor 00247 EventMapper(); 00248 00249 void addMapping(void* el, EventBase::EventGeneratorID_t egid) { allevents[egid].push_back(el); } //!< Adds a listener for all events from a given event generator 00250 void addMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< Adds a listener for a specific source id and type from a given event generator 00251 00252 //! Removes a listener for all events from a given event generator, returns true if something was actually removed 00253 /*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */ 00254 bool removeMapping(void* el, EventBase::EventGeneratorID_t egid); 00255 00256 //! Removes a listener for a specific source id and type from a given event generator, returns true if something was actually removed 00257 /*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */ 00258 bool removeMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); 00259 00260 void clean(); //!<removes empty data structures for all event generators 00261 void clean(EventBase::EventGeneratorID_t egid); //!< removes empty data structures associated with a single event generator 00262 void clear(); //!<Resets the mapping 00263 00264 //@{ 00265 //! so stuff can tell if it even needs to bother generating an event... 00266 /*! ... if a tree falls in a forest, and there's no one around to see it, does it make a sound?\n 00267 ... if Vision sees a ball in an image, and there's no listeners, does it make an event? ;) \n 00268 @return true if it has any listeners, false otherwise */ 00269 bool hasMapping(EventBase::EventGeneratorID_t egid); 00270 bool hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid); 00271 bool hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); 00272 //@} 00273 00274 //! builds a list of all listeners which should receive the event, templated to typecast the pointers for you 00275 /*! @param e the key event 00276 * @param listeners upon return, the resulting list of listeners @a e maps to\n 00277 * @a listeners is not cleared prior to building, new listeners are pushed on end\n 00278 * Results are in the order: all specific matches first, all generator listeners second, in order they were added to the EventMapper.*/ 00279 template<class T> 00280 void getMapping(const EventBase& e, std::vector<T*>& listeners); 00281 00282 //! Used to make sure that the specified listener exists for the given event 00283 /*! This is needed because after we call processEvent on a lister, we can't assume 00284 * that no other listeners have been modified - one listener could cause another 00285 * to turn off. If that has happened, we shouldn't send the event, even if it 00286 * was in the queue originally. */ 00287 bool verifyMapping(void * listener, const EventBase& e) { return verifyMapping(listener,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } 00288 //! Used to make sure that the specified listener exists for the given event 00289 /*! This is needed because after we call processEvent on a lister, we can't assume 00290 * that no other listeners have been modified - one listener could cause another 00291 * to turn off. If that has happened, we shouldn't send the event, even if it 00292 * was in the queue originally. */ 00293 bool verifyMapping(void * listener, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); 00294 00295 //! Needed to complete EventRouter::isListening suite 00296 /*! Only checks #allevents */ 00297 bool verifyMappingAll(void * listener, EventBase::EventGeneratorID_t egid); 00298 //! Needed to complete EventRouter::isListening suite 00299 /*! Checks both #allevents and #filtered events */ 00300 bool verifyMappingAny(void * listener, EventBase::EventGeneratorID_t egid); 00301 00302 //! Needed to complete EventRouter::isListening suite 00303 /*! Checks both #allevents and #filteredevents, must be found in all */ 00304 bool verifyMappingAll(void * listener, EventBase::EventGeneratorID_t egid, unsigned int sid); 00305 //! Needed to complete EventRouter::isListening suite 00306 /*! Checks both #allevents and #filteredevents, can be found in either */ 00307 bool verifyMappingAny(void * listener, EventBase::EventGeneratorID_t egid, unsigned int sid); 00308 00309 protected: 00310 //! a mapping from source IDs (unsigned ints), each to a vector of pointers to listeners 00311 /*! main use in filteredevents @see filteredevents */ 00312 typedef std::map<unsigned int,std::vector<void*>,std::less<unsigned int> > SIDtoListenerVectorMap_t; 00313 00314 //! an array of vectors of pointers to listeners... in other words, a vector of listener pointers for each generator 00315 std::vector<void*> allevents[EventBase::numEGIDs]; 00316 //! not for the faint of heart: a matrix of mappings to vectors of pointers to listeners 00317 SIDtoListenerVectorMap_t* filteredevents[EventBase::numEGIDs][EventBase::numETIDs]; 00318 00319 private: 00320 EventMapper(const EventMapper&); //!< this shouldn't be called... 00321 EventMapper operator=(const EventMapper&); //!< this shouldn't be called... 00322 }; 00323 00324 EventMapper trappers; //!< A mapping of which EventTrapper's should get a chance to trap the event 00325 EventMapper listeners; //!< A mapping of which EventListener's should receive events 00326 00327 }; 00328 00329 //! a global router for cross communication, probably the most common usage, although perhaps there may be times you'd rather have multiple event routers for smaller sections 00330 extern EventRouter * erouter; 00331 00332 /*! @file 00333 * @brief Describes EventRouter class, for distribution and trapping of events to listeners 00334 * @author ejt (Creator) 00335 * 00336 * $Author: ejt $ 00337 * $Name: tekkotsu-2_3 $ 00338 * $Revision: 1.18 $ 00339 * $State: Exp $ 00340 * $Date: 2005/01/27 20:15:32 $ 00341 */ 00342 00343 #endif |
|
Tekkotsu v2.3 |
Generated Sat Jan 29 02:25:21 2005 by Doxygen 1.4.0 |