SimReqHandler.H

Go to the documentation of this file.
00001 /*!@file Simulation/SimReqHandler.H Handle SimReq requests */
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/SimReqHandler.H $
00035 // $Id: SimReqHandler.H 13065 2010-03-28 00:01:00Z itti $
00036 //
00037 
00038 #ifndef SIMULATION_SIMREQHANDLER_H_DEFINED
00039 #define SIMULATION_SIMREQHANDLER_H_DEFINED
00040 #include <typeinfo>
00041 #include "rutz/shared_ptr.h"
00042 #include "rutz/demangle.h"
00043 #include "Simulation/SimEventQueueFlag.H"
00044 #include "Util/log.H"
00045 #include "Util/sformat.H"
00046 
00047 class SimReqHandlerClient;
00048 class SimEventQueue;
00049 class SimReq;
00050 class SimModule;
00051 
00052 //! A SimEventQueue callback for SimModule
00053 /*! This is the base class. We will then create template derived
00054     classes (see ModelParamBase and ModelParam for a similar
00055     idea). The basic idea here is that a SimModule should, at
00056     construction, declare a series of request handlers which
00057     SimEventQueue will automatically route when the appropriate SimReq
00058     objects are received by the queue. The standard C++ way of doing
00059     this typically would involve a callback class, and then
00060     derivatives of this, each one implementing the operator() in
00061     various ways (functor paradigm). However, this is not very
00062     convenient as typically the handler function would want to access
00063     the data members of its SimModule. Hence, we here use a different
00064     strategy, first declaring a function which is a member of
00065     SimModule and implements the actual code to be executed during
00066     callback, and second implementing a template "handler hook" whose
00067     role is just to connect that member function to the SimEventQueue.
00068     SimReqHandler is just the hook. */
00069 class SimReqHandlerBase {
00070 public:
00071   //! Constructor
00072   SimReqHandlerBase(SimReqHandlerClient *smod, const SimModule* reqsource = 0);
00073 
00074   //! Destructor
00075   virtual inline ~SimReqHandlerBase();
00076 
00077   //! What's our underlying SimReq type?
00078   /*! Forbidden in the base class. */
00079   virtual const std::type_info& rtype() const = 0;
00080 
00081   //! What's our underlying SimReqHandlerClient (usually SimModule) type?
00082   /*! Forbidden in the base class. */
00083   virtual const std::type_info& mtype() const = 0;
00084 
00085   //! Get the SimReqHandlerClient
00086   virtual SimReqHandlerClient *client() const = 0;
00087 
00088   //! Get the desired req source, if any
00089   inline const SimModule* reqsrc() const;
00090 
00091   //! Get some string description of ourselves, for printing/debug
00092   inline std::string toString() const;
00093 
00094   //! Execute the handler
00095   /*! This will call the handler method on the req handler client,
00096       passing it the queue and the req. */
00097   virtual void execute(SimEventQueue& q, rutz::shared_ptr<SimReq>& e) = 0;
00098 
00099 protected:
00100   const SimModule *itsReqSrc;
00101 
00102 private:
00103   SimReqHandlerBase(const SimReqHandlerBase& s);      //!< forbid copy-contruction
00104   SimReqHandlerBase& operator=(const SimReqHandlerBase& s); //!< forbid copy
00105 };
00106 
00107 // ######################################################################
00108 //! Template class for SimEventQueue requests
00109 /*! Method 'meth' will be called by the SimEventQueue when a
00110   desired requesr is triggered. Typical usage is as follows:
00111 
00112   in your .H:
00113 
00114   \code
00115 
00116   // your class should inherit from at least SimReqHandlerClient,
00117   // typically it will inherit from SimModule which itself iherits
00118   // from SimReqHandlerClient:
00119   class MySimModule : public SimModule {
00120   ...
00121   private:
00122   // our method to run when SimReqX is posted to the queue,
00123   // will be called by SimEventQueue:
00124   void processX(SimEventQueue& q, rutz::shared_ptr<SimReqX>& e);
00125 
00126   // a hook by which we will let our SimEventQueue know about processX():
00127   SimReqHandler<MySimModule, SimReqX> itsRHx;
00128   \endcode
00129 
00130   in your .C, in the constructor of your class (which must be
00131   a SimReqHandlerClient derivative), in the initalizer list:
00132 
00133   \code
00134   MySimModule::MySimModule() :
00135   ...
00136   itsRHx(this, &MySimModule::processX),
00137   ...
00138   { ... }
00139   \endcode
00140 
00141   and finally you also should implement MySimModule::processX(). */
00142 
00143 template <class Module, class Req>
00144 class SimReqHandler : public SimReqHandlerBase
00145 {
00146 public:
00147   //! Definition for the format and args of the called-back method
00148   typedef void (Module::*Method)(SimEventQueue&, rutz::shared_ptr<Req>&);
00149 
00150   //! Constructor
00151   inline SimReqHandler(Module* mod, Method meth, const SimModule* reqsource = 0);
00152 
00153   //! Destructor
00154   virtual inline ~SimReqHandler();
00155 
00156   //! What's our underlying SimReq type?
00157   virtual const std::type_info& rtype() const;
00158 
00159   //! What's our underlying SimReqHandlerClient (usually SimModule) type?
00160   virtual const std::type_info& mtype() const;
00161 
00162   //! Get the SimReqHandlerClient
00163   virtual inline SimReqHandlerClient *client() const;
00164 
00165   //! Call the callback
00166   virtual inline void execute(SimEventQueue& q, rutz::shared_ptr<SimReq>& e);
00167 
00168 private:
00169   Module* itsModule;
00170   Method itsMethod;
00171 
00172   template <class M, class E> SimReqHandler(const SimReqHandler<M, E>& s);      //!< forbid copy-contruction
00173   template <class M, class E> SimReqHandler<Module, Req>& operator=(const SimReqHandler<M, E>& s); //!< forbid copy
00174 };
00175 
00176 // ######################################################################
00177 //! Macro to declare a SimReqHandler (use in your .H)
00178 /*! This will declare a SimReqHandler called itsReqHandler[reqname] and a
00179   function called handle[reqname] which you will need to implement. For example:
00180 
00181   \code
00182   SIMREQHANDLER_DECLARE(VisualCortex, SimReqVCXfeatures);
00183   \endcode
00184 
00185   is equivalent to:
00186 
00187   \code
00188   void handleSimReqVCXfeatures(SimEventQueue& q, rutz::shared_ptr<SimReqVCXfeatures>& e);
00189   SimReqHandler<VisualCortex, SimReqVCXfeatures> itsReqHandlerSimReqVCXfeatures;
00190   \endcode
00191 
00192   then make sure you use the macro SIMCALLBACK_INIT in your class
00193   constructor, and that you implement onSimReqInputFrame() somewhere
00194   in your .C file. In our example:
00195 
00196   \code
00197   VisualCortex::VisualCortex(...) :
00198     ...,
00199     SIMREQHANDLER_INIT(SimReqVCXfeatures)
00200   { }
00201 
00202   void VisualCortex::handleSimReqVCXfeatures(SimEventQueue& q, rutz::shared_ptr<SimReqVCXfeatures>& e)
00203   { do_something(); }
00204   \endcode
00205 
00206   Have a look at VisualCortex and other modules in src/Neuro for examples of usage. */
00207 #define SIMREQHANDLER_DECLARE(classname, reqname)                             \
00208   void handle##reqname(SimEventQueue& q, rutz::shared_ptr<reqname>& e);       \
00209   typedef classname itsSimReqClassTypeFor##reqname;                           \
00210   SimReqHandler<classname, reqname> itsReqHandler##reqname;
00211 
00212 //! Init a SimReqHandler created by SIMREQHANDLER_DECLARE
00213 /*! Takes possible optional arguments which are the ones that have
00214     default values in the SimReqHandler constructor, namely:
00215       const SimModule* source = 0. */
00216 #define SIMREQHANDLER_INIT(reqname, ...)                                      \
00217   itsReqHandler##reqname(this, &itsSimReqClassTypeFor##reqname::handle##reqname, ## __VA_ARGS__ )
00218 
00219 // ######################################################################
00220 // Inline function implementations:
00221 // ######################################################################
00222 SimReqHandlerBase::~SimReqHandlerBase()
00223 { }
00224 
00225 const SimModule* SimReqHandlerBase::reqsrc() const
00226 { return itsReqSrc; }
00227 
00228 std::string SimReqHandlerBase::toString() const
00229 {
00230   return sformat("%s handler by %s", rutz::demangled_name(this->rtype()),
00231                  rutz::demangled_name(this->mtype()));
00232 }
00233 
00234 template <class Module, class Req>
00235 SimReqHandler<Module, Req>::
00236 SimReqHandler(Module* mod, SimReqHandler<Module, Req>::Method meth,
00237             const SimModule* source) :
00238   SimReqHandlerBase(mod, source), itsModule(mod), itsMethod(meth)
00239 { }
00240 
00241 template <class Module, class Req>
00242 SimReqHandler<Module, Req>::~SimReqHandler()
00243 { }
00244 
00245 template <class Module, class Req>
00246 const std::type_info& SimReqHandler<Module, Req>::rtype() const
00247 { return typeid(Req); }
00248 
00249 template <class Module, class Req>
00250 const std::type_info& SimReqHandler<Module, Req>::mtype() const
00251 { return typeid(Module); }
00252 
00253 template <class Module, class Req>
00254 SimReqHandlerClient* SimReqHandler<Module, Req>::client() const
00255 { return itsModule; }
00256 
00257 template <class Module, class Req>
00258 void SimReqHandler<Module, Req>::
00259 execute(SimEventQueue& q, rutz::shared_ptr<SimReq>& e)
00260 {
00261   // Make sure e is of type Req:
00262   rutz::shared_ptr<Req> ee; dyn_cast_to_from(ee, e);
00263   if (ee.is_valid() == false)
00264     LFATAL("Passed SimReq does not derive from '%s'", rutz::demangled_name(typeid(Req)));
00265 
00266   // want to learn a new exotic syntax? calling a pointer to member function
00267   (itsModule->*itsMethod)(q, ee);
00268 };
00269 
00270 // ######################################################################
00271 /* So things look consistent in everyone's emacs... */
00272 /* Local Variables: */
00273 /* mode: c++ */
00274 /* indent-tabs-mode: nil */
00275 /* End: */
00276 
00277 #endif // SIMULATION_SIMREQHANDLER_H_DEFINED
Generated on Sun May 8 08:42:18 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3