Homepage Demos Overview Downloads Tutorials Reference
Credits
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Search

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
00115   void doSendEvent(const EventBase& e); //!< does the work of sending an event
00116 
00117   //! Contains all the information needed to maintain a timer by the EventRouter
00118   struct TimerEntry {
00119     //! constructors an entry using the given value for next - useful for with TimerEntryPtrCmp
00120     explicit TimerEntry(unsigned int nxt) : el(NULL), sid(0), delay(0), next(nxt), repeat(false) {}
00121     //! constructs with the given values, sets next field automatically @see next
00122     TimerEntry(EventListener* e, unsigned int s, unsigned int d, bool r) : el(e), sid(s), delay(d), next(get_time()+delay), repeat(r) {}
00123     //! just does the default, i'm just being explicit since there's a pointer (no deep copy!)
00124     TimerEntry(const TimerEntry& t) : el(t.el), sid(t.sid), delay(t.delay), next(t.next), repeat(t.repeat) {}
00125     //! just does the default, i'm just being explicit since there's a pointer (no deep copy!)
00126     TimerEntry operator=(const TimerEntry& t) { el=t.el; sid=t.sid; delay=t.delay; next=t.next; repeat=t.repeat; return *this; }
00127     //! will reset timer
00128     /*! @param d the time from now when the timer should go off (in milliseconds)
00129      *  @param r true if the timer should automatically repeat */
00130     void Set(unsigned int d, bool r) { delay=d; repeat=r; next=get_time()+delay; }
00131     EventListener* el;  //!< the listener to fire at
00132     unsigned int sid;   //!< the source id to fire with
00133     unsigned int delay; //!< the delay until firing
00134     unsigned int next;  //!< the time at which this timer will go off next
00135     bool repeat;        //!< if true, will reset after firing, else will be deleted
00136   };
00137   /*! @brief Used by STL to sort the timer list in order of activation time
00138    *  @see EventRouter::timers */
00139   class TimerEntryPtrCmp {
00140   public:
00141     //! Used by STL to sort the timer list in order of activation time @see timers
00142     /*! Since we remove NULLs before sorting, shouldn't need to check here (and I want to know if i'm wrong)
00143      *  @return (a->next<b->next) */
00144     bool operator()(const TimerEntry* const a, const TimerEntry* const b) const { return (a->next<b->next); }
00145   };
00146   typedef std::vector<TimerEntry*>::iterator timer_it_t; //!< makes code more readable
00147   std::vector<TimerEntry*> timers;         //!< the list of timer entries being maintained, kept sorted by time they go active
00148 
00149   //! just for debugging
00150   void chkTimers() {
00151     unsigned int last=0;
00152     for(timer_it_t it=timers.begin(); it!=timers.end(); it++) {
00153       if(last>(*it)->next) {
00154         dispTimers();
00155         return;
00156       }
00157       last=(*it)->next;
00158     }
00159   }
00160   //! just for debugging
00161   void dispTimers() {
00162     std::cout << "out of order timers " << get_time() << " :\t";
00163     unsigned int last=0;
00164     for(timer_it_t it=timers.begin(); it!=timers.end(); it++) {
00165       if(last>(*it)->next)
00166         std::cout << "##";
00167       std::cout << (last=(*it)->next) << '\t';
00168     }
00169     std::cout << std::endl;
00170   }
00171 
00172   std::vector<EventBase*> events;     //!< used to store buffered events
00173   bool doSendBufferLock;              //!< in case of recursive calls to processEventBuffer()/doSendBuffer()
00174   unsigned int lastBufClear;          //!< time of last event buffer clear
00175   unsigned int buffertime;            //!< The time between clearings of the buffer
00176                                       /*!< <li>0 will not use the buffer, events are routed upon posting
00177                                        *   <li>1 will clear the buffer at next call to processTimers() or processEventBuffer()
00178                                        *   <li>a larger value will cause a delay of that number of milliseconds since the last clearing */
00179   
00180   //! Does the actual storage of the mapping between EventBase's and the EventListeners/EventTrappers who should receive them
00181   /*! Actually only stores void*'s, so it's more general than just Listeners or Trappers */
00182   class EventMapper {
00183   public:
00184     //! constructor
00185     EventMapper();
00186 
00187     void addMapping(void* el, EventBase::EventGeneratorID_t egid) { allevents[egid].push_back(el); } //!< Adds a listener for all events from a given event generator
00188     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
00189 
00190     //! Removes a listener for all events from a given event generator
00191     /*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */
00192     void removeMapping(void* el, EventBase::EventGeneratorID_t egid); 
00193 
00194     //! Removes a listener for a specific source id and type from a given event generator
00195     /*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */
00196     void removeMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid);
00197 
00198     void clean(); //!<compresses empty data structures
00199     void clear(); //!<Resets the mapping
00200 
00201     //@{
00202     //! so stuff can tell if it even needs to bother generating an event...
00203     /* ... if a tree falls in a forest, and there's no one around to see it, does it make a sound?
00204        ... if Vision sees a ball in an image, and there's no listeners, does it make an event? ;) */
00205     /*! @return true if it has any listeners, false otherwise */
00206     bool hasMapping(EventBase::EventGeneratorID_t egid);
00207     bool hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid);
00208     bool hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid);
00209     //@}
00210 
00211     //! builds a list of all listeners which should receive the event, templated to typecast the pointers for you
00212     /*! @param e the key event
00213      *  @param listeners upon return, the resulting list of listeners @a e maps to\n
00214      *  @a listeners is not cleared prior to building, new listeners are pushed on end\n
00215      *  Results are in the order: all specific matches first, all generator listeners second, in order they were added to the EventMapper.*/
00216     template<class T>
00217     void getMapping(const EventBase& e, std::vector<T*>& listeners);
00218 
00219   protected:
00220     //! a mapping from source IDs (unsigned ints), each to a vector of pointers to listeners
00221     /*! main use in filteredevents @see filteredevents */
00222     typedef std::map<unsigned int,std::vector<void*>,std::less<unsigned int> > SIDtoListenerVectorMap_t;
00223     
00224     //! an array of vectors of pointers to listeners... in other words, a vector of listener pointers for each generator
00225     std::vector<void*> allevents[EventBase::numEGIDs];
00226     //! not for the faint of heart: a matrix of mappings to vectors of pointers to listeners
00227     SIDtoListenerVectorMap_t* filteredevents[EventBase::numEGIDs][EventBase::numETIDs];
00228 
00229   private:
00230     EventMapper(const EventMapper&);           //!< this shouldn't be called...
00231     EventMapper operator=(const EventMapper&); //!< this shouldn't be called...
00232   };
00233 
00234   EventMapper trappers;  //!< A mapping of which EventTrapper's should get a chance to trap the event
00235   EventMapper listeners; //!< A mapping of which EventListener's should receive events
00236 
00237 };
00238 
00239 //! 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
00240 extern EventRouter * erouter;
00241 
00242 /*! @file
00243  * @brief Describes EventRouter class, for distribution and trapping of events to listeners
00244  * @author ejt (Creator)
00245  *
00246  * $Author: ejt $
00247  * $Name: tekkotsu-1_4_1 $
00248  * $Revision: 1.10 $
00249  * $State: Exp $
00250  * $Date: 2003/04/25 18:22:39 $
00251  */
00252 
00253 #endif

Tekkotsu v1.4
Generated Sat Jul 19 00:06:30 2003 by Doxygen 1.3.2