Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

EventRouter.cc

Go to the documentation of this file.
00001 #include "EventRouter.h"
00002 #include "Shared/Profiler.h"
00003 #include "Behaviors/BehaviorBase.h"
00004 #include "Shared/ProjectInterface.h"
00005 #include <algorithm>
00006 
00007 EventRouter * erouter=NULL;
00008 
00009 EventRouter::EventRouter()
00010   : timers(), events(), doSendBufferLock(false), lastBufClear(0), buffertime(0), trappers(), listeners()
00011 {}
00012 
00013 //! @todo handle recursive calls
00014 void EventRouter::processTimers() {
00015   //    cout << "processTimers..." << flush;
00016   unsigned int curtime=get_time();
00017   if(curtime-lastBufClear>=buffertime || buffertime==1)
00018     processEventBuffer();
00019 
00020   TimerEntry curTimer(curtime);
00021   timer_it_t last_it=upper_bound(timers.begin(),timers.end(),&curTimer,TimerEntryPtrCmp());
00022   std::vector<TimerEntry*> process(timers.begin(),last_it); //copy these out for safe keeping
00023   for(timer_it_t it=process.begin(); it!=process.end(); it++) //increment the timers we're processing
00024     if((*it)->repeat)
00025       (*it)->next+=(*it)->delay;
00026     else
00027       (*it)->next=(unsigned int)-1;
00028   sort(timers.begin(),last_it,TimerEntryPtrCmp()); //re-sort the timers we're processing (at the beginning of timers)
00029   inplace_merge(timers.begin(),last_it,timers.end(),TimerEntryPtrCmp()); //now do a merge of the sorted processed stuff and the rest of the list (which is still sorted)
00030   //  if(process.size()>0) chkTimers();
00031   for(timer_it_t it=process.begin(); it!=process.end(); it++) { // process the timers we say we're going to, can no longer assume anything about the state of the world
00032     EventBase e(EventBase::timerEGID,(*it)->sid,EventBase::statusETID,(*it)->next);
00033     try {
00034       (*it)->el->processEvent(e);
00035     } catch(const std::exception& ex) {
00036       std::string msg="Occurred while processing event "+e.getName()+" by ";
00037       if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>((*it)->el))
00038         msg+="listener "+beh->getName();
00039       else
00040         msg+="unnamed EventListener";
00041       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
00042         throw;
00043     } catch(...) {
00044       std::string msg="Occurred while processing event "+e.getName()+" by ";
00045       if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>((*it)->el))
00046         msg+="listener "+beh->getName();
00047       else
00048         msg+="unnamed EventListener";
00049       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
00050         throw;
00051     }
00052   }
00053   //  if(process.size()>0) chkTimers();
00054   static const TimerEntry deadTimer((unsigned int)-1); // matches all the dead ones as set in the incrementation phase
00055   last_it=lower_bound(timers.begin(),timers.end(),&deadTimer,TimerEntryPtrCmp()); //find the beginning of all the non-repeating timers we're clearing
00056   for(timer_it_t it=last_it; it!=timers.end(); it++) // delete all of them
00057     delete *it;
00058   timers.erase(last_it,timers.end()); //and then remove them from the timer list
00059   //  if(process.size()>0) chkTimers();
00060   //    cout << "done" << endl;
00061 }
00062 
00063 /*! timers are unique by EventListener and source ID - can't have two timers for the same el and sid\n
00064  *  a delay of 0 with repeating will cause an event to be sent at every opportunity, use sparingly\n
00065  *  a delay of -1U will call removeTimer() if it already exists, otherwise is ignored\n
00066  *
00067  *  To add a timer, you can also call addListener() with EventBase::timerEGID and the sid
00068  *  and delay (in the EventBase::duration field) - this method will simply cause this
00069  *  function to be called internally.
00070  *
00071  *  @param el the EventListener to send the timer event to
00072  *  @param sid the source ID to use on that event (if you need to send more info, send a pointer to a struct of your devising, typecasted as int)
00073  *  @param delay the delay between the first (and future) calls
00074  *  @param repeat set to true if you want to keep receiving this event, otherwise it will only send once */
00075 void EventRouter::addTimer(EventListener* el, unsigned int sid, unsigned int delay, bool repeat) {
00076   if(delay==-1U) {
00077     removeTimer(el,sid);
00078     return;
00079   }
00080   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00081     if((*it)->el==el && (*it)->sid==sid) {
00082       (*it)->Set(delay,repeat);
00083       // now put that timer back into the correct place in the ordering (think before touching this! ;)
00084       if(it!=timers.begin() && (*it)->next<(*(it-1))->next)
00085         rotate(upper_bound(timers.begin(),it,*it,TimerEntryPtrCmp()),it,it+1);
00086       else if(it+1!=timers.end() && (*it)->next>(*(it+1))->next)
00087         rotate(it,it+1,lower_bound(it+1,timers.end(),*it,TimerEntryPtrCmp()));
00088       return;
00089     }
00090   //didn't find a pre-existing one
00091   TimerEntry * add=new TimerEntry(el,sid,delay,repeat);
00092   timers.insert(lower_bound(timers.begin(),timers.end(),add,TimerEntryPtrCmp()),add);
00093   //  chkTimers();
00094 }
00095 
00096 void EventRouter::removeTimer(EventListener* el) {
00097   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00098     if((*it)->el==el) {
00099       delete *it;
00100       *it=NULL;
00101     }
00102   timers.erase(remove(timers.begin(),timers.end(),(const TimerEntry*)NULL),timers.end());
00103 }
00104 
00105 void EventRouter::removeTimer(EventListener* el, unsigned int sid) {
00106   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00107     if((*it)->el==el && (*it)->sid==sid) {
00108       delete *it;
00109       timers.erase(it);
00110       return;
00111     }
00112 }
00113 
00114 void EventRouter::removeAllTimers() {
00115   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00116     delete *it;
00117   timers.erase(timers.begin(),timers.end());
00118 }
00119 
00120 void EventRouter::addListener(EventListener* el, EventBase::EventGeneratorID_t egid) {
00121   if(egid==EventBase::timerEGID)
00122     printf("WARNING: The use of addListener with timerEGID is deprecated,\n"
00123                  "         please see http://bugs.tekkotsu.org/show_bug.cgi?id=89\n");
00124   bool hadListener=hasListeners(egid);
00125   listeners.addMapping(el,egid); 
00126   if(!hadListener)
00127     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00128   else
00129     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00130 }
00131 void EventRouter::addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) {
00132   if(egid==EventBase::timerEGID)
00133     printf("WARNING: The use of addListener with timerEGID is deprecated,\n"
00134                  "         please see http://bugs.tekkotsu.org/show_bug.cgi?id=89\n");
00135   bool hadListener=hasListeners(egid);
00136   for(unsigned int et=0; et<EventBase::numETIDs; et++)
00137     listeners.addMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
00138   if(!hadListener)
00139     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00140   else
00141     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00142 }
00143 void EventRouter::addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
00144   if(egid==EventBase::timerEGID)
00145     printf("WARNING: The use of addListener with timerEGID is deprecated,\n"
00146                  "         please see http://bugs.tekkotsu.org/show_bug.cgi?id=89\n");
00147   bool hadListener=hasListeners(egid);
00148   listeners.addMapping(el,egid,sid,etid);
00149   if(!hadListener)
00150     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00151   else
00152     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00153 }
00154 void EventRouter::addListener(EventListener* el, const EventBase& e) {
00155   if(e.getGeneratorID()==EventBase::timerEGID) {
00156     printf("WARNING: The use of addListener with timerEGID is deprecated,\n"
00157                  "         please see http://bugs.tekkotsu.org/show_bug.cgi?id=89\n");
00158     addTimer(el,e.getSourceID(),e.getDuration());
00159   } else {
00160     bool hadListener=hasListeners(e.getGeneratorID());
00161     listeners.addMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID());
00162     if(!hadListener)
00163       postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::activateETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00164     else
00165       postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00166   }
00167 }
00168 
00169 void EventRouter::removeListener(EventListener* el) {
00170   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) {
00171     EventBase::EventGeneratorID_t egid=(EventBase::EventGeneratorID_t)eg;
00172     if(!listeners.removeMapping(el,egid))
00173       continue; //nothing was removed, don't want to clean up or throw an event
00174     listeners.clean(egid);
00175     if(!hasListeners(egid))
00176       postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00177     else
00178       postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00179   }
00180   removeTimer(el); //this should go away when we implement bug 89
00181 }
00182 void EventRouter::removeListener(EventListener* el, EventBase::EventGeneratorID_t egid) {
00183   if(egid==EventBase::timerEGID) {
00184     printf("WARNING: The use of removeListener with timerEGID is deprecated,\n"
00185            "         please see http://bugs.tekkotsu.org/show_bug.cgi?id=89\n");
00186     removeTimer(el);
00187   } else {
00188     if(!listeners.removeMapping(el,egid))
00189       return; //nothing was removed, don't want to clean up or throw an event
00190     listeners.clean(egid);
00191     if(!hasListeners(egid))
00192       postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00193     else
00194       postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00195   }
00196 }
00197 void EventRouter::removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) {
00198   if(egid==EventBase::timerEGID) {
00199     printf("WARNING: The use of removeListener with timerEGID is deprecated,\n"
00200            "         please see http://bugs.tekkotsu.org/show_bug.cgi?id=89\n");
00201     removeTimer(el,sid);
00202   } else {
00203     unsigned int removed=0;
00204     for(unsigned int et=0; et<EventBase::numETIDs; et++)
00205       removed+=listeners.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
00206     if(!removed)
00207       return; //nothing was removed, don't want to clean up or throw an event
00208     listeners.clean(egid);
00209     if(!hasListeners(egid))
00210       postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00211     else
00212       postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00213   }
00214 }
00215 void EventRouter::removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
00216   if(egid==EventBase::timerEGID) {
00217     printf("WARNING: The use of removeListener with timerEGID is deprecated,\n"
00218            "         please see http://bugs.tekkotsu.org/show_bug.cgi?id=89\n");
00219     if(etid==EventBase::statusETID)
00220       removeTimer(el,sid);
00221   } else {
00222     if(!listeners.removeMapping(el,egid,sid,etid))
00223       return; //nothing was removed, don't want to clean up or throw an event
00224     listeners.clean(egid);
00225     if(!hasListeners(egid))
00226       postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00227     else
00228       postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00229   }
00230 }
00231 void EventRouter::removeListener(EventListener* el, const EventBase& e) {
00232   if(e.getGeneratorID()==EventBase::timerEGID) {
00233     printf("WARNING: The use of removeListener with timerEGID is deprecated,\n"
00234            "         please see http://bugs.tekkotsu.org/show_bug.cgi?id=89\n");
00235     removeTimer(el,e.getSourceID());
00236   } else {
00237     if(!listeners.removeMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()))
00238       return; //nothing was removed, don't want to clean up or throw an event
00239     listeners.clean(e.getGeneratorID());
00240     if(!hasListeners(e.getGeneratorID()))
00241       postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::deactivateETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],0));
00242     else
00243       postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00244   }
00245 }
00246 
00247 void EventRouter::addTrapper(EventTrapper* el, const EventBase& e) {
00248   bool hadListener=hasListeners(e.getGeneratorID());
00249   trappers.addMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID());
00250   if(!hadListener)
00251     postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::activateETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00252   else
00253     postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00254 }
00255 /*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
00256 void EventRouter::addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid) {
00257   bool hadListener=hasListeners(egid);
00258   trappers.addMapping(el,egid);
00259   if(!hadListener)
00260     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00261   else
00262     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00263 }
00264 /*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
00265 void EventRouter::addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) {
00266   bool hadListener=hasListeners(egid);
00267   for(unsigned int et=0; et<EventBase::numETIDs; et++)
00268     trappers.addMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
00269   if(!hadListener)
00270     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00271   else
00272     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00273 }
00274 /*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
00275 void EventRouter::addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
00276   bool hadListener=hasListeners(egid);
00277   trappers.addMapping(el,egid,sid,etid);
00278   if(!hadListener)
00279     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00280   else
00281     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00282 }
00283 
00284 /*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
00285 void EventRouter::addTrapper(EventTrapper* el) {
00286   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
00287     addTrapper(el,(EventBase::EventGeneratorID_t)eg);
00288 }
00289 
00290 
00291 void EventRouter::removeTrapper(EventTrapper* el, const EventBase& e) {
00292   if(!trappers.removeMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()))
00293     return; //nothing was removed, don't want to clean up or throw an event
00294   trappers.clean(e.getGeneratorID());
00295   if(!hasListeners(e.getGeneratorID()))
00296     postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::deactivateETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],0));
00297   else
00298     postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00299 }
00300 void EventRouter::removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid) {
00301   if(!trappers.removeMapping(el,egid))
00302     return; //nothing was removed, don't want to clean up or throw an event
00303   trappers.clean(egid);
00304   if(!hasListeners(egid))
00305     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00306   else
00307     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00308 }
00309 void EventRouter::removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) {
00310   int removed=0;
00311   for(unsigned int et=0; et<EventBase::numETIDs; et++)
00312     removed+=trappers.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
00313   if(!removed)
00314     return; //nothing was removed, don't want to clean up or throw an event
00315   trappers.clean(egid);
00316   if(!hasListeners(egid))
00317     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00318   else
00319     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00320 }
00321 void EventRouter::removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
00322   if(!trappers.removeMapping(el,egid,sid,etid))
00323     return; //nothing was removed, don't want to clean up or throw an event
00324   trappers.clean(egid);
00325   if(!hasListeners(egid))
00326     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00327   else
00328     postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00329 }
00330 
00331 void EventRouter::removeTrapper(EventTrapper* el) {
00332   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
00333     removeTrapper(el,(EventBase::EventGeneratorID_t)eg);
00334 }
00335 
00336 void EventRouter::processEventBuffer() { //clears buffered events
00337   if(events.size()>0)
00338     doSendBuffer();
00339 }
00340 void EventRouter::doSendBuffer() {
00341   if(doSendBufferLock) {
00342     std::cout << "*** WARNING recursive call to doSendBuffer()" << std::endl;
00343     return;
00344   }
00345   doSendBufferLock=true;
00346   unsigned int start=get_time();
00347   //  doSendEvent(EventBase(EventBase::eventRouterEGID,0,EventBase::activateETID,0));
00348   //important to use indexes instead of iterators in case the event listeners decide to post more events during processing
00349   for(unsigned int i=0; i<events.size(); i++) {
00350     doSendEvent(*events[i]);
00351     delete events[i];
00352   }
00353   events.erase(events.begin(),events.end());
00354   doSendBufferLock=false;
00355   lastBufClear=start;
00356   //  doSendEvent(EventBase(EventBase::eventRouterEGID,0,EventBase::deactivateETID,get_time()-start));
00357 }
00358 
00359 void EventRouter::processEvent(const EventBase& e) {
00360   // want to make sure we don't send events out of order...
00361   if(events.size()>0)
00362     doSendBuffer();
00363   doSendEvent(e);
00364 }
00365 void EventRouter::doSendEvent(const EventBase& e) {
00366   //  cout << "doSendEvent("<<e.getName()<<")..." << flush;
00367   std::vector<EventTrapper*> t;
00368   trappers.getMapping(e,t);
00369   for(std::vector<EventTrapper*>::iterator it=t.begin(); it!=t.end(); it++)
00370     if(trappers.verifyMapping(*it,e)) {
00371       try {
00372         if((*it)->trapEvent(e))
00373           return;
00374       } catch(const std::exception& ex) {
00375         std::string msg="Occurred while processing event "+e.getName()+" by ";
00376         if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(*it))
00377           msg+="trapper "+beh->getName();
00378         else
00379           msg+="unnamed EventTrapper";
00380         if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
00381           throw;
00382       } catch(...) {
00383         std::string msg="Occurred while processing event "+e.getName()+" by ";
00384         if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(*it))
00385           msg+="trapper "+beh->getName();
00386         else
00387           msg+="unnamed EventTrapper";
00388         if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
00389           throw;
00390       }
00391     }
00392   std::vector<EventListener*> l;
00393   listeners.getMapping(e,l);
00394   for(std::vector<EventListener*>::iterator it=l.begin(); it!=l.end(); it++)
00395     if(listeners.verifyMapping(*it,e)) {
00396       try {
00397         (*it)->processEvent(e);
00398       } catch(const std::exception& ex) {
00399         std::string msg="Occurred while processing event "+e.getName()+" by ";
00400         if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(*it))
00401           msg+="listener "+beh->getName();
00402         else
00403           msg+="unnamed EventListener";
00404         if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
00405           throw;
00406       } catch(...) {
00407         std::string msg="Occurred while processing event "+e.getName()+" by ";
00408         if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(*it))
00409           msg+="listener "+beh->getName();
00410         else
00411           msg+="unnamed EventListener";
00412         if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
00413           throw;
00414       }
00415     }
00416   //  cout << "done." << flush;
00417 }
00418 
00419 EventRouter::EventMapper::EventMapper() {
00420   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
00421     for(unsigned int et=0; et<EventBase::numETIDs; et++)
00422       filteredevents[eg][et]=NULL;
00423 }
00424 
00425 void EventRouter::EventMapper::addMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
00426   if(filteredevents[egid][etid]==NULL) //if this is the first subscriber to this EGID and ETID
00427     filteredevents[egid][etid]=new SIDtoListenerVectorMap_t(); 
00428   SIDtoListenerVectorMap_t::iterator it=filteredevents[egid][etid]->find(sid); // now find subscribers to the source id as well
00429   std::vector<void*>* elv=NULL;
00430   if(it==filteredevents[egid][etid]->end()) { // if this is the first subscriber to the source ID
00431     std::pair<const unsigned int,std::vector<void*> > p(sid,std::vector<void*>());
00432     //    p.first=sid; //p.second is a vector, only needs to be constructed
00433     filteredevents[egid][etid]->insert(p);
00434     elv=&(*filteredevents[egid][etid]->find(sid)).second;
00435   } else {
00436     elv=&(*it).second;
00437   }
00438   elv->push_back(el); // now that everything's set up, we can add the listener
00439 }
00440 
00441 bool EventRouter::EventMapper::removeMapping(void* el, EventBase::EventGeneratorID_t egid) {
00442   // remove listener from allevents
00443   unsigned int numlist=allevents[egid].size();
00444   allevents[egid].erase(remove(allevents[egid].begin(),allevents[egid].end(),el),allevents[egid].end());
00445   bool hadListener=allevents[egid].size()!=numlist;
00446   
00447   // now remove listener from all of the filtered events
00448   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00449     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00450     if(mapping!=NULL) { // if there are subscribers to this egid/etid
00451       SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
00452       for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++) {// go through each sourceID, delete EL
00453         std::vector<void*> * v=&(*mapit).second;
00454         std::vector<void*>::iterator last=remove(v->begin(),v->end(),el);
00455         if(last!=v->end()) {
00456           hadListener=true;
00457           v->erase(last,v->end());
00458         }
00459       }
00460     }
00461   }
00462   return hadListener;
00463 }
00464 
00465 bool EventRouter::EventMapper::removeMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
00466   bool hadListener=false;
00467   SIDtoListenerVectorMap_t* mapping=filteredevents[egid][etid];
00468   if(mapping!=NULL) { // if there are subscribers to this egid/etid
00469     SIDtoListenerVectorMap_t::iterator mapit=mapping->find(sid);
00470     if(mapit!=mapping->end()) {
00471       std::vector<void*> * v=&(*mapit).second;
00472       std::vector<void*>::iterator last=remove(v->begin(),v->end(),el);
00473       if(last!=v->end()) {
00474         hadListener=true;
00475         v->erase(last,v->end());
00476       }
00477     }
00478   }
00479   return hadListener;
00480 }
00481 
00482 void EventRouter::EventMapper::clean() {
00483   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
00484     clean((EventBase::EventGeneratorID_t)eg);
00485 }
00486 void EventRouter::EventMapper::clean(EventBase::EventGeneratorID_t egid) {
00487   // first, remove any empty sid vectors from all the mappings
00488   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00489     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00490     if(mapping!=NULL) { // if there are subscribers to this egid/etid
00491       SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
00492       bool done=false;
00493       while(!done) {
00494         done=true;
00495         for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++) { // go through each sourceID vector
00496           if((*mapit).second.size()==0) {
00497             mapping->erase(mapit);
00498             done=false;
00499             break;
00500           }
00501         }
00502       }
00503     }
00504   }
00505   // now remove any empty mappings
00506   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00507     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00508     if(mapping!=NULL) { // if there are subscribers to this egid/etid
00509       if(mapping->size()==0) {
00510         delete mapping;
00511         filteredevents[egid][et]=NULL;
00512       }
00513     }
00514   }
00515 }
00516 
00517 void EventRouter::EventMapper::clear() {
00518   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) {
00519     for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00520       SIDtoListenerVectorMap_t* mapping=filteredevents[eg][et];
00521       if(mapping!=NULL) { // don't beat a dead horse!
00522         mapping->erase(mapping->begin(),mapping->end());
00523         delete mapping;
00524         filteredevents[eg][et]=NULL;
00525       }
00526     }
00527   }
00528 }
00529 
00530 bool EventRouter::EventMapper::hasMapping(EventBase::EventGeneratorID_t egid) {
00531   if(allevents[egid].size()>0)
00532     return true;
00533   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00534     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00535     if(mapping!=NULL) {
00536       SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
00537       for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++)
00538         if((*mapit).second.size()>0)
00539           return true;
00540     }
00541   }
00542   return false;
00543 }
00544 
00545 bool EventRouter::EventMapper::hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid) {
00546   if(allevents[egid].size()>0)
00547     return true;
00548   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00549     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00550     if(mapping!=NULL) {
00551       SIDtoListenerVectorMap_t::iterator mapit=mapping->find(sid);
00552       if(mapit!=mapping->end() && (*mapit).second.size()>0)
00553         return true;
00554     }
00555   }
00556   return false;
00557 }
00558 
00559 bool EventRouter::EventMapper::hasMapping(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
00560   if(allevents[egid].size()>0)
00561     return true;
00562   SIDtoListenerVectorMap_t* mapping=filteredevents[egid][etid];
00563   if(mapping!=NULL) {
00564     SIDtoListenerVectorMap_t::iterator mapit=mapping->find(sid);
00565     if(mapit!=mapping->end())
00566       return ((*mapit).second.size()>0);
00567   }
00568   return false;
00569 }
00570 
00571 template<class T>
00572 void EventRouter::EventMapper::getMapping(const EventBase& e, std::vector<T*>& ls) {
00573   // first get all the filtered subscribers (tricky!)
00574   std::vector<void*>* elv=NULL;
00575   SIDtoListenerVectorMap_t* sidtovm=filteredevents[e.getGeneratorID()][e.getTypeID()];
00576   if(sidtovm!=NULL) { // if there's a map (at least one EL is filtering on this EGID and ETID)
00577     SIDtoListenerVectorMap_t::iterator mapit=sidtovm->find(e.getSourceID()); // find listening for this source id
00578     if(mapit!=sidtovm->end()) { // if there's at least one is filtering on this sourceID as well
00579       elv=&(*mapit).second; // now go through them all
00580       for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00581         ls.push_back(static_cast<T*>(*elit));
00582     }
00583   }
00584   // now get the 'all events' subscribers
00585   elv=&allevents[e.getGeneratorID()];
00586   for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00587     ls.push_back(static_cast<T*>(*elit));
00588 }
00589 
00590 bool EventRouter::EventMapper::verifyMapping(void * listener, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
00591   // first check the 'all events' subscribers
00592   std::vector<void*>* elv=&allevents[egid];
00593   for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00594     if(*elit==listener)
00595       return true;
00596   
00597   // then check all the filtered subscribers (tricky!)
00598   SIDtoListenerVectorMap_t* sidtovm=filteredevents[egid][etid];
00599   if(sidtovm!=NULL) { // if there's a map (at least one EL is filtering on this EGID and ETID)
00600     SIDtoListenerVectorMap_t::iterator mapit=sidtovm->find(sid); // find listening for this source id
00601     if(mapit!=sidtovm->end()) { // if there's at least one is filtering on this sourceID as well
00602       elv=&(*mapit).second; // now go through them all
00603       for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00604         if(*elit==listener)
00605           return true;
00606     }
00607   }
00608 
00609   // if we haven't found it, doesn't exist:
00610   return false;
00611 }
00612 
00613 bool EventRouter::EventMapper::verifyMappingAll(void* listener, EventBase::EventGeneratorID_t egid) {
00614   std::vector<void*>* elv=&allevents[egid];
00615   for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00616     if(*elit==listener)
00617       return true;
00618   // if not in the all listeners, can't be listening for *every* source id
00619   return false;
00620 }
00621 
00622 bool EventRouter::EventMapper::verifyMappingAny(void* listener, EventBase::EventGeneratorID_t egid) {
00623   // first check the 'all events' subscribers
00624   std::vector<void*>* elv=&allevents[egid];
00625   for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00626     if(*elit==listener)
00627       return true;
00628   
00629   // then check all the filtered subscribers (tricky!)
00630   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00631     SIDtoListenerVectorMap_t* sidtovm=filteredevents[egid][et];
00632     if(sidtovm!=NULL) { // if there's a map (at least one EL is filtering on this EGID and ETID)
00633       SIDtoListenerVectorMap_t::iterator mapit=sidtovm->begin(); // for each of the source ids
00634       for(;mapit!=sidtovm->end();mapit++) {
00635         elv=&(*mapit).second; // now go through them all
00636         for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00637           if(*elit==listener)
00638             return true;
00639       }
00640     }
00641   }
00642 
00643   // if we haven't found any, none exist:
00644   return false;
00645 }
00646 
00647 bool EventRouter::EventMapper::verifyMappingAll(void* listener, EventBase::EventGeneratorID_t egid, unsigned int sid) {
00648   // first check the 'all events' subscribers
00649   std::vector<void*>* elv=&allevents[egid];
00650   for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00651     if(*elit==listener)
00652       return true;
00653   
00654   // then check all the filtered subscribers (tricky!)
00655   // must be found in ALL etids
00656   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00657     SIDtoListenerVectorMap_t* sidtovm=filteredevents[egid][et];
00658     if(sidtovm==NULL)
00659       return false;
00660     // there's a map (at least one EL is filtering on this EGID and ETID)
00661     SIDtoListenerVectorMap_t::iterator mapit=sidtovm->find(sid); // find listening for this source id
00662     if(mapit==sidtovm->end())
00663       return false;
00664     // there's at least one is filtering on this sourceID as well
00665     elv=&(*mapit).second; // now go through them all
00666     std::vector<void*>::iterator elit=elv->begin();
00667     while(elit!=elv->end() && *elit!=listener)
00668       elit++;
00669     if(elit==elv->end())
00670       return false;
00671     //if we didn't return false, we found a match... continue checking other ETIDs
00672   }
00673 
00674   // we only got here if we *did* find listener in each of the ETIDs
00675   return true;
00676 }
00677 
00678 bool EventRouter::EventMapper::verifyMappingAny(void* listener, EventBase::EventGeneratorID_t egid, unsigned int sid) {
00679   // first check the 'all events' subscribers
00680   std::vector<void*>* elv=&allevents[egid];
00681   for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00682     if(*elit==listener)
00683       return true;
00684   
00685   // then check all the filtered subscribers (tricky!)
00686   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00687     SIDtoListenerVectorMap_t* sidtovm=filteredevents[egid][et];
00688     if(sidtovm!=NULL) { // if there's a map (at least one EL is filtering on this EGID and ETID)
00689       SIDtoListenerVectorMap_t::iterator mapit=sidtovm->find(sid); // find listening for this source id
00690       if(mapit!=sidtovm->end()) { // if there's at least one is filtering on this sourceID as well
00691         elv=&(*mapit).second; // now go through them all
00692         for(std::vector<void*>::iterator elit=elv->begin(); elit!=elv->end(); elit++)
00693           if(*elit==listener)
00694             return true;
00695       }
00696     }
00697   }
00698 
00699   // if we haven't found it, doesn't exist:
00700   return false;
00701 }
00702 
00703 /*! @file
00704  * @brief Implements EventRouter class, for distribution and trapping of events to listeners
00705  * @author ejt (Creator)
00706  *
00707  * $Author: ejt $
00708  * $Name: tekkotsu-2_4_1 $
00709  * $Revision: 1.20 $
00710  * $State: Exp $
00711  * $Date: 2005/08/16 18:43:04 $
00712  */
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 // Use hasListeners(*) it's faster, i doubt anyone would really care how many... (but just in case...)
00721 /*
00722 unsigned int EventRouter::numListeners(EventBase::EventGeneratorID_t egid) {
00723   unsigned int ans=allevents[egid].size();
00724   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00725     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00726     if(mapping!=NULL) {
00727       SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
00728       for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++)
00729         ans+=(*mapit).second.size();
00730     }
00731   }
00732   return ans;
00733 }
00734 
00735 bool EventRouter::numListeners(EventBase::EventGeneratorID_t egid, unsigned int sid) {
00736   unsigned int ans=allevents[egid].size();
00737   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00738     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00739     if(mapping!=NULL) {
00740       SIDtoListenerVectorMap_t::iterator mapit=mapping->find(sid);
00741       if(mapit!=mapping->end())
00742         ans+=(*mapit).second.size();
00743     }
00744   }
00745   return false;
00746 }
00747 
00748 unsigned int EventRouter::numListeners(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
00749   unsigned int ans=allevents[egid].size();
00750   SIDtoListenerVectorMap_t* mapping=filteredevents[egid][etid];
00751   if(mapping!=NULL) {
00752     SIDtoListenerVectorMap_t::iterator mapit=mapping->find(sid);
00753     if(mapit!=mapping->end())
00754       ans+=(*mapit).second.size();
00755   }
00756   return ans;
00757 }
00758 */

Tekkotsu v2.4.1
Generated Tue Aug 16 16:32:47 2005 by Doxygen 1.4.4