Homepage
Demos
Overview
Downloads
Tutorials
Reference
Credits

EventRouter.h

Go 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