SimEventQueue.H

Go to the documentation of this file.
00001 /*!@file Simulation/SimEventQueue.H Dispatch simulation events */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Simulation/SimEventQueue.H $
00035 // $Id: SimEventQueue.H 13103 2010-03-31 02:24:47Z itti $
00036 //
00037 
00038 #ifndef SIMULATION_SIMEVENTQUEUE_H_DEFINED
00039 #define SIMULATION_SIMEVENTQUEUE_H_DEFINED
00040 
00041 #include "Component/ModelParam.H"
00042 #include "Simulation/SimEvent.H"
00043 #include "Simulation/SimModule.H"
00044 #include "Simulation/SimCallback.H"
00045 #include "Simulation/SimCallbackClient.H"
00046 #include "Simulation/SimReq.H"
00047 #include "Simulation/SimReqHandler.H"
00048 #include "Simulation/SimReqHandlerClient.H"
00049 #include "Simulation/SimEventQueueFlag.H"
00050 #include "Util/SimTime.H"
00051 #include "rutz/demangle.h"
00052 #include <vector>
00053 #include <map>
00054 #include <set>
00055 
00056 //! Simple enum to return a status after evolve()
00057 enum SimStatus
00058   {
00059     SIM_CONTINUE,
00060     SIM_BREAK
00061   };
00062 
00063 //! Helper class to check for events (defined below)
00064 template <class T> class SeC;
00065 
00066 //! Helper class to gather events generated while running a simulation
00067 /*! The class maintains a list of events which may arise from various
00068   simulation modules, and can be queried for specific events.
00069 
00070   This class implements a so-called 'blackboard architecture', a
00071   concept which was introduced in artificial intelligence research to
00072   facilitate information sharing among multiple heterogeneous
00073   problem-solving agents. The basic idea is that the blackboard is a
00074   shared repository of information which all agents can access while
00075   working towards the solution to a given problem.
00076 
00077   Because different modules are usually run sequentially, e.g., in
00078   Brain::evolve(), the intent here is that we keep track of both the
00079   events that arise during a given evolve at SimTime t and during the
00080   previous evolve. If an event arises after a given module has already
00081   been evolve'd for the current iteration, that module will know about
00082   the event on the next iteration. For example, in Brain::evolve(), we
00083   evolve the SaliencyMap module before the EyeHeadController module;
00084   hence if an eye saccade is initiated by the EyeHeadController, the
00085   SaliencyMap will become aware of that at the next iteration, and may
00086   decide to take appropriate action, e.g., saccadic suppression. To
00087   eliminate events older than a given time, use prune(), typically
00088   this would be done at the beginning of Brain::evolve().
00089 
00090   IMPORTANT: When a given SimModule posts an event at time t, all
00091   events posted by that same SimModule at times < t are erased from
00092   the queue. This is as soon as the event type matches, whether or not
00093   the event's contents match.
00094 
00095   HISTORICAL NOTE: SimEventQueue was introduced as an attempt to give
00096   more autonomy to the Brain modules by employing a blackboard
00097   architecture. An example of how things worked before is as follows:
00098   a SaccadeController may decide in its evolve() function that it is
00099   time to blink, and will switch itself to blink state.
00100   Brain::evolve() would have to query the controller after running
00101   evolve() on it, to check whether anything happened, like for example
00102   the start of the blink. If so, Brain::eyeBlink() would be triggered,
00103   which in turn would dispatch the event to several other modules,
00104   calling for example SimulationViewer::eyeBlink() and
00105   SaliencyMap::blinkSuppression(). The more types of events could
00106   occur, the more complex Brain::evolve() was becoming. With
00107   SimEventQueue, most of the complex orchestration which was in
00108   Brain::evolve() is now delegated to the brain modules
00109   themselves. For example, when SaccadeController initiates a blink,
00110   it simply posts a SimEvent indicating so. When SimulationViewer's
00111   turn comes to evolve, it can query SimEventQueue to check whether a
00112   blink has started, and take appropriate action. */
00113 class SimEventQueue : public SimModule {
00114 public:
00115   //! Constructor
00116   /*! An optional start time for the master simulation clock may be
00117     provided. */
00118   SimEventQueue(OptionManager& mgr,
00119                 const std::string& descrName = "Simulation Event Queue",
00120                 const std::string& tagName = "SimEventQueue",
00121                 const SimTime starttime = SimTime::ZERO());
00122 
00123   //! Destructor
00124   virtual ~SimEventQueue();
00125 
00126   //! Post a new SimEvent; typically, SimModule modules do this
00127   template <class E> inline
00128   void post(rutz::shared_ptr<E> e);
00129 
00130   //! Handle a new SimReq; typically, SimModule modules do this
00131   /*! Note two differences between this and post(): here, the SimReq
00132       object does not end up in the queue, it is just privately passed
00133       to the event handlewr, who will modify it, and then the caller
00134       can use the results. Second, SimReq objects are typically passed
00135       read/write while SimEvent objects are read-only in post(). This
00136       function returns the number of handlers that were triggered by
00137       the request. Zero means that nobody caught the request. Default
00138       behavior is to throw a fatal exception if zero or more than 1
00139       handlers catch the request. */
00140   template <class R> inline
00141   size_t request(rutz::shared_ptr<R> r,
00142                const SimReqQueueFlag flags = SRQ_NONE_FATAL | SRQ_SEVERAL_FATAL);
00143 
00144   //! Return event, if any, that satisfies the given criteria
00145   /*! Example usage is as follows:
00146     \code
00147 
00148     // Assume a SimEventQueue object q
00149     // Assume that caller is a SimModule
00150     // Assume that CovertShift derives from SimEvent
00151     if (SeC<CovertShift> e = q.check<CovertShift>(this))
00152       {
00153         // handle the event; you can use 'e' pretty much as you
00154         // would use a shared_ptr
00155       }
00156 
00157     \endcode
00158 
00159     You can specify an eventsrc SimModule to further narrow the search
00160     to only events that originated from this module. NOTE: only events
00161     which are either public or intended for the caller will be
00162     returned (assuming that all other match criteria are also
00163     fullfilled). See Simulation/SimEvent.H for the distinction between
00164     public and private events. By default, the flags are set so that
00165     we will return the most recent matching unmarked event, then mark
00166     it in the queue as done by the caller module; hence several calls
00167     to check will return all unmarked events (from most recent to
00168     oldest) until they have all been marked.  PROGRAMMER NOTE: don't
00169     overload this, instead you can overload checkHelper() which is
00170     called from here. */
00171   template <class E> inline
00172   SeC<E> check(const SimModule* caller,
00173                const SimEventQueueFlag flags = SEQ_UNMARKED | SEQ_MARK,
00174                const SimModule* eventsrc = 0);
00175 
00176   //! Increment the master clock and delete old events
00177   /*! Events whose time is < t just before we increment the clock will
00178     be removed from the queue. We will here also check for some events
00179     that are handled directly by the queue agent. */
00180   virtual SimStatus evolve();
00181 
00182   //! Get the master clock's time
00183   virtual const SimTime& now() const;
00184 
00185   //! Erase the entire queue; like reset() but does not reset time
00186   /*! Use reset() instead unless you know what you are doing. */
00187   virtual void clear();
00188 
00189   //! Erase all events with time <= tt
00190   virtual void prune(const SimTime& tt);
00191 
00192   //! Reset the time to the given value and erase the entire queue
00193   /*! Like reset() but does not propagate to subcomponents.  Use
00194    reset() instead unless you know what you are doing. */
00195   virtual void resetTime(const SimTime& tim = SimTime::ZERO());
00196 
00197   //! Register a new SimCallbackClient, taking all its callbacks
00198   void registerSimCallbackClient(SimModule *s);
00199 
00200   //! Register a new SimReqHandlerClient, taking all its callbacks
00201   void registerSimReqHandlerClient(SimModule *s);
00202 
00203   //! Show all registered callbacks
00204   void printCallbacks() const;
00205 
00206 protected:
00207   //! Simulation time step, in seconds
00208   OModelParam<SimTime> itsTimeStep;
00209 
00210   //! Exit after a given time in seconds (if not zero)
00211   OModelParam<SimTime> itsTooMuchTime;
00212 
00213   //! Display memory stats when a module posts a SimEventShowMemStats
00214   OModelParam<bool> itsShowMemStats;
00215 
00216   //! Default units for memory stats
00217   OModelParam<size_t> itsShowMemStatsUnits;
00218 
00219   //! text log file name
00220   OModelParam<std::string> itsLogFile;
00221 
00222   SimTime t;  //!< the simulation's master clock
00223 
00224   //! This is called by post(). Default is a no-op.
00225   /*! @param etype typeid of the event which the caller
00226     wanted to check for (use rutz::demangle(etype) to get the type name)
00227     @param e the event posted
00228     @param the post time */
00229   inline virtual
00230   void postHelper(const std::type_info& etype,
00231                   const rutz::shared_ptr<SimEvent>& e);
00232 
00233   //! This is called by request(). Default is a no-op.
00234   inline virtual
00235   void requestHelper(const std::type_info& etype,
00236                      const rutz::shared_ptr<SimReq>& e);
00237 
00238   //! this is called by check(). Default is a no-op.
00239   /*! @param etype typeid of the event which the caller
00240     wanted to check for (use rutz::demangle(etype) to get the type name)
00241     @param e matching event found, will be invalid if no match was
00242     found. Note that e may have a different type from what the caller
00243     was looking for, namely it could be a derived class from the one
00244     looked for.
00245     @param caller the SimModule that called check().
00246     @param flags the flags passed to check().
00247     @param eventsrc the event source passed to check() if any.  */
00248   inline virtual
00249   void checkHelper(const std::type_info& etype,
00250                    const rutz::shared_ptr<SimEvent>& e,
00251                    const SimModule* caller,
00252                    const SimEventQueueFlag flags,
00253                    const SimModule* eventsrc);
00254 
00255   //! Reset and propagate the reset signal to the sub-components
00256   /*! See the base function in ModelComponent.H for info. */
00257   virtual void reset1();
00258 
00259   //! get started
00260   virtual void start1();
00261 
00262   struct TypeInfoCompare {
00263     bool operator()(const std::type_info* t1, const std::type_info* t2) const
00264     { return (t1->before(*t2)); }
00265   };
00266 
00267   // our queue of SimEvents is segmented into realms by using a map
00268   // with the realm name as key; for each realm, we have events,
00269   // callbacks, and request handlers:
00270 
00271   // Data for events: within each realm, we simply pile them up into a
00272   // vector and keep track of their time:
00273   typedef std::pair<SimTime, rutz::shared_ptr<SimEvent> > SeqEntry;
00274   typedef std::vector<SeqEntry> SeqEntryVec;
00275 
00276   // Data for callback management:
00277   // sscbb is a multiset type where we just pile up all the callbacks
00278   //   for a given event type (in the given realm), using some ordering by
00279   //   priority and insertion order.
00280   // scbm is a map of sscbb where each entry corresponds to a given event
00281   //   type (in the current realm)
00282   typedef std::multiset<SimCallbackBase*, SimCallbackCompare> sscbb;
00283   typedef std::map<const std::type_info*, rutz::shared_ptr<sscbb>, TypeInfoCompare> scbm;
00284 
00285   // Data for SimReq handler management:
00286   typedef std::vector<SimReqHandlerBase*> ssrhb;
00287   typedef std::map<const std::type_info*, rutz::shared_ptr<ssrhb>, TypeInfoCompare> srhm;
00288 
00289   // we have one of these for each realm:
00290   typedef struct {
00291     SeqEntryVec events;
00292     scbm callbacks;
00293     srhm reqhandlers;
00294   } RealmData;
00295 
00296   typedef std::map<std::string, RealmData> SeqData;
00297   SeqData itsQueue;
00298 
00299   // get access to the RealmData for a given realm; if create_on_fail
00300   // is true, a new realm will be created if one was not found by that
00301   // name; otherwise a fatal error will occur if realm not found:
00302   RealmData* getRealm(const std::string& realmname, const bool create_on_fail);
00303 
00304 private:
00305   // prevent people from calling SimModule::evolve() on us:
00306   virtual void evolve(SimEventQueue& q);
00307 
00308   // show memory stats
00309   void showMemStats(const int frame, const size_t units) const;
00310 };
00311 
00312 // ######################################################################
00313 //! SeC class to assist with checking for events
00314 /*! This class is to allow for a simple syntax when checking for
00315   events:
00316   <PRE>
00317 
00318   // assume a SimEventQueue q
00319   if (SeC<SimEventBreak> e = q.check<SimEventBreak>(this))
00320     {
00321       // a matching event was found and is in 'e'
00322       cerr<<"Break: "<<e->toString()<<endl;
00323     }
00324 
00325   </PRE>
00326 
00327   With this syntax, matching event 'e' will only live within the scope
00328   of the 'if' statement. Note that this is a somewhat weird syntax and
00329   other seemingly equivalent syntaxes do not work. There must be an
00330   assignment and a provision to convert to bool for this to work. */
00331 template <class T>
00332 class SeC {
00333 public:
00334   // Constructor; used by SimEventQueue::check()
00335   inline SeC(const rutz::shared_ptr<T> event) throw();
00336 
00337   // Assignment constructor
00338   inline SeC(const SeC<T>& other) throw();
00339 
00340   //! Destructor
00341   inline virtual ~SeC();
00342 
00343   //! Get the underlying event
00344   inline T* operator->() const throw();
00345 
00346   //! Get the underlying event
00347   inline T& operator*() const throw();
00348 
00349   //! Convert to bool by checking whether underlying event is valid
00350   /*! This is the key to enabling declaration of a SeC variable inside
00351     an if(...) statement. */
00352   inline operator bool() const;
00353 
00354   //! Check whether the pointee is non-null (there is an event)
00355   inline bool is_valid() const;
00356 
00357   //! Get the underlying shared_ptr
00358   inline rutz::shared_ptr<T>& getPtr();
00359 
00360   //! Get the underlying shared_ptr, const version
00361   inline const rutz::shared_ptr<T>& getPtr() const;
00362 
00363 private:
00364   rutz::shared_ptr<T> itsEvent;
00365 
00366   // forbidden
00367   inline SeC() { };
00368 };
00369 
00370 // ######################################################################
00371 // inlined functions:
00372 // ######################################################################
00373 
00374 // ######################################################################
00375 template <class E> inline
00376 void SimEventQueue::post(rutz::shared_ptr<E> e)
00377 {
00378   // reject uninitialized shared_ptr's:
00379   if (e.is_valid() == false) LFATAL("You cannot post invalid events.");
00380 
00381   // enforce that E should derive from SimEvent, i.e., a pointer to an
00382   // object of type E should be dyn_cast'able to a pointer to type
00383   // SimEvent:
00384   rutz::shared_ptr<SimEvent> ebase; dyn_cast_to_from(ebase, e);
00385   if (ebase.is_valid() == false)
00386     LFATAL("Passed event of type '%s' does not derive from SimEvent", rutz::demangled_name(typeid(*e)));
00387 
00388   // plunge into the appropriate realm:
00389   if (e->itsSource == 0) LFATAL("Received event [%s] with invalid source", e->toString().c_str());
00390   SimEventQueue::RealmData *rd = getRealm(e->itsSource->realm(), false);
00391   SeqEntryVec *sevec = &(rd->events);
00392   scbm *cbmap = &(rd->callbacks);
00393 
00394   // let's delete all events from this caller that have same type as e and a time < t:
00395   SeqEntryVec::iterator ee = sevec->begin();
00396   while (ee != sevec->end())
00397     {
00398       rutz::shared_ptr<SimEvent> evt = ee->second;
00399 
00400       // is evt a shared_ptr onto a SimEvent derivative of type E,
00401       // coming from the same source as e, and with a time < tt?
00402       if (typeid(*evt) == typeid(*e) &&
00403           evt->itsSource == e->itsSource &&
00404           ee->first < t)
00405         ee = sevec->erase(ee);
00406       else ++ee;
00407     }
00408 
00409   // now push the new event into the queue, in case other people later
00410   // need it even though they don't have a callback registered for it
00411   // (they will have to manually do a check() for it), or in case some
00412   // of our callbacks below trigger other callbacks which in turn need
00413   // to check for our event::
00414   sevec->push_back(SeqEntry(t, e));
00415 
00416   // Call all our registered callbacks:
00417   scbm::iterator i = cbmap->find(&typeid(E));
00418   if (i != cbmap->end()) {
00419     // we have callbacks for this event type:
00420     rutz::shared_ptr<sscbb> cbset = i->second;
00421 
00422     // call them all in order (our sets are sorted):
00423     sscbb::iterator ii = cbset->begin(), stop = cbset->end();
00424 
00425     while (ii != stop) {
00426       // should we trigger the callback and how should we dispose of
00427       // the event? The logic here is similar to that in check() so
00428       // make sure both stay in sync if you modify one of them.
00429       // Differences include: the event here is brand new, just
00430       // posted, so clearly it is unmarked and nobody has seen it yet,
00431       // all clients will see it for the first time.
00432       const SimEventQueueFlag flags = (*ii)->sflags();
00433       const SimModule *eventsrc = (*ii)->eventsrc();
00434       SimCallbackClient *cli = (*ii)->client();
00435       SimModule *caller = dynamic_cast<SimModule*>(cli); // or 0 if caller not a SimModule
00436 
00437       // Only consider this event if either we con't care about a
00438       // specific event source, or we do care and the source matches:
00439       if (eventsrc == 0 || e->itsSource == eventsrc) {
00440         // run the callback function:
00441         LDEBUG("CALLBACK[%.2fms]: [%s]:%s, EVENT=[%s]", now().msecs(), e->itsSource->realm().c_str(),
00442                (*ii)->toString().c_str(), ebase->toString().c_str());
00443 
00444         (*ii)->execute(*this, ebase);
00445 
00446         // this event has been "consumed" by that caller, make a note of
00447         // that if caller was a full-blown SimModule:
00448         if (caller != 0 && (flags & SEQ_MARK)) e->markDone(caller);
00449       }
00450       ++ii;
00451     }
00452   }
00453 
00454   // let our helper know what happened:
00455   postHelper(typeid(E), e);
00456 }
00457 
00458 // ######################################################################
00459 template <class R> inline
00460 size_t SimEventQueue::request(rutz::shared_ptr<R> r, const SimReqQueueFlag flags)
00461 {
00462   // reject uninitialized shared_ptr's:
00463   if (r.is_valid() == false) LFATAL("You cannot request invalid SimReqs.");
00464 
00465   // enforce that R should derive from SimReq, i.e., a pointer to an object of type R should be dyn_cast'able to a
00466   // pointer to type SimReq:
00467   rutz::shared_ptr<SimReq> rbase; dyn_cast_to_from(rbase, r);
00468   if (rbase.is_valid() == false)
00469     LFATAL("Passed request of type '%s' does not derive from SimReq", rutz::demangled_name(typeid(*r)));
00470 
00471   // plunge into the appropriate realm:
00472   if (r->itsSource == 0) LFATAL("Received req [%s] with invalid source", r->toString().c_str());
00473   SimEventQueue::RealmData *rd = getRealm(r->itsSource->realm(), false);
00474   srhm *rhmap = &(rd->reqhandlers);
00475 
00476   // Call all our registered handlers:
00477   size_t donesofar = 0;
00478   srhm::iterator i = rhmap->find(&typeid(R));
00479   if (i != rhmap->end())
00480     {
00481       // we have handlers for this request type:
00482       rutz::shared_ptr<ssrhb> rhset = i->second;
00483 
00484       // call them all in order:
00485       ssrhb::iterator ii = rhset->begin(), stop = rhset->end();
00486 
00487       while (ii != stop) {
00488         // Handle the request:
00489         const SimModule *reqsrc = (*ii)->reqsrc();
00490 
00491         // Only consider it if either we con't care about a specific req source, or we do care and the source matches:
00492         if (reqsrc == 0 || r->itsSource == reqsrc) {
00493 
00494           // run the handler function:
00495           LDEBUG("HANDLER[%.2fms]: [%s]:%s, REQ=[%s]", now().msecs(), r->itsSource->realm().c_str(),
00496                  (*ii)->toString().c_str(), rbase->toString().c_str());
00497 
00498           (*ii)->execute(*this, rbase);
00499           ++ donesofar;
00500 
00501           // do we want to enforce unique handling?
00502           if (donesofar > 1 && (flags & SRQ_SEVERAL_FATAL))
00503             LFATAL("More than one handler for %s requested by %s",
00504                    r->toString().c_str(),  r->itsSource->tagName().c_str());
00505         }
00506         ++ii;
00507       }
00508     }
00509 
00510 
00511   if (donesofar == 0 && (flags & SRQ_NONE_FATAL))
00512     LFATAL("No handler for %s requested by %s", r->toString().c_str(),  r->itsSource->tagName().c_str());
00513 
00514   // let our helper know what happened:
00515   requestHelper(typeid(R), r);
00516 
00517   return donesofar;
00518 }
00519 
00520 // ######################################################################
00521 template <class E> inline
00522 SeC<E> SimEventQueue::check(const SimModule* caller,
00523                             const SimEventQueueFlag flags,
00524                             const SimModule* eventsrc)
00525 {
00526   // plunge into the appropriate realm:
00527   if (caller == 0) LFATAL("Received check request for [%s] from invalid caller", rutz::demangled_name(typeid(E)));
00528   SimEventQueue::RealmData *rd = getRealm(caller->realm(), false);
00529   SeqEntryVec *sevec = &(rd->events);
00530 
00531   SeqEntryVec::iterator e = sevec->begin();
00532   rutz::shared_ptr<E> event;
00533 
00534   while(e != sevec->end()) {
00535     // Only consider if either we con't care about a specific event source, or we do care and the source matches:
00536     if (eventsrc == 0 || e->second->itsSource == eventsrc) {
00537       // attempt a dynamic cast to type E:
00538       rutz::shared_ptr<E> ev = rutz::dyn_cast<E>(e->second);
00539 
00540       // if the dynamic cast succeeded, this event has the type we are looking for:
00541       if (ev.is_valid()) {
00542         // do we want to skip this event (if already marked, unless we don't care about marking)?
00543         if ((flags & SEQ_UNMARKED) == 0 || ev->isDone(caller) == false) {
00544           // ok, we want to consider this event as a match. Done searching.
00545           event = ev;
00546           break;
00547         }
00548       }
00549     }
00550     // keep searching...
00551     ++e;
00552   }
00553 
00554   // mark event as done if desired:
00555   if (event.is_valid() && (flags & SEQ_MARK)) event->markDone(caller);
00556 
00557   // let our helper know what happened:
00558   checkHelper(typeid(E), event, caller, flags, eventsrc);
00559 
00560   // if could not find a match, event is an empty shared_ptr:
00561   return SeC<E>(event);
00562 }
00563 
00564 // ######################################################################
00565 inline void
00566 SimEventQueue::checkHelper(const std::type_info& ename,
00567                            const rutz::shared_ptr<SimEvent>& e,
00568                            const SimModule* caller,
00569                            const SimEventQueueFlag flags,
00570                            const SimModule* eventsrc)
00571 { }
00572 
00573 // ######################################################################
00574 inline void
00575 SimEventQueue::postHelper(const std::type_info& etype, const rutz::shared_ptr<SimEvent>& e)
00576 { }
00577 
00578 // ######################################################################
00579 inline void
00580 SimEventQueue::requestHelper(const std::type_info& rtype, const rutz::shared_ptr<SimReq>& r)
00581 { }
00582 
00583 // ######################################################################
00584 template <class T>
00585 inline SeC<T>::SeC(const rutz::shared_ptr<T> event) throw() :
00586   itsEvent(event)
00587 { }
00588 
00589 template <class T>
00590 inline SeC<T>::SeC(const SeC<T>& other) throw() :
00591   itsEvent(other.itsEvent)
00592 { }
00593 
00594 template <class T> inline
00595 SeC<T>::~SeC()
00596 { }
00597 
00598 template <class T> inline
00599 T* SeC<T>::operator->() const throw()
00600 { return itsEvent.get(); }
00601 
00602 template <class T> inline
00603 T& SeC<T>::operator*() const throw()
00604 { return *(itsEvent.get()); }
00605 
00606 template <class T> inline
00607 SeC<T>::operator bool() const
00608 { return itsEvent.is_valid(); }
00609 
00610 template <class T> inline
00611 bool SeC<T>::is_valid() const
00612 { return itsEvent.is_valid(); }
00613 
00614 template <class T> inline
00615 rutz::shared_ptr<T>& SeC<T>::getPtr()
00616 { return itsEvent; }
00617 
00618 template <class T> inline
00619 const rutz::shared_ptr<T>& SeC<T>::getPtr() const
00620 { return itsEvent; }
00621 
00622 
00623 // ######################################################################
00624 /* So things look consistent in everyone's emacs... */
00625 /* Local Variables: */
00626 /* mode: c++ */
00627 /* indent-tabs-mode: nil */
00628 /* End: */
00629 
00630 #endif // SIMULATION_SIMEVENTQUEUE_H_DEFINED
Generated on Sun May 8 08:42:18 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3