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.\n 00018 * Use the global @c ::erouter EventRouter to post and subscribe to events\n 00019 * 00020 * When multiple listeners are subscribed, the order in which an event is 00021 * distributed among them looks like this: 00022 * -# "Specific" listeners: any listener which specifies a particular source id. 00023 * (It doesn't matter if they specify a type id or not.) 00024 * - older listeners get events before younger listeners 00025 * -# "General" listeners: those that subscribe to an entire generator 00026 * - older listeners get events before younger listeners 00027 * 00028 * ...but if you're relying on that ordering, there should be a cleaner 00029 * way to do whatever you're doing. 00030 * 00031 * If one behaviors unsubscribes another one during a processEvent(), that 00032 * behavior will still get the "current" event before the unsubscription 00033 * takes place. 00034 * 00035 * Buffering events has not been tested thoroughly... 00036 * 00037 * @see EventBase::EventGeneratorID_t for a complete listing of all generators, 00038 * as well as instructions on how to add new generators. 00039 */ 00040 class EventRouter : public EventListener { 00041 public: 00042 EventRouter(); //!< Constructs the router, #buffertime defaults to 1 00043 virtual ~EventRouter() { reset(); removeAllTimers(); } //!< just calls reset and removeAllTimers() 00044 void reset() { listeners.clear(); trappers.clear(); removeAllTimers(); } //!< erases all listeners, trappers and timers, resets EventRouter 00045 00046 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 */ 00047 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 */ 00048 00049 //!@name Posting/Processing Events 00050 /*!@brief recommended to create and post an event using current buffer setting */ 00051 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)); } 00052 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)); } 00053 void postEvent(EventBase* e) { if(buffertime>0) events.push_back(e); else { processEvent(*e); delete e; } } 00054 00055 //! determines if timers need to be posted, and posts them if so. 00056 /*! Call this often to ensure accurate timers. Also, will clear event buffer before sending 00057 timer events in order to ensure correct ordering of event reception */ 00058 void processTimers(); 00059 void processEventBuffer(); //!< clears the event buffer, deletes events as it does so. 00060 void processEvent(const EventBase& e); //!< forces unbuffered - sends event *now*. Will clear the buffer first if needed to ensure proper event ordering 00061 //@} 00062 00063 //!@name Listener Detection 00064 /*!@brief <b>counts both listeners and trappers</b>, so stuff can tell if it even needs to bother generating an event...*/ 00065 /* ... if a tree falls in a forest, and there's no one around to see it, does it make a sound?\n 00066 ... if Vision sees a ball in an image, and there's no listeners, does it make an event? ;) */ 00067 bool hasListeners(EventBase::EventGeneratorID_t egid) { return trappers.hasMapping(egid) || listeners.hasMapping(egid); } 00068 bool hasListeners(EventBase::EventGeneratorID_t egid, unsigned int sid) { return trappers.hasMapping(egid,sid) || listeners.hasMapping(egid,sid); } 00069 bool hasListeners(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { return trappers.hasMapping(egid,sid,etid) || listeners.hasMapping(egid,sid,etid); } 00070 //@} 00071 00072 //!@name Timer Management 00073 void addTimer(EventListener* el, unsigned int sid, unsigned int delay, bool repeat=true); //!< adds a timer or sets a timer if it doesn't already exist. 00074 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 00075 void removeTimer(EventListener* el); //!< clears all pending timers for listener @a el 00076 void removeTimer(EventListener* el, unsigned int sid); //!< clears any pending timers with source id @a sid for listener @a el 00077 void removeAllTimers(); //!< clears all timers for all listeners 00078 //@} 00079 00080 //!@name Listener Management 00081 void addListener(EventListener* el, const EventBase& e); //!< 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) 00082 void addListener(EventListener* el, EventBase::EventGeneratorID_t egid); //!< Adds a listener for all events from a given event generator 00083 void addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< Adds a listener for all types from a specific source and generator 00084 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 00085 00086 //! stops sending specified events from the generator to the listener. If a timer is passed it will invoke removeTimer(@a el, @a e.getSourceID()) 00087 void removeListener(EventListener* el, const EventBase& e); 00088 void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid) { listeners.removeMapping(el,egid); listeners.clean(); } //!< stops sending specified events from the generator to the listener. 00089 void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { for(unsigned int et=0; et<EventBase::numETIDs; et++) listeners.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et); listeners.clean(); } //!< stops sending specified events from the generator to the listener. 00090 void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { listeners.removeMapping(el,egid,sid,etid); listeners.clean(); } //!< stops sending specified events from the generator to the listener. 00091 00092 void removeListener(EventListener* el) { for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) listeners.removeMapping(el,(EventBase::EventGeneratorID_t)eg); listeners.clean(); } //!< stops sending ALL events to the listener 00093 void forgetListener(EventListener* el) { removeTimer(el); removeListener(el); } //!< clears timers and removes listener from all events 00094 //@} 00095 00096 //!@name Trapper Management 00097 void addTrapper(EventTrapper* el, const EventBase& e) { trappers.addMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } //!< Adds a trapper for a specific source id and type from a given event generator 00098 void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid) { trappers.addMapping(el,egid); } //!< Adds a trapper for all events from a given event generator 00099 void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { for(unsigned int et=0; et<EventBase::numETIDs; et++) trappers.addMapping(el,egid,sid,(EventBase::EventTypeID_t)et); } //!< Adds a trapper for all types from a specific source and generator 00100 void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { trappers.addMapping(el,egid,sid,etid); } //!< Adds a trapper for a specific source id and type from a given event generator 00101 00102 void addTrapper(EventTrapper* el) { for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) trappers.addMapping(el,(EventBase::EventGeneratorID_t)eg); } //!< adds a trapper for ALL events 00103 00104 //! stops sending specified events from the generator to the trapper. 00105 void removeTrapper(EventTrapper* el, const EventBase& e) { trappers.removeMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); trappers.clean(); } 00106 void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid) { trappers.removeMapping(el,egid); trappers.clean(); } //!< stops sending specified events from the generator to the trapper. 00107 void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { for(unsigned int et=0; et<EventBase::numETIDs; et++) trappers.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et); trappers.clean(); } //!< stops sending specified events from the generator to the trapper. 00108 void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { trappers.removeMapping(el,egid,sid,etid); trappers.clean(); } //!< stops sending specified events from the generator to the trapper. 00109 00110 void removeTrapper(EventTrapper* el) { for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) trappers.removeMapping(el,(EventBase::EventGeneratorID_t)eg); trappers.clean(); } //!< stops sending ALL events to the trapper 00111 //@} 00112 00113 protected: 00114 void doSendBuffer(); //!< does the work of clearing the buffer (calls doSendEvent() ) 00115 00116 //! does the work of sending an event 00117 /*! Be aware this is an O(n^2) where n is the number of listeners for a particular event. 00118 * This is because after each call to processEvent, the list of listeners could have changed 00119 * so each listener much be verified before it is sent an event. New listeners won't get the 00120 * current event, but neither should listeners which have just be removed */ 00121 void doSendEvent(const EventBase& e); 00122 00123 //! Contains all the information needed to maintain a timer by the EventRouter 00124 struct TimerEntry { 00125 //! constructors an entry using the given value for next - useful for with TimerEntryPtrCmp 00126 explicit TimerEntry(unsigned int nxt) : el(NULL), sid(0), delay(0), next(nxt), repeat(false) {} 00127 //! constructs with the given values, sets next field automatically; see next 00128 TimerEntry(EventListener* e, unsigned int s, unsigned int d, bool r) : el(e), sid(s), delay(d), next(get_time()+delay), repeat(r) {} 00129 //! just does the default, i'm just being explicit since there's a pointer (no deep copy!) 00130 TimerEntry(const TimerEntry& t) : el(t.el), sid(t.sid), delay(t.delay), next(t.next), repeat(t.repeat) {} 00131 //! just does the default, i'm just being explicit since there's a pointer (no deep copy!) 00132 TimerEntry operator=(const TimerEntry& t) { el=t.el; sid=t.sid; delay=t.delay; next=t.next; repeat=t.repeat; return *this; } 00133 //! will reset timer 00134 /*! @param d the time from now when the timer should go off (in milliseconds) 00135 * @param r true if the timer should automatically repeat */ 00136 void Set(unsigned int d, bool r) { delay=d; repeat=r; next=get_time()+delay; } 00137 EventListener* el; //!< the listener to fire at 00138 unsigned int sid; //!< the source id to fire with 00139 unsigned int delay; //!< the delay until firing 00140 unsigned int next; //!< the time at which this timer will go off next 00141 bool repeat; //!< if true, will reset after firing, else will be deleted 00142 }; 00143 /*! @brief Used by STL to sort the timer list in order of activation time 00144 * @see EventRouter::timers */ 00145 class TimerEntryPtrCmp { 00146 public: 00147 //! Used by STL to sort the timer list in order of activation time; see timers 00148 /*! Since we remove NULLs before sorting, shouldn't need to check here (and I want to know if i'm wrong) 00149 * @return (a->next<b->next) */ 00150 bool operator()(const TimerEntry* const a, const TimerEntry* const b) const { return (a->next<b->next); } 00151 }; 00152 typedef std::vector<TimerEntry*>::iterator timer_it_t; //!< makes code more readable 00153 std::vector<TimerEntry*> timers; //!< the list of timer entries being maintained, kept sorted by time they go active 00154 00155 //! just for debugging 00156 void chkTimers() { 00157 unsigned int last=0; 00158 for(timer_it_t it=timers.begin(); it!=timers.end(); it++) { 00159 if(last>(*it)->next) { 00160 dispTimers(); 00161 return; 00162 } 00163 last=(*it)->next; 00164 } 00165 } 00166 //! just for debugging 00167 void dispTimers() { 00168 std::cout << "out of order timers " << get_time() << " :\t"; 00169 unsigned int last=0; 00170 for(timer_it_t it=timers.begin(); it!=timers.end(); it++) { 00171 if(last>(*it)->next) 00172 std::cout << "##"; 00173 std::cout << (last=(*it)->next) << '\t'; 00174 } 00175 std::cout << std::endl; 00176 } 00177 00178 std::vector<EventBase*> events; //!< used to store buffered events 00179 bool doSendBufferLock; //!< in case of recursive calls to processEventBuffer()/doSendBuffer() 00180 unsigned int lastBufClear; //!< time of last event buffer clear 00181 unsigned int buffertime; //!< The time between clearings of the buffer 00182 /*!< <li>0 will not use the buffer, events are routed upon posting 00183 * <li>1 will clear the buffer at next call to processTimers() or processEventBuffer() 00184 * <li>a larger value will cause a delay of that number of milliseconds since the last clearing */ 00185 00186 //! Does the actual storage of the mapping between EventBase's and the EventListeners/EventTrappers who should receive them 00187 /*! Actually only stores void*'s, so it's more general than just Listeners or Trappers */ 00188 class EventMapper { 00189 public: 00190 //! constructor 00191 EventMapper(); 00192 00193 void addMapping(void* el, EventBase::EventGeneratorID_t egid) { allevents[egid].push_back(el); } //!< Adds a listener for all events from a given event generator 00194 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 00195 00196 //! Removes a listener for all events from a given event generator 00197 /*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */ 00198 void removeMapping(void* el, EventBase::EventGeneratorID_t egid); 00199 00200 //! Removes a listener for a specific source id and type from a given event generator 00201 /*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */ 00202 void removeMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); 00203 00204 void clean(); //!<compresses empty data structures 00205 void clear(); //!<Resets the mapping 00206 00207 //@{ 00208 //! so stuff can tell if it even needs to bother generating an event... 00209 /*! ... if a tree falls in a forest, and there's no one around to see it, does it make a sound?\n 00210 ... if Vision sees a ball in an image, and there's no listeners, does it make an event? ;) \n 00211 @return true if it has any listeners, false otherwise */ 00212 bool hasMapping(EventBase::EventGeneratorID_t egid); 00213 bool hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid); 00214 bool hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); 00215 //@} 00216 00217 //! builds a list of all listeners which should receive the event, templated to typecast the pointers for you 00218 /*! @param e the key event 00219 * @param listeners upon return, the resulting list of listeners @a e maps to\n 00220 * @a listeners is not cleared prior to building, new listeners are pushed on end\n 00221 * Results are in the order: all specific matches first, all generator listeners second, in order they were added to the EventMapper.*/ 00222 template<class T> 00223 void getMapping(const EventBase& e, std::vector<T*>& listeners); 00224 00225 //! Used to make sure that the specified listener exists for the given event 00226 /*! This is needed because after we call processEvent on a lister, we can't assume 00227 * that no other listeners have been modified - one listener could cause another 00228 * to turn off. If that has happened, we shouldn't send the event, even if it 00229 * was in the queue originally. */ 00230 bool verifyMapping(void * listener, const EventBase& e) { return verifyMapping(listener,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } 00231 //! Used to make sure that the specified listener exists for the given event 00232 /*! This is needed because after we call processEvent on a lister, we can't assume 00233 * that no other listeners have been modified - one listener could cause another 00234 * to turn off. If that has happened, we shouldn't send the event, even if it 00235 * was in the queue originally. */ 00236 bool verifyMapping(void * listener, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); 00237 00238 protected: 00239 //! a mapping from source IDs (unsigned ints), each to a vector of pointers to listeners 00240 /*! main use in filteredevents @see filteredevents */ 00241 typedef std::map<unsigned int,std::vector<void*>,std::less<unsigned int> > SIDtoListenerVectorMap_t; 00242 00243 //! an array of vectors of pointers to listeners... in other words, a vector of listener pointers for each generator 00244 std::vector<void*> allevents[EventBase::numEGIDs]; 00245 //! not for the faint of heart: a matrix of mappings to vectors of pointers to listeners 00246 SIDtoListenerVectorMap_t* filteredevents[EventBase::numEGIDs][EventBase::numETIDs]; 00247 00248 private: 00249 EventMapper(const EventMapper&); //!< this shouldn't be called... 00250 EventMapper operator=(const EventMapper&); //!< this shouldn't be called... 00251 }; 00252 00253 EventMapper trappers; //!< A mapping of which EventTrapper's should get a chance to trap the event 00254 EventMapper listeners; //!< A mapping of which EventListener's should receive events 00255 00256 }; 00257 00258 //! 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 00259 extern EventRouter * erouter; 00260 00261 /*! @file 00262 * @brief Describes EventRouter class, for distribution and trapping of events to listeners 00263 * @author ejt (Creator) 00264 * 00265 * $Author: ejt $ 00266 * $Name: tekkotsu-2_1 $ 00267 * $Revision: 1.13 $ 00268 * $State: Exp $ 00269 * $Date: 2004/01/18 10:16:57 $ 00270 */ 00271 00272 #endif |
Tekkotsu v2.1 |
Generated Tue Mar 16 23:19:13 2004 by Doxygen 1.3.5 |