| Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | 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 <queue> 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 "Shared/attributes.h" 00014 #include <iostream> 00015 00016 //! This class will handle distribution of events as well as management of timers 00017 /*! Classes must inherit from EventListener and/or EventTrapper in order to 00018 * receive events. 00019 * 00020 * Use the global ::erouter instance of EventRouter to both send (post) and receive (subscribe/listen) to 00021 * events. (except if you are posting from within a MotionCommand, in 00022 * which case you should use MotionCommand::postEvent() so that it can correctly 00023 * handle inter-process communication issues under Aperios (the Aibo's OS) -- under a 00024 * Unix-based OS, this wouldn't be necessary.) 00025 * 00026 * The events available for processing are listed in EventBase::EventGeneratorID_t. 00027 * Each generator ID's documentation specifies how to interpret the source ID field, and whether 00028 * you can expect events with that generator ID to be of a subclass of EventBase, 00029 * such as TextMsgEvent or LocomotionEvent. Many generators send plain 00030 * EventBase instances. 00031 * 00032 * When multiple listeners are subscribed, the order in which an event is 00033 * distributed among them is: 00034 * -# "Specific" listeners: any listener which specifies a particular source id. 00035 * (doesn't matter if they specified type id as well) 00036 * - older listeners get events before more recently added listeners ("FIFO") 00037 * -# "General" listeners: those that subscribe to an entire generator 00038 * - older listeners get events before more recently added listeners ("FIFO") 00039 * 00040 * ...but if you're relying on that ordering, there probably should be a cleaner 00041 * way to do whatever you're doing. 00042 * 00043 * TimerEvents are generally only sent to the generator which requested them. So if 00044 * EventListener @e A requests a timer (see addTimer()) with ID 0 at two second intervals, 00045 * and @e B requests a timer with ID 0 at three second intervals, 00046 * each will still only receive the timers they requested - no cross talk. 00047 * The timer generator is unique in this regard, which is why it is built in 00048 * as an integral component of the EventRouter. However, EventListener @e A 00049 * <b>can</b> receive @e B's timers if it specifically wants to, via addListener(). See "Timers" below. 00050 * 00051 * If an EventListener/EventTrapper subscribes to the same event source multiple 00052 * times, it will receive multiple copies of the event. However, the first call 00053 * to removeListener for a source will remove all subscriptions to that source.\n 00054 * Example: EventListener @e A subscribes to (buttonEGID,*,*), and twice to 00055 * (buttonEGID,0,*). 00056 * - If button 0 is pressed, @e A will get three copies of the event. 00057 * - If button 1 is pressed, @e A will get one copy. 00058 * - If removeListener(&A,buttonEGID) is called, the (buttonEGID,*,*) is 00059 * removed, <em>as well as</em> both of (buttonEGID,0,*). 00060 * - If removeListener(&A,buttonEGID,0) is called, both of (buttonEGID,0,*) 00061 * are removed, but (buttonEGID,*,*) would be untouched. 00062 * 00063 * <h3>Timers</h3> 00064 * addTimer() allows you to request an TimerEvent to be sent at some later point in time, 00065 * possibly on a repeating basis. Timers are specific to the behavior which requests 00066 * them, and you @e do @e not (and usually should not) call addListener() in order to receive a timer 00067 * event. 00068 * 00069 * There is an important different between addTimer() and #addListener(timerEGID,...)! 00070 * addTimer will "create" the timer, and will send the timer to the listener 00071 * which created it when the timer expires. This means that as long as the listener in 00072 * question does @e not call addListener(timerEGID), it will @e only receive its own timers. 00073 * In other words, with this usage there is no confusion with timer cross-talk between 00074 * listeners, because each listener is only receiving its own timers. 00075 * 00076 * However, if a listener calls addListener(timerEGID), it will begin receiving @e all timer events 00077 * from throughout the system. This allows you to have one behavior "eavesdrop" on 00078 * another's timers. In order to determine which listener requested/created the timer, 00079 * you can use the TimerEvent::getTarget() value. 00080 * 00081 * So beware that if you call both addTimer() and addListener(foo,timerEGID), 'foo' will get 00082 * two calls to processEvent() for its own timers, and one call for all other timers, and will 00083 * have to know to call TimerEvent::getTarget() to distinguish its timers from other 00084 * listener's timers (if it cares about the difference...) 00085 * 00086 * Timers are sent to the requesting listener before being broadcast -- EventTrappers cannot 00087 * filter a listener's own timers, but can prevent the timer from being broadcast to other listeners. 00088 * 00089 * <h3>Event processing examples:</h3> 00090 * 00091 * Posting events: 00092 * @code 00093 * //method A: basic event posting (EventBase instance is sent) 00094 * erouter->postEvent(EventBase::aiEGID, 1234, EventBase::statusETID); 00095 * 00096 * //method B: specific event instance is posted (have to use this style to post a subclass) 00097 * TextMsgEvent txt("hello world"); 00098 * erouter->postEvent(txt); 00099 * // or can be done in one line: 00100 * erouter->postEvent(TextMsgEvent("hello world")) 00101 * @endcode 00102 * 00103 * Receiving events: 00104 * @code 00105 * //given an EventListener subclass: 00106 * class YourListener : public EventListener { 00107 * public: 00108 * virtual void processEvent(const EventBase& e) { 00109 * std::cout << "Got: " << e.getName() << std::endl; 00110 * } 00111 * }; 00112 * 00113 * YourListener yourList; 00114 * 00115 * // subscribes it to all EventBase::aiEGID events: 00116 * erouter->addListener(&yourList, EventBase::aiEGID); 00117 * 00118 * // subscribes only to button activity from the head, but not other buttons: 00119 * erouter->addListener(&yourList, EventBase::buttonEGID, ERS7Info::HeadButOffset); 00120 * @endcode 00121 * Typically in a BehaviorBase subclass, you would just specify 'this' instead of '&yourList'. 00122 * 00123 * <h3>Timer processing examples:</h3> 00124 * 00125 * Requesting/Creating timers: 00126 * @code 00127 * YourListener yourList; // (any EventListener subclass) 00128 * 00129 * // sends a timer with source ID 123 every 5 seconds to yourList: 00130 * erouter->addTimer(&yourList, 123, 5000); 00131 * 00132 * // sends a timer with ID 456 after 1 second, *no repeat, one time only* 00133 * erouter->addTimer(&yourList, 456, 1000, false); 00134 * 00135 * // cancels the first timer 00136 * erouter->removeTimer(&yourList, 123); 00137 * 00138 * // postpone/update the second timer's settings (*doesn't* create two timers with the same ID) 00139 * erouter->addTimer(&yourList, 456, 2500, false); 00140 * 00141 * @endcode 00142 * Again, typically in a BehaviorBase subclass, you would just specify 'this' instead of '&yourList'. 00143 * 00144 * @see EventBase::EventGeneratorID_t for a complete listing of all generators, 00145 * as well as instructions on how to add new generators. 00146 * @see Tutorials: 00147 * - <a href="../FirstBehavior2.html">Steps 3, 4, & 5 of Tekkotsu's First Behavior Tutorial</a> 00148 * - <a href="http://www.cs.cmu.edu/~dst/Tekkotsu/Tutorial/events.shtml">David Touretzky's Events Chapter</a> 00149 * - <a href="http://www.cs.cmu.edu/afs/cs/academic/class/15494-s06/www/lectures/behaviors.pdf">CMU's Cognitive Robotics course slides</a> 00150 */ 00151 class EventRouter : public EventListener { 00152 public: 00153 EventRouter(); //!< Constructs the router 00154 virtual ~EventRouter() { reset(); removeAllTimers(); } //!< just calls reset and removeAllTimers() 00155 00156 void reset() { listeners.clear(); trappers.clear(); removeAllTimers(); } //!< erases all listeners, trappers and timers, resets EventRouter 00157 00158 00159 //!@name Posting/Processing Events 00160 00161 /*!@brief recommended to create and post an event using current buffer setting */ 00162 void postEvent(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid, unsigned int dur=0) { processEvent(EventBase(egid,sid,etid,dur)); } 00163 void postEvent(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid, unsigned int dur, const std::string& n, float m) { processEvent(EventBase(egid,sid,etid,dur,n,m)); } 00164 //! deprecated -- pass by reference instead; this version posts the specified event and then deletes it after processing is complete 00165 /*! moving to pass by reference instead of pass by pointer to avoid questions about who deletes the event and the event's scope, 00166 * also keeping the event on the stack is faster by avoiding unnecessary heap operations. */ 00167 void postEvent(EventBase* e) ATTR_deprecated; 00168 //! posts the specified event, but doesn't delete it at the end -- equivalent to processEvent(e) 00169 void postEvent(const EventBase& e) { processEvent(e); } 00170 00171 //! determines if timers need to be posted, and posts them if so. 00172 /*! Call this often to ensure accurate timers. */ 00173 void processTimers(); 00174 //! sends event to its trappers & listeners, but doesn't delete the event at the end (see also postEvent()) 00175 /*! this posting method is supplied to allow an EventRouter to behave as a listener as 00176 * well -- the 'routers' really can form a sort of network, if desired. postEvent() is 00177 * probably a more memnomic interface to use in direct function calls however, 00178 * so that is the one you should call. */ 00179 void processEvent(const EventBase& e); 00180 //@} 00181 00182 00183 //!@name Listener/Trapper Recall 00184 00185 //! returns true if the specified listener/trapper would receive any events that match the specified criteria 00186 bool isListeningAny(EventListener* el, EventBase::EventGeneratorID_t egid) { return listeners.verifyMappingAny(el,egid); } 00187 bool isListeningAny(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { return listeners.verifyMappingAny(el,egid,sid); } 00188 bool isListeningAll(EventListener* el, EventBase::EventGeneratorID_t egid) { return listeners.verifyMappingAll(el,egid); } 00189 bool isListeningAll(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { return listeners.verifyMappingAll(el,egid,sid); } 00190 bool isListening(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { return listeners.verifyMapping(el,egid,sid,etid); } 00191 bool isListening(EventListener* el, const EventBase& e) { return listeners.verifyMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } 00192 bool isTrappingAny(EventTrapper* el, EventBase::EventGeneratorID_t egid) { return trappers.verifyMappingAny(el,egid); } 00193 bool isTrappingAny(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { return trappers.verifyMappingAny(el,egid,sid); } 00194 bool isTrappingAll(EventTrapper* el, EventBase::EventGeneratorID_t egid) { return trappers.verifyMappingAll(el,egid); } 00195 bool isTrappingAll(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { return trappers.verifyMappingAll(el,egid,sid); } 00196 bool isTrapping(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { return trappers.verifyMapping(el,egid,sid,etid); } 00197 bool isTrapping(EventTrapper* el, const EventBase& e) { return trappers.verifyMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } 00198 //@} 00199 00200 00201 //!@name Listener/Trapper Detection 00202 00203 /*!@brief <b>counts both listeners and trappers</b>, so generators can tell if it even needs to bother generating an event...*/ 00204 /* Generators can also subscribe to the EventBase::erouterEGID event stream if 00205 * they wish to be notified when they gain or lose listeners (particularly the 00206 * first or last).\n 00207 * ... if a tree falls in a forest, and there's no one around to see it, does 00208 * it make a sound?\n 00209 * ... if Vision sees a ball in an image, and there's no listeners, does it 00210 * make an event? ;) */ 00211 bool hasListeners(EventBase::EventGeneratorID_t egid) { return trappers.hasMapping(egid) || listeners.hasMapping(egid); } 00212 bool hasListeners(EventBase::EventGeneratorID_t egid, unsigned int sid) { return trappers.hasMapping(egid,sid) || listeners.hasMapping(egid,sid); } 00213 bool hasListeners(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { return trappers.hasMapping(egid,sid,etid) || listeners.hasMapping(egid,sid,etid); } 00214 bool hasListeners(const EventBase& e) { return hasListeners(e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } 00215 //@} 00216 00217 00218 //!@name Timer Management 00219 00220 //! adds a timer if it doesn't exist, or resets the timer if it already exists. 00221 void addTimer(EventListener* el, unsigned int sid, unsigned int delay, bool repeat=true); 00222 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 00223 00224 //! clears all pending timers for listener @a el; see remove() 00225 void removeTimer(EventListener* el); 00226 void removeTimer(EventListener* el, unsigned int sid); //!< clears any pending timers with source id @a sid for listener @a el 00227 void removeAllTimers(); //!< clears all timers for all listeners 00228 unsigned int getNextTimer() { return (timers.size()==0 ? -1U : timers.front()->next); } //!< returns time of next timer activation 00229 //@} 00230 00231 00232 //!@name Listener Management 00233 00234 //! Adds a listener for all events from a given event generator 00235 void addListener(EventListener* el, EventBase::EventGeneratorID_t egid); 00236 void addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< Adds a listener for all types from a specific source and generator 00237 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 00238 void addListener(EventListener* el, const EventBase& e); //!< Uses the generator, source, and type fields of @a e to add a listener for that specific tuple 00239 00240 //! stops sending ALL events to the listener -- does not remove pending timers however (may need to call removeTimer(el) as well); see remove() 00241 void removeListener(EventListener* el); 00242 //! stops sending specified events from the generator to the listener. 00243 void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid); 00244 void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< stops sending specified events from the generator to the listener. 00245 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. 00246 void removeListener(EventListener* el, const EventBase& e); //!< Uses the generator, source, and type fields of @a e to remove a listener for that specific tuple 00247 00248 //! stops all events and timers, shorthand for removeListener(el) and removeTimer(el); Note that trappers are separate, removeTrapper() is @e not called 00249 void remove(EventListener* el) { removeListener(el); removeTimer(el); } 00250 00251 //@} 00252 00253 //!@name Trapper Management 00254 00255 //! Adds a trapper for a specific source id and type from a given event generator 00256 /*! Note that only the broadcasted timers can be trapped. The EventListener which requested the timer will receive that timer before any trapping is done. */ 00257 void addTrapper(EventTrapper* el, const EventBase& e); 00258 void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid); //!< Adds a trapper for all events from a given event generator 00259 void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< Adds a trapper for all types from a specific source and generator 00260 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 00261 00262 void addTrapper(EventTrapper* el); //!< adds a trapper for ALL events 00263 00264 //! stops sending specified events from the generator to the trapper. 00265 void removeTrapper(EventTrapper* el, const EventBase& e); 00266 void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid); //!< stops sending specified events from the generator to the trapper. 00267 void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< stops sending specified events from the generator to the trapper. 00268 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. 00269 00270 void removeTrapper(EventTrapper* el); //!< stops sending ALL events to the trapper 00271 //@} 00272 00273 protected: 00274 //! Contains all the information needed to maintain a timer by the EventRouter 00275 struct TimerEntry { 00276 //! constructs an entry using the given value for next - useful for with TimerEntryPtrCmp 00277 explicit TimerEntry(unsigned int nxt) : el(NULL), sid(0), delay(0), next(nxt), repeat(false) {} 00278 //! constructs with the given values, sets next field automatically; see next 00279 TimerEntry(EventListener* e, unsigned int s, unsigned int d, bool r) : el(e), sid(s), delay(d), next(get_time()+delay), repeat(r) {} 00280 //! just does the default, i'm just being explicit since there's a pointer (no deep copy!) 00281 TimerEntry(const TimerEntry& t) : el(t.el), sid(t.sid), delay(t.delay), next(t.next), repeat(t.repeat) {} 00282 //! just does the default, i'm just being explicit since there's a pointer (no deep copy!) 00283 TimerEntry& operator=(const TimerEntry& t) { el=t.el; sid=t.sid; delay=t.delay; next=t.next; repeat=t.repeat; return *this; } 00284 //! will reset timer 00285 /*! @param d the time from now when the timer should go off (in milliseconds) 00286 * @param r true if the timer should automatically repeat */ 00287 void Set(unsigned int d, bool r) { delay=d; repeat=r; next=get_time()+delay; } 00288 EventListener* el; //!< the listener to fire at 00289 unsigned int sid; //!< the source id to fire with 00290 unsigned int delay; //!< the delay until firing 00291 unsigned int next; //!< the time at which this timer will go off next 00292 bool repeat; //!< if true, will reset after firing, else will be deleted 00293 }; 00294 /*! @brief Used by STL to sort the timer list in order of activation time 00295 * @see EventRouter::timers */ 00296 class TimerEntryPtrCmp { 00297 public: 00298 //! Used by STL to sort the timer list in order of activation time; see timers 00299 /*! Since we remove NULLs before sorting, shouldn't need to check here (and I want to know if i'm wrong) 00300 * @return (a->next<b->next) */ 00301 bool operator()(const TimerEntry* const a, const TimerEntry* const b) const { return (a->next<b->next); } 00302 }; 00303 typedef std::vector<TimerEntry*>::iterator timer_it_t; //!< makes code more readable 00304 std::vector<TimerEntry*> timers; //!< the list of timer entries being maintained, kept sorted by time they go active 00305 00306 //! just for debugging 00307 void chkTimers() { 00308 unsigned int last=0; 00309 for(timer_it_t it=timers.begin(); it!=timers.end(); it++) { 00310 if(last>(*it)->next) { 00311 dispTimers(); 00312 return; 00313 } 00314 last=(*it)->next; 00315 } 00316 } 00317 //! just for debugging 00318 void dispTimers() { 00319 std::cout << "out of order timers " << get_time() << " :\t"; 00320 unsigned int last=0; 00321 for(timer_it_t it=timers.begin(); it!=timers.end(); it++) { 00322 if(last>(*it)->next) 00323 std::cout << "##"; 00324 std::cout << (last=(*it)->next) << '\t'; 00325 } 00326 std::cout << std::endl; 00327 } 00328 00329 //! Does the actual storage of the mapping between EventBase's and the EventListeners/EventTrappers who should receive them 00330 /*! Actually only stores void*'s, so it's more general than just Listeners or Trappers */ 00331 class EventMapper { 00332 public: 00333 //! constructor 00334 EventMapper(); 00335 00336 void addMapping(void* el, EventBase::EventGeneratorID_t egid) { allevents[egid].push_back(el); } //!< Adds a listener for all events from a given event generator 00337 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 00338 00339 //! Removes a listener for all events from a given event generator, returns true if something was actually removed 00340 /*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */ 00341 bool removeMapping(void* el, EventBase::EventGeneratorID_t egid); 00342 00343 //! Removes a listener for a specific source id and type from a given event generator, returns true if something was actually removed 00344 /*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */ 00345 bool removeMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); 00346 00347 void clean(); //!<removes empty data structures for all event generators 00348 void clean(EventBase::EventGeneratorID_t egid); //!< removes empty data structures associated with a single event generator 00349 void clear(); //!<Resets the mapping 00350 00351 //@{ 00352 //! so stuff can tell if it even needs to bother generating an event... 00353 /*! ... if a tree falls in a forest, and there's no one around to see it, does it make a sound?\n 00354 ... if Vision sees a ball in an image, and there's no listeners, does it make an event? ;) \n 00355 @return true if it has any listeners, false otherwise */ 00356 bool hasMapping(EventBase::EventGeneratorID_t egid) const; 00357 bool hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid) const; 00358 bool hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) const; 00359 //@} 00360 00361 //! builds a list of all listeners which should receive the event, templated to typecast the pointers for you 00362 /*! @param e the key event 00363 * @param listeners upon return, the resulting list of listeners @a e maps to\n 00364 * @a listeners is not cleared prior to building, new listeners are pushed on end\n 00365 * Results are in the order: all specific matches first, all generator listeners second, in order they were added to the EventMapper.*/ 00366 template<class T> 00367 void getMapping(const EventBase& e, std::vector<T*>& listeners) const; 00368 00369 //! Used to make sure that the specified listener exists for the given event 00370 /*! This is needed because after we call processEvent on a lister, we can't assume 00371 * that no other listeners have been modified - one listener could cause another 00372 * to turn off. If that has happened, we shouldn't send the event, even if it 00373 * was in the queue originally. */ 00374 bool verifyMapping(void * listener, const EventBase& e) const { return verifyMapping(listener,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } 00375 //! Used to make sure that the specified listener exists for the given event 00376 /*! This is needed because after we call processEvent on a lister, we can't assume 00377 * that no other listeners have been modified - one listener could cause another 00378 * to turn off. If that has happened, we shouldn't send the event, even if it 00379 * was in the queue originally. */ 00380 bool verifyMapping(void * listener, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) const; 00381 00382 //! Needed to complete EventRouter::isListening suite 00383 /*! Only checks #allevents */ 00384 bool verifyMappingAll(void * listener, EventBase::EventGeneratorID_t egid) const; 00385 //! Needed to complete EventRouter::isListening suite 00386 /*! Checks both #allevents and #filteredevents */ 00387 bool verifyMappingAny(void * listener, EventBase::EventGeneratorID_t egid) const; 00388 00389 //! Needed to complete EventRouter::isListening suite 00390 /*! Checks both #allevents and #filteredevents, must be found in all */ 00391 bool verifyMappingAll(void * listener, EventBase::EventGeneratorID_t egid, unsigned int sid) const; 00392 //! Needed to complete EventRouter::isListening suite 00393 /*! Checks both #allevents and #filteredevents, can be found in either */ 00394 bool verifyMappingAny(void * listener, EventBase::EventGeneratorID_t egid, unsigned int sid) const; 00395 00396 protected: 00397 //! a mapping from source IDs (unsigned ints), each to a vector of pointers to listeners 00398 /*! main use in filteredevents @see filteredevents */ 00399 typedef std::map<unsigned int,std::vector<void*>,std::less<unsigned int> > SIDtoListenerVectorMap_t; 00400 00401 //! an array of vectors of pointers to listeners... in other words, a vector of listener pointers for each generator 00402 std::vector<void*> allevents[EventBase::numEGIDs]; 00403 //! not for the faint of heart: a matrix of mappings to vectors of pointers to listeners 00404 SIDtoListenerVectorMap_t* filteredevents[EventBase::numEGIDs][EventBase::numETIDs]; 00405 00406 private: 00407 EventMapper(const EventMapper&); //!< this shouldn't be called... 00408 EventMapper& operator=(const EventMapper&); //!< this shouldn't be called... 00409 }; 00410 00411 EventMapper trappers; //!< A mapping of which EventTrapper's should get a chance to trap the event 00412 EventMapper listeners; //!< A mapping of which EventListener's should receive events 00413 00414 //! contains information regarding the progress of posting an event 00415 /*! This allows us to resume and complete the posting of the "current" event before processing a new incoming event */ 00416 class PostingStatus { 00417 public: 00418 //! constructor 00419 PostingStatus(const EventMapper& eventTrappers, const EventMapper& eventListeners, const EventBase& event) 00420 : trappers(eventTrappers), listeners(eventListeners), t(), tit(), l(), lit(), e(event) 00421 { trappers.getMapping(e,t); tit=t.begin(); listeners.getMapping(e,l); lit=l.begin(); } 00422 //! begins or resumes sending the event #e to trappers and listeners in #t and #l 00423 void process(); 00424 protected: 00425 const EventMapper& trappers; //!< the current trapper mapping, used to verify each entry in #t is still valid before processing it 00426 const EventMapper& listeners; //!< the current listener mapping, used to verify each entry in #l is still valid before processing it 00427 std::vector<EventTrapper*> t; //!< list of trappers which were subscribed when the PostingStatus instance was constructed 00428 std::vector<EventTrapper*>::const_iterator tit; //!< current position within #t 00429 std::vector<EventListener*> l; //!< list of listeners which were subscribed when the PostingStatus instance was constructed 00430 std::vector<EventListener*>::const_iterator lit; //!< current position within #l 00431 const EventBase& e; //!< the event being processed 00432 }; 00433 std::queue<PostingStatus*> postings; //!< stores calls to post() currently in progress -- may grow if one postEvent() triggers another; this allows us to finish processing of the original postEvent() before starting the second. 00434 }; 00435 00436 //! 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 00437 extern EventRouter * erouter; 00438 00439 /*! @file 00440 * @brief Describes EventRouter class, for distribution and trapping of events to listeners 00441 * @author ejt (Creator) 00442 * 00443 * $Author: ejt $ 00444 * $Name: tekkotsu-3_0 $ 00445 * $Revision: 1.35 $ 00446 * $State: Exp $ 00447 * $Date: 2006/10/03 21:09:04 $ 00448 */ 00449 00450 #endif |
|
Tekkotsu v3.0 |
Generated Wed Oct 4 00:03:43 2006 by Doxygen 1.4.7 |