Tekkotsu 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 #include "Events/TimerEvent.h"
00007 #include "EventTranslator.h"
00008 #include "Shared/string_util.h"
00009 #include "Shared/debuget.h"
00010 
00011 #ifndef TGT_IS_DYNAMIC
00012 #  include "Events/RemoteRouter.h"
00013 #  include "Events/EventProxy.h"
00014 #endif
00015 
00016 #include <sstream>
00017 
00018 #ifndef PLATFORM_APERIOS
00019 #  include "IPC/Thread.h"
00020 #  include "Shared/MarkScope.h"
00021 #  include "IPC/ThreadedMessageQueue.h"
00022 #endif
00023 
00024 EventRouter * erouter=NULL;
00025 
00026 EventRouter::EventRouter() :
00027 #ifndef TGT_IS_DYNAMIC
00028   proxies(), rrouters(), sck(NULL), nextProxyPort(defaultPort+1),
00029 #endif
00030   timers(), trappers(), listeners(), postings()
00031 #ifndef PLATFORM_APERIOS
00032   , eventQueue(new ThreadedMessageQueue<EventBase*>)
00033 #endif
00034 {
00035   for(unsigned int i=0; i<ProcessID::NumProcesses; ++i) {
00036     forwards[i]=NULL;
00037   }
00038 }
00039 
00040 EventRouter::~EventRouter() {
00041 #ifndef PLATFORM_APERIOS
00042   delete eventQueue;
00043   eventQueue=NULL;
00044 #endif
00045   reset();
00046   removeAllTimers();
00047   for(unsigned int i=0; i<ProcessID::NumProcesses; ++i) {
00048     delete forwards[i];
00049     forwards[i]=NULL;
00050   }
00051 
00052 #ifndef TGT_IS_DYNAMIC
00053   //Delete all the event proxies
00054   //printf("Deleting %zu EventProxies and %zu RemoteRouters\n", proxies.size(), rrouters.size());
00055   for (std::list<EventProxy *>::iterator pi = proxies.begin(); pi != proxies.end(); pi++)
00056     delete *pi;
00057   
00058   //Delete the remote routers
00059   for (std::map<int, RemoteRouter *>::iterator mi = rrouters.begin(); mi != rrouters.end(); mi++)
00060     delete (*mi).second;
00061 #endif
00062   
00063 }
00064 
00065 void EventRouter::postEvent(EventBase* e) { processEvent(*e); delete e; }
00066 
00067 #ifndef PLATFORM_APERIOS
00068 void EventRouter::queueEvent(EventBase* e) { eventQueue->send(e); }
00069 
00070 void EventRouter::requeueEvent(EventBase* e) { eventQueue->remove(SameID(e)); queueEvent(e); }
00071 #endif
00072 
00073 
00074 //! @todo handle recursive calls
00075 void EventRouter::processTimers() {
00076   //    cout << "processTimers..." << flush;
00077   unsigned int curtime=get_time();
00078   TimerEntry curTimer(curtime);
00079   timer_it_t last_it=upper_bound(timers.begin(),timers.end(),&curTimer,TimerEntryPtrCmp());
00080   std::vector<TimerEntry*> process(timers.begin(),last_it); //copy these out for safe keeping
00081   for(timer_it_t it=process.begin(); it!=process.end(); it++) //increment the timers we're processing
00082     if(!(*it)->repeat)
00083       (*it)->next=(unsigned int)-1;
00084     else if((*it)->delay==0)
00085       (*it)->next=curtime+1;
00086     else while((*it)->next<=curtime)
00087       (*it)->next+=(*it)->delay;
00088   sort(timers.begin(),last_it,TimerEntryPtrCmp()); //re-sort the timers we're processing (at the beginning of timers)
00089   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)
00090   //  if(process.size()>0) chkTimers();
00091   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
00092     if(find(timers.begin(),timers.end(),*it)==timers.end())
00093       continue; // the timer has been removed during processesing of a previous timer...
00094     TimerEvent e((*it)->el,EventBase::timerEGID,(*it)->sid,EventBase::statusETID,(*it)->next-(*it)->delay);
00095     try {
00096       (*it)->el->processEvent(e);
00097     } catch(const std::exception& ex) {
00098       std::string msg="Occurred while processing event "+e.getName()+" by ";
00099       if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>((*it)->el))
00100         msg+="listener "+beh->getName();
00101       else
00102         msg+="unnamed EventListener";
00103       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
00104         throw;
00105     } catch(...) {
00106       std::string msg="Occurred while processing event "+e.getName()+" by ";
00107       if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>((*it)->el))
00108         msg+="listener "+beh->getName();
00109       else
00110         msg+="unnamed EventListener";
00111       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
00112         throw;
00113     }
00114     postEvent(e);
00115   }
00116   //  if(process.size()>0) chkTimers();
00117   static const TimerEntry deadTimer((unsigned int)-1); // matches all the dead ones as set in the incrementation phase
00118   last_it=lower_bound(timers.begin(),timers.end(),&deadTimer,TimerEntryPtrCmp()); //find the beginning of all the non-repeating timers we're clearing
00119   for(timer_it_t it=last_it; it!=timers.end(); it++) // delete all of them
00120     delete *it;
00121   timers.erase(last_it,timers.end()); //and then remove them from the timer list
00122   //  if(process.size()>0) chkTimers();
00123   //    cout << "done" << endl;
00124 }
00125 
00126 /*! timers are unique by EventListener and source ID - can't have two timers for the same el and sid\n
00127  *  a delay of 0 with repeating will cause an event to be sent at every opportunity, use sparingly\n
00128  *  a delay of -1U will call removeTimer() if it already exists, otherwise is ignored\n
00129  *
00130  *  @param el the EventListener to send the timer event to
00131  *  @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)
00132  *  @param delay the delay between the first (and future) calls
00133  *  @param repeat set to true if you want to keep receiving this event, otherwise it will only send once */
00134 void EventRouter::addTimer(EventListener* el, size_t sid, unsigned int delay, bool repeat) {
00135   if(delay==-1U) {
00136     removeTimer(el,sid);
00137     return;
00138   }
00139   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00140     if((*it)->el==el && (*it)->sid==sid) {
00141       (*it)->Set(delay,repeat);
00142       // now put that timer back into the correct place in the ordering (think before touching this! ;)
00143       if(it!=timers.begin() && (*it)->next<(*(it-1))->next)
00144         rotate(upper_bound(timers.begin(),it,*it,TimerEntryPtrCmp()),it,it+1);
00145       else if(it+1!=timers.end() && (*it)->next>(*(it+1))->next)
00146         rotate(it,it+1,lower_bound(it+1,timers.end(),*it,TimerEntryPtrCmp()));
00147       return;
00148     }
00149   //didn't find a pre-existing one
00150   TimerEntry * add=new TimerEntry(el,sid,delay,repeat);
00151   timers.insert(lower_bound(timers.begin(),timers.end(),add,TimerEntryPtrCmp()),add);
00152   //  chkTimers();
00153 }
00154 
00155 void EventRouter::removeTimer(const EventListener* el) {
00156   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00157     if((*it)->el==el) {
00158       delete *it;
00159       *it=NULL;
00160     }
00161   timers.erase(std::remove(timers.begin(),timers.end(),(const TimerEntry*)NULL),timers.end());
00162 }
00163 
00164 void EventRouter::removeTimer(const EventListener* el, size_t sid) {
00165   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00166     if((*it)->el==el && (*it)->sid==sid) {
00167       delete *it;
00168       timers.erase(it);
00169       return;
00170     }
00171 }
00172 
00173 void EventRouter::removeAllTimers() {
00174   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00175     delete *it;
00176   timers.erase(timers.begin(),timers.end());
00177 }
00178 
00179 const EventRouter::TimerEntry* EventRouter::getNextTimerInfo(const EventListener* el) {
00180   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00181     if((*it)->el==el)
00182       return *it;
00183   return NULL;
00184 }
00185 
00186 const EventRouter::TimerEntry* EventRouter::getNextTimerInfo(const EventListener* el, size_t sid) {
00187   for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
00188     if((*it)->el==el && (*it)->sid==sid)
00189       return *it;
00190   return NULL;
00191 }
00192 
00193 void EventRouter::addListener(EventListener* el, EventBase::EventGeneratorID_t egid) {
00194   bool hadListener=hasListeners(egid);
00195   listeners.addMapping(el,egid); 
00196   if(!hadListener)
00197     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00198   else
00199     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00200 }
00201 void EventRouter::addListener(EventListener* el, EventBase::EventGeneratorID_t egid, size_t sid) {
00202   bool hadListener=hasListeners(egid);
00203   for(unsigned int et=0; et<EventBase::numETIDs; et++)
00204     listeners.addMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
00205   if(!hadListener)
00206     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00207   else
00208     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00209 }
00210 void EventRouter::addListener(EventListener* el, EventBase::EventGeneratorID_t egid, size_t sid, EventBase::EventTypeID_t etid) {
00211   bool hadListener=hasListeners(egid);
00212   listeners.addMapping(el,egid,sid,etid);
00213   if(!hadListener)
00214     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00215   else
00216     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00217 }
00218 void EventRouter::addListener(EventListener* el, const EventBase& e) {
00219   bool hadListener=hasListeners(e.getGeneratorID());
00220   listeners.addMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID());
00221   if(!hadListener)
00222     postEvent(EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::activateETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00223   else
00224     postEvent(EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00225 }
00226 
00227 #ifndef TGT_IS_DYNAMIC
00228 //Start of remote event code------------------
00229 void EventRouter::addRemoteListener(EventListener* el, int host,
00230                   EventBase::EventGeneratorID_t egid) {
00231   RemoteRouter &rr = remoteRouterForHost(host);
00232   addListener(el, egid);
00233   rr.addListener(egid);
00234 }
00235 
00236 void EventRouter::addRemoteListener(EventListener* el, int host,
00237                   EventBase::EventGeneratorID_t egid, size_t sid) {
00238   RemoteRouter &rr = remoteRouterForHost(host);
00239   addListener(el, egid, sid);
00240   rr.addListener(egid, sid);
00241 }
00242 
00243 void EventRouter::addRemoteListener(EventListener* el, int host, const EventBase& e){
00244   addRemoteListener(el, host, e.getGeneratorID(), e.getSourceID(), e.getTypeID());
00245 }
00246 
00247 void EventRouter::addRemoteListener(EventListener* el, int host,
00248                   EventBase::EventGeneratorID_t egid, size_t sid,
00249                   EventBase::EventTypeID_t etid) {
00250   RemoteRouter &rr = remoteRouterForHost(host);
00251   addListener(el, egid, sid, etid);
00252   rr.addListener(egid, sid, etid);
00253 }
00254 
00255 
00256 void EventRouter::removeRemoteListener(const EventListener* el, int host,
00257                      EventBase::EventGeneratorID_t egid) {
00258   RemoteRouter &rr = remoteRouterForHost(host);
00259   removeListener(el, egid);
00260   rr.removeListener(egid);
00261 }
00262 
00263 void EventRouter::removeRemoteListener(const EventListener* el, int host,
00264                      EventBase::EventGeneratorID_t egid, size_t sid) {
00265   RemoteRouter &rr = remoteRouterForHost(host);
00266   removeListener(el, egid, sid);
00267   rr.removeListener(egid, sid); 
00268 }
00269     
00270 void EventRouter::removeRemoteListener(const EventListener* el, int host,
00271                      const EventBase& e) {
00272   removeRemoteListener(el, host, e.getGeneratorID(), e.getSourceID(), e.getTypeID()); 
00273 }
00274 
00275 void EventRouter::removeRemoteListener(const EventListener* el, int host,
00276                      EventBase::EventGeneratorID_t egid, size_t sid,
00277                      EventBase::EventTypeID_t etid) {
00278   RemoteRouter &rr = remoteRouterForHost(host);
00279   removeListener(el, egid, sid, etid);
00280   rr.removeListener(egid, sid, etid);
00281 }
00282 
00283 
00284 void EventRouter::requestRemoteStateUpdates(int host, RemoteState::StateType type,
00285                       unsigned int interval) {
00286   RemoteRouter &rr = remoteRouterForHost(host);
00287   rr.requestStateUpdates(type, interval);
00288 }
00289 
00290 void EventRouter::stopRemoteStateUpdates(int host, RemoteState::StateType type) {
00291   RemoteRouter &rr = remoteRouterForHost(host);
00292   rr.stopStateUpdates(type);
00293 }
00294 
00295 RemoteRouter &EventRouter::remoteRouterForHost(int host) {
00296   RemoteRouter *rr = rrouters[host];
00297   if (rr) {
00298     printf("Returning existing remote router for host %s\n", string_util::intToStringIP(host).c_str());
00299     return *rr;
00300   } else {
00301     rrouters[host] = rr = new RemoteRouter(host);
00302     printf("Returning new remote router for host %s\n", string_util::intToStringIP(host).c_str());
00303     return *rr;
00304   }
00305 }
00306 
00307 /* This is called in MMCombo.cc on startup. */
00308 bool EventRouter::serveRemoteEventRequests() {
00309   if (sck)
00310     return false;
00311   sck = wireless->socket(Socket::SOCK_STREAM);
00312   wireless->setReceiver(sck, this);
00313   wireless->setDaemon(sck, true);
00314   wireless->listen(sck, EventRouter::defaultPort);
00315   return true;
00316 }
00317 
00318 int EventRouter::processData(char* /* data*/, int bytes) {
00319   if (bytes != sizeof(int)) {
00320     std::cerr << "Unknown data received" << std::endl;
00321     return -1;
00322   }
00323   
00324   int nextPort = nextProxyPort++;
00325   std::cout << "Starting EventProxy on port " << nextPort
00326     << " for host " << string_util::intToStringIP(sck->getPeerAddress()) << std::endl;
00327   proxies.push_back(new EventProxy(nextPort));
00328 
00329   //Send the port to the RemoteRouter
00330   sck->write((byte *)&nextPort, sizeof(int));
00331 
00332   //Start listening again
00333   wireless->close(sck);
00334   
00335   return 0;
00336 }
00337 
00338 //End of remote event code
00339 #endif
00340 
00341 void EventRouter::removeListener(const EventListener* el) {
00342   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) {
00343     EventBase::EventGeneratorID_t egid=(EventBase::EventGeneratorID_t)eg;
00344     if(!listeners.removeMapping(el,egid))
00345       continue; //nothing was removed, don't want to clean up or throw an event
00346     listeners.clean(egid);
00347     if(!hasListeners(egid))
00348       postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00349     else
00350       postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00351   }
00352 }
00353 void EventRouter::removeListener(const EventListener* el, EventBase::EventGeneratorID_t egid) {
00354   if(!listeners.removeMapping(el,egid))
00355     return; //nothing was removed, don't want to clean up or throw an event
00356   listeners.clean(egid);
00357   if(!hasListeners(egid))
00358     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00359   else
00360     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00361 }
00362 void EventRouter::removeListener(const EventListener* el, EventBase::EventGeneratorID_t egid, size_t sid) {
00363   unsigned int removed=0;
00364   for(unsigned int et=0; et<EventBase::numETIDs; et++)
00365     removed+=listeners.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
00366   if(!removed)
00367     return; //nothing was removed, don't want to clean up or throw an event
00368   listeners.clean(egid);
00369   if(!hasListeners(egid))
00370     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00371   else
00372     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00373 }
00374 void EventRouter::removeListener(const EventListener* el, EventBase::EventGeneratorID_t egid, size_t sid, EventBase::EventTypeID_t etid) {
00375   if(!listeners.removeMapping(el,egid,sid,etid))
00376     return; //nothing was removed, don't want to clean up or throw an event
00377   listeners.clean(egid);
00378   if(!hasListeners(egid))
00379     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00380   else
00381     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00382 }
00383 void EventRouter::removeListener(const EventListener* el, const EventBase& e) {
00384   if(!listeners.removeMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()))
00385     return; //nothing was removed, don't want to clean up or throw an event
00386   listeners.clean(e.getGeneratorID());
00387   if(!hasListeners(e.getGeneratorID()))
00388     postEvent(EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::deactivateETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],0));
00389   else
00390     postEvent(EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00391 }
00392 
00393 void EventRouter::addTrapper(EventTrapper* el, const EventBase& e) {
00394   bool hadListener=hasListeners(e.getGeneratorID());
00395   trappers.addMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID());
00396   if(!hadListener)
00397     postEvent(EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::activateETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00398   else
00399     postEvent(EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00400 }
00401 /*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
00402 void EventRouter::addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid) {
00403   bool hadListener=hasListeners(egid);
00404   trappers.addMapping(el,egid);
00405   if(!hadListener)
00406     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00407   else
00408     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00409 }
00410 /*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
00411 void EventRouter::addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, size_t sid) {
00412   bool hadListener=hasListeners(egid);
00413   for(unsigned int et=0; et<EventBase::numETIDs; et++)
00414     trappers.addMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
00415   if(!hadListener)
00416     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00417   else
00418     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00419 }
00420 /*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
00421 void EventRouter::addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, size_t sid, EventBase::EventTypeID_t etid) {
00422   bool hadListener=hasListeners(egid);
00423   trappers.addMapping(el,egid,sid,etid);
00424   if(!hadListener)
00425     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::activateETID,0,EventBase::EventGeneratorNames[egid],1));
00426   else
00427     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00428 }
00429 
00430 /*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
00431 void EventRouter::addTrapper(EventTrapper* el) {
00432   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
00433     addTrapper(el,(EventBase::EventGeneratorID_t)eg);
00434 }
00435 
00436 
00437 void EventRouter::removeTrapper(const EventTrapper* el, const EventBase& e) {
00438   if(!trappers.removeMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()))
00439     return; //nothing was removed, don't want to clean up or throw an event
00440   trappers.clean(e.getGeneratorID());
00441   if(!hasListeners(e.getGeneratorID()))
00442     postEvent(EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::deactivateETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],0));
00443   else
00444     postEvent(EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID,0,EventBase::EventGeneratorNames[e.getGeneratorID()],1));
00445 }
00446 void EventRouter::removeTrapper(const EventTrapper* el, EventBase::EventGeneratorID_t egid) {
00447   if(!trappers.removeMapping(el,egid))
00448     return; //nothing was removed, don't want to clean up or throw an event
00449   trappers.clean(egid);
00450   if(!hasListeners(egid))
00451     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00452   else
00453     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00454 }
00455 void EventRouter::removeTrapper(const EventTrapper* el, EventBase::EventGeneratorID_t egid, size_t sid) {
00456   int removed=0;
00457   for(unsigned int et=0; et<EventBase::numETIDs; et++)
00458     removed+=trappers.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
00459   if(!removed)
00460     return; //nothing was removed, don't want to clean up or throw an event
00461   trappers.clean(egid);
00462   if(!hasListeners(egid))
00463     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00464   else
00465     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00466 }
00467 void EventRouter::removeTrapper(const EventTrapper* el, EventBase::EventGeneratorID_t egid, size_t sid, EventBase::EventTypeID_t etid) {
00468   if(!trappers.removeMapping(el,egid,sid,etid))
00469     return; //nothing was removed, don't want to clean up or throw an event
00470   trappers.clean(egid);
00471   if(!hasListeners(egid))
00472     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID,0,EventBase::EventGeneratorNames[egid],0));
00473   else
00474     postEvent(EventBase(EventBase::erouterEGID,egid,EventBase::statusETID,0,EventBase::EventGeneratorNames[egid],1));
00475 }
00476 
00477 void EventRouter::removeTrapper(const EventTrapper* el) {
00478   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
00479     removeTrapper(el,(EventBase::EventGeneratorID_t)eg);
00480 }
00481 
00482 void EventRouter::setForwardingAgent(ProcessID::ProcessID_t proc, EventTranslator* trans) {
00483   delete forwards[proc];
00484   forwards[proc]=trans;
00485 }
00486 
00487 void EventRouter::processEvent(const EventBase& e) {
00488   // check for forwarding *before* the lock
00489   ProcessID::ProcessID_t pid=ProcessID::getID();
00490   if(pid!=ProcessID::NumProcesses && forwards[pid]!=NULL) {
00491     if(forwards[pid]->trapEvent(e))
00492       return;
00493   }
00494   
00495 #ifndef PLATFORM_APERIOS
00496   static Thread::Lock lk;
00497   MarkScope autolock(lk);
00498 #endif
00499   PostingStatus ps(trappers,listeners,e);
00500   postings.push(&ps);
00501   while(postings.size()>0) {
00502 #ifdef DEBUG
00503     size_t presize=postings.size();
00504     postings.front()->process();
00505     ASSERT(postings.size()==0 || postings.size()==presize,"partial queue completion?");
00506 #else
00507     postings.front()->process();
00508 #endif
00509     if(postings.size()>0) // in case a sub-post took over and finished off the queue
00510       postings.pop();
00511   }
00512 }
00513 
00514 void EventRouter::PostingStatus::process() {
00515   while(tit!=t.end()) {
00516     // increment before processing so if a new post is done during the processing, we pick up on the *next* entry
00517     EventTrapper * et=*tit++;
00518     if(!trappers.verifyMapping(et,e))
00519       continue;
00520     try {
00521       if(et->trapEvent(e))
00522         return;
00523     } catch(const std::exception& ex) {
00524       std::string msg="Occurred while processing event "+e.getName()+" by ";
00525       if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(et))
00526         msg+="trapper "+beh->getName();
00527       else
00528         msg+="unnamed EventTrapper";
00529       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
00530         throw;
00531     } catch(...) {
00532       std::string msg="Occurred while processing event "+e.getName()+" by ";
00533       if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(et))
00534         msg+="trapper "+beh->getName();
00535       else
00536         msg+="unnamed EventTrapper";
00537       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
00538         throw;
00539     }
00540   }
00541   while(lit!=l.end()) {
00542     // increment before processing so if a new post is done during the processing, we pick up on the *next* entry
00543     EventListener * el=*lit++;
00544     if(!listeners.verifyMapping(el,e))
00545       continue;
00546     try {
00547       el->processEvent(e);
00548     } catch(const std::exception& ex) {
00549       std::string msg="Occurred while processing event "+e.getName()+" by ";
00550       if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(el))
00551         msg+="listener "+beh->getName();
00552       else
00553         msg+="unnamed EventListener";
00554       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
00555         throw;
00556     } catch(...) {
00557       std::string msg="Occurred while processing event "+e.getName()+" by ";
00558       if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(el))
00559         msg+="listener "+beh->getName();
00560       else
00561         msg+="unnamed EventListener";
00562       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
00563         throw;
00564     }
00565   }
00566 }
00567 
00568 EventRouter::EventMapper::EventMapper() {
00569   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
00570     for(unsigned int et=0; et<EventBase::numETIDs; et++)
00571       filteredevents[eg][et]=NULL;
00572 }
00573 
00574 void EventRouter::EventMapper::addMapping(void* el, EventBase::EventGeneratorID_t egid, size_t sid, EventBase::EventTypeID_t etid) {
00575   if(filteredevents[egid][etid]==NULL) //if this is the first subscriber to this EGID and ETID
00576     filteredevents[egid][etid]=new SIDtoListenerVectorMap_t(); 
00577   SIDtoListenerVectorMap_t::iterator it=filteredevents[egid][etid]->find(sid); // now find subscribers to the source id as well
00578   std::vector<void*>* elv=NULL;
00579   if(it==filteredevents[egid][etid]->end()) { // if this is the first subscriber to the source ID
00580     std::pair<const size_t,std::vector<void*> > p(sid,std::vector<void*>());
00581     //    p.first=sid; //p.second is a vector, only needs to be constructed
00582     filteredevents[egid][etid]->insert(p);
00583     elv=&(*filteredevents[egid][etid]->find(sid)).second;
00584   } else {
00585     elv=&(*it).second;
00586   }
00587   elv->push_back(el); // now that everything's set up, we can add the listener
00588 }
00589 
00590 bool EventRouter::EventMapper::removeMapping(const void* el, EventBase::EventGeneratorID_t egid) {
00591   // remove listener from allevents
00592   size_t numlist=allevents[egid].size();
00593   allevents[egid].erase(std::remove(allevents[egid].begin(),allevents[egid].end(),el),allevents[egid].end());
00594   bool hadListener=allevents[egid].size()!=numlist;
00595   
00596   // now remove listener from all of the filtered events
00597   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00598     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00599     if(mapping!=NULL) { // if there are subscribers to this egid/etid
00600       SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
00601       for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++) {// go through each sourceID, delete EL
00602         std::vector<void*> * v=&(*mapit).second;
00603         std::vector<void*>::iterator last=std::remove(v->begin(),v->end(),el);
00604         if(last!=v->end()) {
00605           hadListener=true;
00606           v->erase(last,v->end());
00607         }
00608       }
00609     }
00610   }
00611   return hadListener;
00612 }
00613 
00614 bool EventRouter::EventMapper::removeMapping(const void* el, EventBase::EventGeneratorID_t egid, size_t sid, EventBase::EventTypeID_t etid) {
00615   bool hadListener=false;
00616   SIDtoListenerVectorMap_t* mapping=filteredevents[egid][etid];
00617   if(mapping!=NULL) { // if there are subscribers to this egid/etid
00618     SIDtoListenerVectorMap_t::iterator mapit=mapping->find(sid);
00619     if(mapit!=mapping->end()) {
00620       std::vector<void*> * v=&(*mapit).second;
00621       std::vector<void*>::iterator last=std::remove(v->begin(),v->end(),el);
00622       if(last!=v->end()) {
00623         hadListener=true;
00624         v->erase(last,v->end());
00625       }
00626     }
00627   }
00628   return hadListener;
00629 }
00630 
00631 void EventRouter::EventMapper::clean() {
00632   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
00633     clean((EventBase::EventGeneratorID_t)eg);
00634 }
00635 void EventRouter::EventMapper::clean(EventBase::EventGeneratorID_t egid) {
00636   // first, remove any empty sid vectors from all the mappings
00637   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00638     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00639     if(mapping!=NULL) { // if there are subscribers to this egid/etid
00640       SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
00641       bool done=false;
00642       while(!done) {
00643         done=true;
00644         for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++) { // go through each sourceID vector
00645           if((*mapit).second.size()==0) {
00646             mapping->erase(mapit);
00647             done=false;
00648             break;
00649           }
00650         }
00651       }
00652     }
00653   }
00654   // now remove any empty mappings
00655   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00656     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00657     if(mapping!=NULL) { // if there are subscribers to this egid/etid
00658       if(mapping->size()==0) {
00659         delete mapping;
00660         filteredevents[egid][et]=NULL;
00661       }
00662     }
00663   }
00664 }
00665 
00666 void EventRouter::EventMapper::clear() {
00667   for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) {
00668     for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00669       SIDtoListenerVectorMap_t* mapping=filteredevents[eg][et];
00670       if(mapping!=NULL) { // don't beat a dead horse!
00671         mapping->erase(mapping->begin(),mapping->end());
00672         delete mapping;
00673         filteredevents[eg][et]=NULL;
00674       }
00675     }
00676   }
00677 }
00678 
00679 bool EventRouter::EventMapper::hasMapping(EventBase::EventGeneratorID_t egid) const {
00680   if(allevents[egid].size()>0)
00681     return true;
00682   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00683     const SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00684     if(mapping!=NULL) {
00685       SIDtoListenerVectorMap_t::const_iterator mapit=mapping->begin();
00686       for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++)
00687         if((*mapit).second.size()>0)
00688           return true;
00689     }
00690   }
00691   return false;
00692 }
00693 
00694 bool EventRouter::EventMapper::hasMapping(EventBase::EventGeneratorID_t egid, size_t sid) const {
00695   if(allevents[egid].size()>0)
00696     return true;
00697   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00698     const SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00699     if(mapping!=NULL) {
00700       SIDtoListenerVectorMap_t::const_iterator mapit=mapping->find(sid);
00701       if(mapit!=mapping->end() && (*mapit).second.size()>0)
00702         return true;
00703     }
00704   }
00705   return false;
00706 }
00707 
00708 bool EventRouter::EventMapper::hasMapping(EventBase::EventGeneratorID_t egid, size_t sid, EventBase::EventTypeID_t etid) const {
00709   if(allevents[egid].size()>0)
00710     return true;
00711   const SIDtoListenerVectorMap_t* mapping=filteredevents[egid][etid];
00712   if(mapping!=NULL) {
00713     SIDtoListenerVectorMap_t::const_iterator mapit=mapping->find(sid);
00714     if(mapit!=mapping->end())
00715       return ((*mapit).second.size()>0);
00716   }
00717   return false;
00718 }
00719 
00720 template<class T>
00721 void EventRouter::EventMapper::getMapping(const EventBase& e, std::vector<T*>& ls) const {
00722   // first get all the filtered subscribers (tricky!)
00723   const std::vector<void*>* elv=NULL;
00724   const SIDtoListenerVectorMap_t* sidtovm=filteredevents[e.getGeneratorID()][e.getTypeID()];
00725   if(sidtovm!=NULL) { // if there's a map (at least one EL is filtering on this EGID and ETID)
00726     SIDtoListenerVectorMap_t::const_iterator mapit=sidtovm->find(e.getSourceID()); // find listening for this source id
00727     if(mapit!=sidtovm->end()) { // if there's at least one is filtering on this sourceID as well
00728       elv=&(*mapit).second; // now go through them all
00729       for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00730         ls.push_back(static_cast<T*>(*elit));
00731     }
00732   }
00733   // now get the 'all events' subscribers
00734   elv=&allevents[e.getGeneratorID()];
00735   for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00736     ls.push_back(static_cast<T*>(*elit));
00737 }
00738 
00739 bool EventRouter::EventMapper::verifyMapping(const void * listener, EventBase::EventGeneratorID_t egid, size_t sid, EventBase::EventTypeID_t etid) const {
00740   // first check the 'all events' subscribers
00741   const std::vector<void*>* elv=&allevents[egid];
00742   for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00743     if(*elit==listener)
00744       return true;
00745   
00746   // then check all the filtered subscribers (tricky!)
00747   const SIDtoListenerVectorMap_t* sidtovm=filteredevents[egid][etid];
00748   if(sidtovm!=NULL) { // if there's a map (at least one EL is filtering on this EGID and ETID)
00749     const SIDtoListenerVectorMap_t::const_iterator mapit=sidtovm->find(sid); // find listening for this source id
00750     if(mapit!=sidtovm->end()) { // if there's at least one is filtering on this sourceID as well
00751       elv=&(*mapit).second; // now go through them all
00752       for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00753         if(*elit==listener)
00754           return true;
00755     }
00756   }
00757 
00758   // if we haven't found it, doesn't exist:
00759   return false;
00760 }
00761 
00762 bool EventRouter::EventMapper::verifyMappingAll(const void* listener, EventBase::EventGeneratorID_t egid) const {
00763   const std::vector<void*>* elv=&allevents[egid];
00764   for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00765     if(*elit==listener)
00766       return true;
00767   // if not in the all listeners, can't be listening for *every* source id
00768   return false;
00769 }
00770 
00771 bool EventRouter::EventMapper::verifyMappingAny(const void* listener, EventBase::EventGeneratorID_t egid) const {
00772   // first check the 'all events' subscribers
00773   const std::vector<void*>* elv=&allevents[egid];
00774   for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00775     if(*elit==listener)
00776       return true;
00777   
00778   // then check all the filtered subscribers (tricky!)
00779   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00780     const SIDtoListenerVectorMap_t* sidtovm=filteredevents[egid][et];
00781     if(sidtovm!=NULL) { // if there's a map (at least one EL is filtering on this EGID and ETID)
00782       SIDtoListenerVectorMap_t::const_iterator mapit=sidtovm->begin(); // for each of the source ids
00783       for(;mapit!=sidtovm->end();mapit++) {
00784         elv=&(*mapit).second; // now go through them all
00785         for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00786           if(*elit==listener)
00787             return true;
00788       }
00789     }
00790   }
00791 
00792   // if we haven't found any, none exist:
00793   return false;
00794 }
00795 
00796 bool EventRouter::EventMapper::verifyMappingAll(const void* listener, EventBase::EventGeneratorID_t egid, size_t sid) const {
00797   // first check the 'all events' subscribers
00798   const std::vector<void*>* elv=&allevents[egid];
00799   for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00800     if(*elit==listener)
00801       return true;
00802   
00803   // then check all the filtered subscribers (tricky!)
00804   // must be found in ALL etids
00805   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00806     const SIDtoListenerVectorMap_t* sidtovm=filteredevents[egid][et];
00807     if(sidtovm==NULL)
00808       return false;
00809     // there's a map (at least one EL is filtering on this EGID and ETID)
00810     const SIDtoListenerVectorMap_t::const_iterator mapit=sidtovm->find(sid); // find listening for this source id
00811     if(mapit==sidtovm->end())
00812       return false;
00813     // there's at least one is filtering on this sourceID as well
00814     elv=&(*mapit).second; // now go through them all
00815     std::vector<void*>::const_iterator elit=elv->begin();
00816     while(elit!=elv->end() && *elit!=listener)
00817       elit++;
00818     if(elit==elv->end())
00819       return false;
00820     //if we didn't return false, we found a match... continue checking other ETIDs
00821   }
00822 
00823   // we only got here if we *did* find listener in each of the ETIDs
00824   return true;
00825 }
00826 
00827 bool EventRouter::EventMapper::verifyMappingAny(const void* listener, EventBase::EventGeneratorID_t egid, size_t sid) const {
00828   // first check the 'all events' subscribers
00829   const std::vector<void*>* elv=&allevents[egid];
00830   for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00831     if(*elit==listener)
00832       return true;
00833   
00834   // then check all the filtered subscribers (tricky!)
00835   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00836     const SIDtoListenerVectorMap_t* sidtovm=filteredevents[egid][et];
00837     if(sidtovm!=NULL) { // if there's a map (at least one EL is filtering on this EGID and ETID)
00838       SIDtoListenerVectorMap_t::const_iterator mapit=sidtovm->find(sid); // find listening for this source id
00839       if(mapit!=sidtovm->end()) { // if there's at least one is filtering on this sourceID as well
00840         elv=&(*mapit).second; // now go through them all
00841         for(std::vector<void*>::const_iterator elit=elv->begin(); elit!=elv->end(); elit++)
00842           if(*elit==listener)
00843             return true;
00844       }
00845     }
00846   }
00847 
00848   // if we haven't found it, doesn't exist:
00849   return false;
00850 }
00851 
00852 /*! @file
00853  * @brief Implements EventRouter class, for distribution and trapping of events to listeners
00854  * @author ejt (Creator)
00855  */
00856 
00857 
00858 
00859 
00860 
00861 
00862 
00863 // Use hasListeners(*) it's faster, i doubt anyone would really care how many... (but just in case...)
00864 /*
00865 unsigned int EventRouter::numListeners(EventBase::EventGeneratorID_t egid) {
00866   unsigned int ans=allevents[egid].size();
00867   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00868     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00869     if(mapping!=NULL) {
00870       SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
00871       for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++)
00872         ans+=(*mapit).second.size();
00873     }
00874   }
00875   return ans;
00876 }
00877 
00878 bool EventRouter::numListeners(EventBase::EventGeneratorID_t egid, size_t sid) {
00879   size_t ans=allevents[egid].size();
00880   for(unsigned int et=0; et<EventBase::numETIDs; et++) {
00881     SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
00882     if(mapping!=NULL) {
00883       SIDtoListenerVectorMap_t::iterator mapit=mapping->find(sid);
00884       if(mapit!=mapping->end())
00885         ans+=(*mapit).second.size();
00886     }
00887   }
00888   return false;
00889 }
00890 
00891 unsigned int EventRouter::numListeners(EventBase::EventGeneratorID_t egid, size_t sid, EventBase::EventTypeID_t etid) {
00892   unsigned int ans=allevents[egid].size();
00893   SIDtoListenerVectorMap_t* mapping=filteredevents[egid][etid];
00894   if(mapping!=NULL) {
00895     SIDtoListenerVectorMap_t::iterator mapit=mapping->find(sid);
00896     if(mapit!=mapping->end())
00897       ans+=(*mapit).second.size();
00898   }
00899   return ans;
00900 }
00901 */

Tekkotsu v5.1CVS
Generated Sat May 4 06:32:46 2013 by Doxygen 1.6.3