Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

EventTranslator.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_EventTranslator_h_
00003 #define INCLUDED_EventTranslator_h_
00004 
00005 #include "Events/EventTrapper.h"
00006 #include "Events/EventListener.h"
00007 #include "Shared/Factory.h"
00008 #include <map>
00009 
00010 //! EventTranslator receives events from EventRouters in non-Main processes and adds them into a SharedQueue for Main to pick up
00011 class EventTranslator : public EventTrapper, public EventListener {
00012 public:
00013   //!constructor
00014   EventTranslator() : trapRet(false) {}
00015 
00016   //!destructor
00017   virtual ~EventTranslator();
00018 
00019   //! Call this with events which should be forwarded to other processes
00020   /*! @param event the event to serialize and send
00021    *  @param onlyReady if true, only send the event to observers which do not have any message backlog (if supported by transfer mechanism) */
00022   virtual void encodeEvent(const EventBase& event, bool onlyReady=false);
00023 
00024   //! Call this with events which should be forwarded to other processes (redirects to encodeEvent())
00025   /*! By providing an EventTrapper interface, you can directly
00026    *  register this class with an EventRouter instead of having to
00027    *  manually forward events (although you could do that as well)
00028    *  @return #trapRet, which you can set via setTrapEventValue() */
00029   virtual bool trapEvent(const EventBase& event) { encodeEvent(event); return trapRet; }
00030 
00031   //! Call this with events which should be forwarded to other processes (redirects to encodeEvent())
00032   /*! By providing an EventListener interface, you can directly
00033    *  register this class with an EventRouter instead of having to
00034    *  manually forward events (although you could do that as well) */
00035   virtual void processEvent(const EventBase& event) { encodeEvent(event); }
00036 
00037   //! Called with buffers containing incoming events which should be reconstituted
00038   /*! @return the reconstituted event, or NULL if an error occured (malformed data) */
00039   static EventBase* decodeEvent(const char* buf, unsigned int size);
00040 
00041   //!This should be called during initialization to register all EventBase subclasses
00042   /*! @return true upon success, false if an event matching that prototype's EventBase::getClassTypeID() was already registered */
00043   template<class EB>
00044   static bool registerPrototype() {
00045     EB prototype;
00046     eventLookup_t::const_iterator it=eventLookup.find(prototype.getClassTypeID());
00047     if(it!=eventLookup.end())
00048       return false;
00049     eventLookup[prototype.getClassTypeID()]=new Factory<EB>;
00050     return true;
00051   }
00052 
00053   //! set #trapRet, which can let you decide whether trapped events should be filtered or not
00054   virtual void setTrapEventValue(bool v) { trapRet=v; }
00055   
00056 
00057 protected:
00058   //! Shorthand for they type of #eventLookup
00059   typedef std::map<unsigned int,FactoryBase*> eventLookup_t;
00060   
00061   //! Allows quick lookup of event subclasses based on their EventBase::getClassTypeID()
00062   static eventLookup_t eventLookup;
00063 
00064   //! Called by encodeEvent() to request a buffer for serializing into, must be at least @a size
00065   /*! This buffer will then be sent to post(), which should free
00066    *  it (or recycle it for usage by a later bufferRequest()) */
00067   virtual char* bufferRequest(unsigned int size)=0;
00068 
00069   //! Called by encodeEvent() after serialization is complete for communication to other processes
00070   /*! @param buf the data to be sent, will be a buffer previously requested from #bufferRequest
00071    *  @param size the number of bytes to send
00072    *  @param onlyReady if true, only send the event to observers which do not have any message backlog (if supported by transfer mechanism)
00073    *
00074    *  You will always get this callback after each call to bufferRequest(), even
00075    *  in the event of an error during saving.  If an error occured, the callback
00076    *  will receive 0 for size.*/
00077   virtual void post(const char* buf, unsigned int size, bool onlyReady)=0;
00078 
00079   //! The value which trapEvent() should return
00080   bool trapRet;
00081 
00082 private:
00083   EventTranslator(const EventTranslator&); //!< don't call
00084   EventTranslator& operator=(const EventTranslator&); //!< don't call
00085 };
00086 
00087 class EventRouter;
00088 
00089 //! For completeness, if you want to have events be piped directly to the local erouter instead having to be encoded and decoded
00090 /*! Unfortunately, this still entails a memory copy of the event since
00091  *  we have to make a new event for posting to the event router.  We
00092  *  could avoid this if events were reference counted or if there was
00093  *  a way to direct the EventRouter not to free the event after
00094  *  processing.
00095  *
00096  *  Beware of subscribing this class as a listener to the same
00097  *  EventRouter that it is sending to -- could cause infinite
00098  *  recursion */
00099 class NoOpEventTranslator : public EventTranslator {
00100 public:
00101   //! constructor
00102   explicit NoOpEventTranslator(EventRouter& er) : EventTranslator(), evtRouter(er) {}
00103 
00104   virtual void encodeEvent(const EventBase& event, bool onlyReady=false);
00105 
00106 protected:
00107   //! should never be called, only included to satisfy interface
00108   virtual char* bufferRequest(unsigned int /*size*/) { return NULL; }
00109   //! should never be called, only included to satisfy interface
00110   virtual void post(const char* /*buf*/, unsigned int /*size*/, bool /*onlyReady*/) { }
00111   
00112   EventRouter& evtRouter; //!< the EventRouter to send events to
00113 };
00114 
00115 
00116 #ifdef PLATFORM_APERIOS
00117 class OSubject;
00118 #else
00119 class MessageQueueBase;
00120 #endif
00121 class RCRegion;
00122 
00123 //! An implementation of EventTranslator which will forward events using the inter-process mechanisms of the current platform
00124 /*! The current implementation creates an RCRegion for each event and
00125  *  then releases its reference to the region after it is sent.  A
00126  *  more efficient implementation might retain a queue of recycled
00127  *  RCRegions to reduce allocation costs */
00128 class IPCEventTranslator : public EventTranslator {
00129 public:
00130 
00131 #ifdef PLATFORM_APERIOS
00132   typedef OSubject IPCSender_t; //!< the class for sending IPC messages on aperios
00133 #else
00134   typedef MessageQueueBase IPCSender_t; //!< the class for sending IPC messages on unix-based systems
00135 #endif
00136 
00137   //! constructor
00138   explicit IPCEventTranslator(IPCSender_t& subj) : EventTranslator(), subject(subj), curRegion(NULL), curName() {}
00139   
00140   //! extends base class's implementation to store @a event.getName() into #curName 
00141   virtual void encodeEvent(const EventBase& event, bool onlyReady=false) {
00142     curName=event.getName();
00143     EventTranslator::encodeEvent(event,onlyReady);
00144   }
00145 
00146 protected:
00147   virtual char* bufferRequest(unsigned int size);
00148   virtual void post(const char* buf, unsigned int size, bool onlyReady);
00149   
00150   IPCSender_t& subject; //!< where to post messages upon serialization, set by constructor
00151   RCRegion* curRegion; //!< the region currently being serialized into, only valid between call to bufferRequest() and following post()
00152   std::string curName; //!< name of current event being posted (for error messages)
00153 
00154 private:
00155   IPCEventTranslator(const IPCEventTranslator&); //!< don't call
00156   IPCEventTranslator operator=(const IPCEventTranslator&); //!< don't call
00157 };
00158 
00159 /*! @file
00160  * @brief Describes EventTranslator and IPCEventTranslator, which receives events from EventRouters in non-Main processes and adds them into a SharedQueue for Main to pick up
00161  * @author ejt (Creator)
00162  *
00163  * $Author: ejt $
00164  * $Name: tekkotsu-3_0 $
00165  * $Revision: 1.12 $
00166  * $State: Exp $
00167  * $Date: 2006/09/25 23:28:12 $
00168  */
00169 
00170 #endif

Tekkotsu v3.0
Generated Wed Oct 4 00:03:43 2006 by Doxygen 1.4.7