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.\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_0 $
00267  * $Revision: 1.13 $
00268  * $State: Exp $
00269  * $Date: 2004/01/18 10:16:57 $
00270  */
00271 
00272 #endif

Tekkotsu v2.0
Generated Wed Jan 21 03:20:28 2004 by Doxygen 1.3.4