SimEventQueue.C

Go to the documentation of this file.
00001 /*!@file Simulation/SimEventQueue.C 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.C $
00035 // $Id: SimEventQueue.C 12962 2010-03-06 02:13:53Z irock $
00036 //
00037 
00038 #include "Simulation/SimEventQueue.H"
00039 
00040 #include "Component/ModelOptionDef.H"
00041 #include "Component/GlobalOpts.H"
00042 #include "Simulation/SimEvents.H"
00043 #include "Simulation/SimulationOpts.H"
00044 #include "Util/AllocAux.H"
00045 #include "Util/sformat.H"
00046 #include "Util/TextLog.H"
00047 
00048 #include <cstdio>
00049 
00050 static const ModelOptionDef OPT_ShowMemStats =
00051   { MODOPT_FLAG, "ShowMemStats", &MOC_GENERAL, OPTEXP_CORE,
00052     "Show verbose memory allocation statistics.",
00053     "mem-stats", '\0', "", "false" };
00054 
00055 static const ModelOptionDef OPT_ShowMemStatsUnits =
00056   { MODOPT_ARG(size_t), "ShowMemStatsUnits", &MOC_GENERAL, OPTEXP_CORE,
00057     "Allocation unit size (in bytes) to use when displaying the "
00058     "verbose memory statistics, or 0 to let simulation modules decide "
00059     "on an allocation unit each time they request that stats be shown.",
00060     "mem-stats-units", '\0', "<bytes>", "0" };
00061 
00062 // ######################################################################
00063 SimEventQueue::SimEventQueue(OptionManager& mgr,
00064                              const std::string& descrName,
00065                              const std::string& tagName,
00066                              const SimTime starttime) :
00067   SimModule(mgr, descrName, tagName),
00068   itsTimeStep(&OPT_SimulationTimeStep, this),
00069   itsTooMuchTime(&OPT_SimulationTooMuchTime, this),
00070   itsShowMemStats(&OPT_ShowMemStats, this),
00071   itsShowMemStatsUnits(&OPT_ShowMemStatsUnits, this),
00072   itsLogFile(&OPT_TextLogFile, this),
00073   t(starttime), itsQueue()
00074 { }
00075 
00076 // ######################################################################
00077 SimEventQueue::~SimEventQueue()
00078 { }
00079 
00080 // ######################################################################
00081 void SimEventQueue::start1()
00082 {
00083   SimModule::start1();
00084 
00085   // make sure the realm in which we are exists, since we will be
00086   // posting events into it (e.g., SimEventClockTick), even if nobody
00087   // is going to catch them and hence that realm might not have been
00088   // created yet:
00089   getRealm(realm(), true);
00090 }
00091 
00092 // ######################################################################
00093 void SimEventQueue::evolve(SimEventQueue& q)
00094 {
00095   LFATAL("Never call this function!");
00096 }
00097 
00098 // ######################################################################
00099 SimStatus SimEventQueue::evolve()
00100 {
00101   // our clock is ticking! Let everyone know:
00102   rutz::shared_ptr<SimEventClockTick> ee(new SimEventClockTick(this, now()));
00103   post(ee);
00104 
00105   // did anyone request that we show memory stats?
00106   if (itsShowMemStats.getVal())
00107     {
00108       if (SeC<SimEventShowMemStats> e = check<SimEventShowMemStats>(this))
00109         {
00110           LINFO("##### %s #####", e->toString().c_str());
00111 
00112           // gobble up all other requests. NOTE: if several requests had
00113           // different units we only show the first one. Maybe a FIXME:
00114           while (SeC<SimEventShowMemStats> ee = check<SimEventShowMemStats>(this))
00115             LINFO("##### %s #####", ee->toString().c_str());
00116 
00117           showMemStats(e->frame(), e->unit());
00118         }
00119     }
00120 
00121   // did anyone post a userwait event?
00122   if (SeC<SimEventUserWait> e = check<SimEventUserWait>(this))
00123     {
00124       // make sure we only pause once even though several modules may
00125       // have requested a pause:
00126       do {
00127         LINFO("##### %s #####", e->toString().c_str());
00128         e = check<SimEventUserWait>(this);
00129       } while(e);
00130 
00131       printf("<<<<< Press [RETURN] to continue >>>>>\n");
00132       char tmp[10];
00133       char* ret = fgets(tmp, 10, stdin);
00134       if (ret);
00135     }
00136 
00137   // did anyone post a break event?
00138   if (SeC<SimEventBreak> e = check<SimEventBreak>(this))
00139     {
00140       // make sure we report all break requests:
00141       do {
00142         LINFO("##### %s #####", e->toString().c_str());
00143         e = check<SimEventBreak>(this);
00144       } while(e);
00145 
00146       LINFO("##### Break requested -- DONE #####");
00147       showMemStats(-2, 0);
00148       return SIM_BREAK;
00149     }
00150 
00151   // have we run for too long?
00152   if (t > itsTooMuchTime.getVal())
00153     {
00154       LINFO("#### Too much time elapsed -- DONE ####");
00155       showMemStats(-2, 0);
00156       return SIM_BREAK;
00157     }
00158 
00159   // increment t by one step:
00160   t += itsTimeStep.getVal();
00161 
00162   // let our TextLog know about the new time:
00163   setLogTime(itsLogFile.getVal(), t);
00164 
00165   // keep running...
00166   return SIM_CONTINUE;
00167 }
00168 
00169 // ######################################################################
00170 void SimEventQueue::clear()
00171 {
00172   SeqData::iterator itr = itsQueue.begin(), stop = itsQueue.end();
00173   while (itr != stop) {
00174     RealmData *rd = &(itr->second);
00175     SeqEntryVec *seq = &(rd->events);
00176     seq->clear();
00177     ++itr;
00178   }
00179 }
00180 
00181 // ######################################################################
00182 void SimEventQueue::prune(const SimTime& tt)
00183 {
00184   SeqData::iterator itr = itsQueue.begin(), stop = itsQueue.end();
00185   while (itr != stop) {
00186     RealmData *rd = &(itr->second);
00187     SeqEntryVec *seq = &(rd->events);
00188 
00189     // delete all events that are <= tt:
00190     SeqEntryVec::iterator ee = seq->begin();
00191     while (ee != seq->end()) if (ee->first <= tt) ee = seq->erase(ee); else ++ee;
00192 
00193     ++itr;
00194   }
00195 }
00196 
00197 // ######################################################################
00198 const SimTime& SimEventQueue::now() const
00199 { return t; }
00200 
00201 // ######################################################################
00202 void SimEventQueue::resetTime(const SimTime& tim)
00203 {
00204   this->clear();
00205   t = tim;
00206 }
00207 // ######################################################################
00208 SimEventQueue::RealmData* SimEventQueue::getRealm(const std::string& realmname, const bool create_on_fail)
00209 {
00210   // do we already know about thsi realm?
00211   SeqData::iterator itr = itsQueue.find(realmname);
00212   if (itr == itsQueue.end())
00213     {
00214       if (create_on_fail)
00215         {
00216           // first time we encounter this realm, let's create an entry for it:
00217           RealmData rd;
00218           std::pair<SeqData::iterator, bool> ii = itsQueue.insert(SeqData::value_type(realmname, rd));
00219           if (ii.second == false) LFATAL("Error creating realm [%s]", realmname.c_str());
00220           itr = ii.first; // use that new entry in the rest of this function
00221         }
00222       else
00223          LFATAL("Unknown realm [%s]", realmname.c_str());
00224     }
00225 
00226   return &(itr->second);
00227 }
00228 
00229 // ######################################################################
00230 void SimEventQueue::registerSimCallbackClient(SimModule *s)
00231 {
00232   // get the realm, create it if new:
00233   SimEventQueue::RealmData *rd = getRealm(s->realm(), true);
00234 
00235   // get the callback map for this realm:
00236   scbm *themap = &(rd->callbacks);
00237 
00238   // loop over all of the client's callbacks and register them:
00239   typedef std::vector<SimCallbackBase *> vscbb;
00240   vscbb *v = &(s->itsSimCallbacks);
00241   vscbb::const_iterator c = v->begin(), stop = v->end();
00242   while (c != stop) {
00243     SimCallbackBase *cb = (*c);
00244 
00245     // get the event type:
00246     const std::type_info *ti = &cb->etype();
00247 
00248     // do we already have registered callbacks for this event type?
00249     scbm::iterator i = themap->find(ti);
00250 
00251     if (i == themap->end()) {
00252       // first time we encounter this event type, create a new map entry for it:
00253       rutz::shared_ptr<sscbb> newset(new sscbb());
00254       std::pair<scbm::iterator, bool> ii = themap->insert(scbm::value_type(ti, newset));
00255       if (ii.second == false)
00256         LFATAL("Error registering callback [%s] in realm [%s]", cb->toString().c_str(), s->realm().c_str());
00257       i = ii.first;
00258     }
00259 
00260     // add the callback to our set of callbacks for that event type:
00261     i->second->insert(cb);
00262 
00263     LDEBUG("Registered [%s] in realm [%s]", cb->toString().c_str(), s->realm().c_str());
00264 
00265     ++c;
00266   }
00267 }
00268 
00269 // ######################################################################
00270 void SimEventQueue::registerSimReqHandlerClient(SimModule *s)
00271 {
00272   // get the realm, create it if new:
00273   SimEventQueue::RealmData *rd = getRealm(s->realm(), true);
00274 
00275   // get the handlers map for this realm:
00276   srhm *themap = &(rd->reqhandlers);
00277 
00278   // loop over all of the client's request handlers and register them:
00279   typedef std::vector<SimReqHandlerBase *> vsrhb;
00280   vsrhb *v = &(s->itsSimReqHandlers);
00281   vsrhb::const_iterator c = v->begin(), stop = v->end();
00282   while (c != stop) {
00283     SimReqHandlerBase *cb = (*c);
00284 
00285     // get the req type:
00286     const std::type_info *ti = &cb->rtype();
00287 
00288     // do we already have registered callbacks for this event type?
00289     srhm::iterator i = themap->find(ti);
00290 
00291     if (i == themap->end()) {
00292       // first time we encounter this req type, create a new map entry for it:
00293       rutz::shared_ptr<ssrhb> newset(new ssrhb());
00294       std::pair<srhm::iterator, bool> ii = themap->insert(srhm::value_type(ti, newset));
00295       if (ii.second == false)
00296         LFATAL("Error registering handler [%s] in realm [%s]", cb->toString().c_str(), s->realm().c_str());
00297       i = ii.first;
00298     }
00299 
00300     // add the handler to our set of handlers for that req type:
00301     i->second->push_back(cb);
00302 
00303     LDEBUG("Registered [%s] in realm [%s]", cb->toString().c_str(), s->realm().c_str());
00304 
00305     ++c;
00306   }
00307 }
00308 
00309 // ######################################################################
00310 void SimEventQueue::printCallbacks() const
00311 {
00312   SeqData::const_iterator itr = itsQueue.begin(), stop = itsQueue.end();
00313   while (itr != stop) {
00314     const char *rname = itr->first.c_str();
00315     const RealmData *rd = &(itr->second);
00316     const scbm *cmap = &(rd->callbacks);
00317     const srhm *rmap = &(rd->reqhandlers);
00318 
00319     scbm::const_iterator c = cmap->begin(), sto = cmap->end();
00320     while (c != sto) {
00321       rutz::shared_ptr<sscbb> s = c->second;
00322       sscbb::const_iterator i = s->begin(), fini = s->end();
00323       while (i != fini) LINFO("[%s] %s", rname, (*i++)->toString().c_str());
00324       ++c;
00325     }
00326     srhm::const_iterator cc = rmap->begin(), sstop = rmap->end();
00327     while (cc != sstop) {
00328       rutz::shared_ptr<ssrhb> s = cc->second;
00329       ssrhb::const_iterator i = s->begin(), fini = s->end();
00330       while (i != fini) LINFO("[%s] %s", rname, (*i++)->toString().c_str());
00331       ++cc;
00332     }
00333     ++itr;
00334   }
00335 }
00336 
00337 // ######################################################################
00338 void SimEventQueue::reset1()
00339 {
00340   resetTime();
00341 
00342   // propagate to our base class:
00343   SimModule::reset1();
00344 }
00345 
00346 // ######################################################################
00347 void SimEventQueue::showMemStats(const int frame, const size_t units) const
00348 {
00349   size_t u = itsShowMemStatsUnits.getVal();
00350   if (u == 0)
00351     {
00352       if (units != 0) u = units;
00353       // else ... just leave u=0 so that invt_allocation_show_stats()
00354       // can fall back to whatever default value has been passed to
00355       // invt_allocation_set_stats_units()
00356     }
00357 
00358   if (frame >= 0)
00359     {
00360       SHOWMEMORY("MEMORY USAGE: frame %d t=%.1fms", frame, t.msecs());
00361       invt_allocation_show_stats
00362         (1, sformat("frame %06d", frame).c_str(), u);
00363     }
00364   else if (frame == -1)
00365     {
00366       SHOWMEMORY("MEMORY USAGE: t=%.1fms", t.msecs());
00367       invt_allocation_show_stats(1, "", u);
00368     }
00369   else
00370     {
00371       SHOWMEMORY("FINAL MEMORY USAGE: t=%.1fms", t.msecs());
00372       invt_allocation_show_stats(1, "final", u);
00373     }
00374 }
00375 
00376 // ######################################################################
00377 /* So things look consistent in everyone's emacs... */
00378 /* Local Variables: */
00379 /* mode: c++ */
00380 /* indent-tabs-mode: nil */
00381 /* End: */
Generated on Sun May 8 08:06:50 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3