Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

EventTranslator.cc

Go to the documentation of this file.
00001 #include "EventTranslator.h"
00002 #include "Events/EventRouter.h"
00003 #include "Shared/debuget.h"
00004 #include "Shared/ProjectInterface.h"
00005 #include <iostream>
00006 
00007 #ifdef PLATFORM_APERIOS
00008 #  include <OPENR/OSubject.h>
00009 #else
00010 #  include "IPC/MessageQueue.h"
00011 #endif
00012 #include "IPC/RCRegion.h"
00013 
00014 using namespace std;
00015 
00016 void
00017 EventTranslator::encodeEvent(const EventBase& event, bool onlyReady/*=false*/) {
00018   event.setSaveFormat(EventBase::BINARY);
00019   EventBase::classTypeID_t header=event.getClassTypeID();
00020   const unsigned int bufsize=LoadSave::getSerializedSize(header)+event.getBinSize();
00021   char * const buf=bufferRequest(bufsize);
00022   if(buf==NULL) {
00023     cerr << "ERROR: EventTranslator unable to transmit event because requested buffer was NULL" << endl;
00024     return;
00025   }
00026   char * cur=buf;
00027   unsigned int remain=bufsize;
00028   if(!LoadSave::encodeInc(header,cur,remain,"Ran out of space encoding event header")) return;
00029   unsigned int used=event.saveBuffer(cur,remain);
00030   if(used==0) {
00031     cerr << "ERROR: EventTranslator unable to transmit event because EventBase::saveBuffer failed (buffer==" << (void*)(cur) << ", size==" << remain << ")" << endl;
00032     post(buf,0,onlyReady);
00033     return;
00034   }
00035   cur+=used;
00036   remain-=used;
00037   ASSERT(cur-buf==(int)(bufsize-remain),"used count does not match offset");
00038   post(buf,bufsize-remain,onlyReady);
00039   return;
00040 }
00041 
00042 EventBase*
00043 EventTranslator::decodeEvent(const char * entry, unsigned int size) {
00044   EventBase::classTypeID_t header;
00045   if(!LoadSave::decodeInc(header,entry,size,"Ran out of space decoding event")) return NULL;
00046   //cout << "decodeEvent(" << (void*)entry << ","<< size << ") header is " << header << " (" << entry[0] << entry[1] << entry[2] << entry[3] << ")" << endl;
00047   EventBase* evt=EventBase::getTypeRegistry().create(header);
00048   if(evt==NULL) {
00049     cerr << "ERROR: EventTranslator unable to translate buffer because header does not match a previously registered class type id" << endl;
00050     return NULL;
00051   }
00052   evt->setSaveFormat(EventBase::BINARY);
00053   if(evt->loadBuffer(entry,size)==0) {
00054     cerr << "ERROR: EventTranlator unable to translate buffer because data is malformed (EventBase::loadBuffer failed)" << endl;
00055     return NULL;
00056   }
00057   //cout << "decodes to " << evt->getDescription() << endl;
00058   return evt;
00059 }
00060 
00061 void
00062 NoOpEventTranslator::encodeEvent(const EventBase& event, bool /*onlyReady=false*/) {
00063   evtRouter.postEvent(event);
00064 }
00065 
00066 char*
00067 IPCEventTranslator::bufferRequest(unsigned int size) {
00068   ASSERT(curRegion==NULL,"WARNING: IPCEventTranslator::bufferRequest() curRegion was not NULL");
00069   try {
00070     lock.lock(ProcessID::getID());
00071     curRegion = new RCRegion(size);
00072     return curRegion->Base();
00073   } catch(...) {
00074     lock.unlock();
00075     curRegion=NULL;
00076     throw;
00077   }
00078 }
00079 
00080 void
00081 IPCEventTranslator::post(const char* buf, unsigned int size, bool onlyReady) {
00082   ASSERTRET(curRegion!=NULL,"ERROR: IPCEventTranslator::post(buf,size) was NULL");
00083   if(size==0) {
00084     curRegion->RemoveReference();
00085     curRegion=NULL;
00086     return;
00087   }
00088   if(buf!=curRegion->Base()) {
00089     cerr << "ERROR: IPCEventTranslator::post(buf,size) buf does not match value given from previous bufferRequest()" << endl;
00090     return;
00091   }
00092 #ifdef PLATFORM_APERIOS
00093   if(!onlyReady) {
00094     subject.SetData(curRegion);
00095     subject.NotifyObservers();
00096   } else {
00097     for(ObserverConstIterator it=subject.begin(); it!=subject.end(); ++it) {
00098       if(subject.IsReady(*it)) {
00099         subject.SetData(*it,curRegion);
00100         subject.NotifyObserver(*it);
00101       }
00102     }
00103   }
00104 #else
00105   if(!onlyReady || subject.getMessageSN(subject.newest())==subject.getMessagesRead()) {
00106     try {
00107       subject.sendMessage(curRegion);
00108     } catch(const std::exception& ex) {
00109       static char errmsg[256];
00110       strncpy(errmsg,("Occurred during IPCEventTranslator::post(), dropping interprocess event "+curName).c_str(),256);
00111       ProjectInterface::uncaughtException(__FILE__,__LINE__,errmsg,&ex);
00112     } catch(...) {
00113       static char errmsg[256];
00114       strncpy(errmsg,("Occurred during IPCEventTranslator::post(), dropping interprocess event "+curName).c_str(),256);
00115       ProjectInterface::uncaughtException(__FILE__,__LINE__,errmsg,NULL);
00116     }
00117   }
00118 #endif
00119   curRegion->RemoveReference();
00120   curRegion=NULL;
00121   lock.unlock();
00122 }
00123   
00124 
00125 /*! @file
00126  * @brief Implements EventTranslator, which receives events from EventRouters in non-Main processes and adds them into a SharedQueue for Main to pick up
00127  * @author ejt (Creator)
00128  */
00129 

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