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 "IPC/MutexLock.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   //! set #trapRet, which can let you decide whether trapped events should be filtered or not
00042   virtual void setTrapEventValue(bool v) { trapRet=v; }
00043   
00044 
00045 protected:
00046 
00047   //! Called by encodeEvent() to request a buffer for serializing into, must be at least @a size
00048   /*! This buffer will then be sent to post(), which should free
00049    *  it (or recycle it for usage by a later bufferRequest()) */
00050   virtual char* bufferRequest(unsigned int size)=0;
00051 
00052   //! Called by encodeEvent() after serialization is complete for communication to other processes
00053   /*! @param buf the data to be sent, will be a buffer previously requested from #bufferRequest
00054    *  @param size the number of bytes to send
00055    *  @param onlyReady if true, only send the event to observers which do not have any message backlog (if supported by transfer mechanism)
00056    *
00057    *  You will always get this callback after each call to bufferRequest(), even
00058    *  in the event of an error during saving.  If an error occured, the callback
00059    *  will receive 0 for size.*/
00060   virtual void post(const char* buf, unsigned int size, bool onlyReady)=0;
00061 
00062   //! The value which trapEvent() should return
00063   bool trapRet;
00064 
00065 private:
00066   EventTranslator(const EventTranslator&); //!< don't call
00067   EventTranslator& operator=(const EventTranslator&); //!< don't call
00068 };
00069 
00070 class EventRouter;
00071 
00072 //! For completeness, if you want to have events be piped directly to the local erouter instead having to be encoded and decoded
00073 /*! Unfortunately, this still entails a memory copy of the event since
00074  *  we have to make a new event for posting to the event router.  We
00075  *  could avoid this if events were reference counted or if there was
00076  *  a way to direct the EventRouter not to free the event after
00077  *  processing.
00078  *
00079  *  Beware of subscribing this class as a listener to the same
00080  *  EventRouter that it is sending to -- could cause infinite
00081  *  recursion */
00082 class NoOpEventTranslator : public EventTranslator {
00083 public:
00084   //! constructor
00085   explicit NoOpEventTranslator(EventRouter& er) : EventTranslator(), evtRouter(er) {}
00086 
00087   virtual void encodeEvent(const EventBase& event, bool onlyReady=false);
00088 
00089 protected:
00090   //! should never be called, only included to satisfy interface
00091   virtual char* bufferRequest(unsigned int /*size*/) { return NULL; }
00092   //! should never be called, only included to satisfy interface
00093   virtual void post(const char* /*buf*/, unsigned int /*size*/, bool /*onlyReady*/) { }
00094   
00095   EventRouter& evtRouter; //!< the EventRouter to send events to
00096 };
00097 
00098 
00099 #ifdef PLATFORM_APERIOS
00100 class OSubject;
00101 #else
00102 class MessageQueueBase;
00103 #endif
00104 class RCRegion;
00105 
00106 //! An implementation of EventTranslator which will forward events using the inter-process mechanisms of the current platform
00107 /*! The current implementation creates an RCRegion for each event and
00108  *  then releases its reference to the region after it is sent.  A
00109  *  more efficient implementation might retain a queue of recycled
00110  *  RCRegions to reduce allocation costs */
00111 class IPCEventTranslator : public EventTranslator {
00112 public:
00113 
00114 #ifdef PLATFORM_APERIOS
00115   typedef OSubject IPCSender_t; //!< the class for sending IPC messages on aperios
00116 #else
00117   typedef MessageQueueBase IPCSender_t; //!< the class for sending IPC messages on unix-based systems
00118 #endif
00119 
00120   //! constructor
00121   explicit IPCEventTranslator(IPCSender_t& subj) : EventTranslator(), subject(subj), curRegion(NULL), curName(), lock() {}
00122   
00123   //! extends base class's implementation to store @a event.getName() into #curName 
00124   virtual void encodeEvent(const EventBase& event, bool onlyReady=false) {
00125     curName=event.getName();
00126     EventTranslator::encodeEvent(event,onlyReady);
00127   }
00128 
00129 protected:
00130   virtual char* bufferRequest(unsigned int size);
00131   virtual void post(const char* buf, unsigned int size, bool onlyReady);
00132   
00133   IPCSender_t& subject; //!< where to post messages upon serialization, set by constructor
00134   RCRegion* curRegion; //!< the region currently being serialized into, only valid between call to bufferRequest() and following post()
00135   std::string curName; //!< name of current event being posted (for error messages)
00136   MutexLock<ProcessID::NumProcesses> lock; //!< prevent concurrent posts, held for the duration of #curRegion
00137 
00138 private:
00139   IPCEventTranslator(const IPCEventTranslator&); //!< don't call
00140   IPCEventTranslator operator=(const IPCEventTranslator&); //!< don't call
00141 };
00142 
00143 /*! @file
00144  * @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
00145  * @author ejt (Creator)
00146  */
00147 
00148 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:38 2016 by Doxygen 1.6.3