Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Platform/Aperios1.3.2/ProcessFramework.h

Go to the documentation of this file.
00001 /**
00002  * @file Platform/Aperios1.3.2/ProcessFramework.h
00003  * This file contains classes related to processes on the Aperios Platform.
00004  * @author Thomas Röfer
00005  */
00006 #ifndef __ProcessFramework_h__
00007 #define __ProcessFramework_h__
00008 
00009 #include <OPENR/OObject.h>
00010 #include <OPENR/OSubject.h>
00011 #include <OPENR/OObserver.h>
00012 #include <ObjectEntryTable.h>
00013 #include <string.h>
00014 #include "Platform/SystemCall.h"
00015 #include "Platform/GTAssert.h"
00016 
00017 const unsigned int ENTRY_TABLE_MIN = 5,   /**< The default number of entries in an Aperios entry table. */
00018           ENTRY_TABLE_MAX = 100, /**< The maximum number of entries in an Aperios entry table. */
00019           NAME_LENGTH_MAX = 100, /**< The maximum length of Aperios connection names. */
00020           PROCESS_MAX = 1,       /**< The maximum number of processes in this address context. */
00021           ROBOT_MAX = 1;         /**< The maximum number of robots in this address context. */
00022 
00023 class PlatformProcess;
00024 class ProcessBase;
00025 
00026 #include "Sender.h"
00027 #include "MotorCommandsSender.h"
00028 #include "SoundDataSender.h"
00029 #include "SharedSender.h"
00030 #include "Receiver.h"
00031 #include "SharedReceiver.h"
00032 
00033 #include "IPEndpoint.h"
00034 
00035 /**
00036  * This class is the platform dependent base class for all processes.
00037  */
00038 class PlatformProcess
00039 {
00040   private:
00041     SenderList* firstSender;     /**< The begin of the list of all senders of this process. */
00042     ReceiverList* firstReceiver; /**< The begin of the list of all receivers of this process. */
00043 
00044   public:
00045     /**
00046      * Constructor.
00047      */
00048     PlatformProcess()
00049     {
00050       firstSender = 0;
00051       firstReceiver = 0;
00052     }
00053 
00054     /**
00055      * The function returns the begin of list of all senders.
00056      * Note that the function returns a reference that can be changed.
00057      * @return A reference to the address of the first element. 
00058      */
00059     SenderList*& getFirstSender() {return firstSender;}
00060 
00061     /**
00062      * The function returns the begin of list of all receivers.
00063      * Note that the function returns a reference that can be changed.
00064      * @return A reference to the address of the first element. 
00065      */
00066     ReceiverList*& getFirstReceiver() {return firstReceiver;}
00067 };
00068 
00069 /**
00070  * The class is a helper that allows to instantiate a class as an Aperios process.
00071  * ProcessBase contains the parts that need not to be implemented as a template.
00072  * It will only be used by the macro MAKE_PROCESS and should never be used directly.
00073  */
00074 class ProcessBase : public OObject
00075 {
00076   public:
00077     static ProcessBase* theInstance; /**< A pointer to the only instance of this class. */
00078     void getAntInformation(int*& listenContSelector, int*& sendContSelector,
00079                  int*& receiveContSelector, int*& closeContSelector, 
00080                  int*& connectContSelector);
00081     OID* getOID(){
00082       return (&myOID_);
00083     }
00084     
00085   private:
00086     static int blockMask,            /**< A mask with bits set for all blocking senders and receivers. */
00087                eventMask;            /**< A mask with bits set for all senders and receivers that received an event */
00088     bool running; /**< The flag states whether the process is still running. */
00089 
00090     /**
00091      * A global Aperios event handler that calls OObject::Init().
00092      * @param reasonMsg A message provided by Aperios.
00093      */
00094     static void aperiosInit(OReasonMessage* reasonMsg);
00095 
00096     /**
00097      * A global Aperios event handler that calls OObject::Start().
00098      * @param reasonMsg A message provided by Aperios.
00099      */
00100     static void aperiosStart(OReasonMessage* reasonMsg);
00101 
00102     /**
00103      * A global Aperios event handler that calls OObject::Stop().
00104      * @param reasonMsg A message provided by Aperios.
00105      */
00106     static void aperiosStop(OReasonMessage* reasonMsg);
00107 
00108     /**
00109      * A global Aperios event handler that calls OObject::Destroy().
00110      * @param reasonMsg A message provided by Aperios.
00111      */
00112     static void aperiosDestroy(OReasonMessage* reasonMsg);
00113 
00114     /**
00115      * A global event handler for timer events.
00116      * It is automatically called after a certain time if Process::main()
00117      * returned a nonzero value. It will note that the timer event occurred,
00118      * and will start a new frame if there are no other pending event, i.e.
00119      * waiting receivers.
00120      * @param reasonMsg A message provided by Aperios.
00121      */
00122     static void awakeOnTimer(OReasonMessage* reasonMsg);
00123 
00124    
00125     /**
00126      * Global event handlers for IP-networking 
00127      */
00128     static void antConnectCont(antEnvMsg* msg);
00129     int antConnectContSelector;
00130     
00131     static void antReceiveCont(antEnvMsg* msg);
00132     int antReceiveContSelector;
00133 
00134     static void antSendCont(antEnvMsg* msg);
00135     int antSendContSelector;
00136 
00137     static void antListenCont(antEnvMsg* msg);
00138     int antListenContSelector;
00139  
00140     static void antCloseCont(antEnvMsg* msg);
00141     int antCloseContSelector;
00142 
00143     /**
00144      * The function calls the member ProcessNextFrame() of the only instance of this class.
00145      */
00146     static void nextFrame();
00147 
00148   protected:
00149     /**
00150      * The function initializes the object and should immediately be called after
00151      * the construction of an object.
00152      */
00153     void init();
00154 
00155     /**
00156      * The function is called once for each frame.
00157      */
00158     virtual void processNextFrame() = 0;
00159 
00160     /**
00161      * The function returns the address of the associated process.
00162      * @return The address of the object.
00163      */
00164     virtual PlatformProcess* getProcess() = 0;
00165 
00166   public:
00167     /**
00168      * Constructor.
00169      */
00170     ProcessBase():running(true)
00171     {
00172       theInstance=this;
00173     }
00174 
00175     /**
00176      * The function marks the process as stopped.
00177      */
00178     void stop() {running = false;}
00179 
00180     /**
00181      * The function returns whether the process is still running.
00182      * @return Shall the process continue?
00183      */
00184     bool isRunning() {return running;}
00185 
00186     /**
00187      * The functions sets or resets a bit in the blocking mask.
00188      * After a bit is set in the blocking mask for a certain 
00189      * sender or receiver, a new frame will not be started before
00190      * this sender or receiver received an event.
00191      * @param id The id of the sender or receiver.
00192      * @param block Should it block or not?
00193      */
00194     static void setBlockingId(int id,bool block = true);
00195 
00196     /**
00197      * The function is called when an event was received. 
00198      * If this was the last event the process was waiting for, the next
00199      * frame is started, i.e. NextFrame() is called.
00200      * @param id The id of the sender or receiver that received an event.
00201      */
00202     static void setEventId(int id);
00203 
00204     /**
00205      * Returns the event mask.
00206      * @return The event mask.
00207      */
00208     static int getEventMask() {return eventMask;}
00209 
00210     /**
00211      * Resets the event mask.
00212      */
00213     static void resetEventMask() {eventMask = 0;}
00214 };
00215 
00216 /**
00217  * The class is a helper that allows to instantiate a class as an Aperios process.
00218  * ProcessCreator contains the parts that need to be implemented as a template.
00219  * It will only be used by the macro MAKE_PROCESS and should never be used directly.
00220  */
00221 template<class T> class ProcessCreator : public ProcessBase
00222 {
00223   private:
00224     T* process;       /**< A pointer to the only instance of the process. */
00225     const char* name; /**< The name of the process. */
00226     int lastTime;     /**< The last time when Process::Main() was finished. */
00227 
00228     /**
00229      * The function registers the global functions for object communication.
00230      * It is called by OObject::Init().
00231      * @param event An Open-R event.
00232      * @return The status. Currently, the function always reports success.
00233      */
00234     virtual OStatus DoInit(const OSystemEvent& event)
00235     {
00236       setBlockingId(31);
00237       int id = ENTRY_TABLE_MIN;
00238       for(ReceiverList* p = process->getFirstReceiver(); p; p = p->getNext())
00239       {
00240         ASSERT(strlen(name) + strlen(p->getName()) + 2 <= NAME_LENGTH_MAX);
00241         char buf[NAME_LENGTH_MAX];
00242         strcpy(buf,name);
00243         strcat(buf,".");
00244         strcat(buf,p->getName());
00245         OServiceEntry entry;
00246         entry.Set(myOID_,id++);
00247         VERIFY(RegisterServiceEntry(entry,buf) == oSUCCESS);
00248         entry.Set(myOID_,id++);
00249         VERIFY(p->SetNotifyEntry(entry) == oSUCCESS);
00250       }
00251       for(SenderList* q = process->getFirstSender(); q; q = q->getNext())
00252       {
00253         ASSERT(strlen(name) + strlen(q->getName()) + 2 <= NAME_LENGTH_MAX);
00254         char buf[NAME_LENGTH_MAX];
00255         strcpy(buf,name);
00256         strcat(buf,".");
00257         strcat(buf,q->getName());
00258         OServiceEntry entry;
00259         entry.Set(myOID_,id++);
00260         VERIFY(RegisterServiceEntry(entry,buf) == oSUCCESS);
00261         entry.Set(myOID_,id++);
00262         VERIFY(q->SetReadyEntry(entry) == oSUCCESS);
00263       }
00264       return oSUCCESS;
00265     }
00266 
00267     /**
00268      * The function starts the process.
00269      * It is called by OObject::Start().
00270      * @param event An Open-R event.
00271      * @return The status. Currently, the function always reports success.
00272      */
00273     virtual OStatus DoStart(const OSystemEvent& event) 
00274     {
00275       for(ReceiverList* p = process->getFirstReceiver(); p; p = p->getNext())
00276         p->AssertReady();
00277       // Call processNextFrame if no blocking receivers are waiting
00278       setEventId(31);
00279       return oSUCCESS;
00280     };
00281 
00282     /**
00283      * The function stops the process.
00284      * It is called by OObject::Stop(). However, OObject::Stop() is 
00285      * never called. Therefore, this function is called neither.
00286      * @param event An Open-R event.
00287      * @return The status. Currently, the function always reports success.
00288      */
00289     virtual OStatus DoStop(const OSystemEvent& event)
00290     {
00291       stop();
00292       for(ReceiverList* p = process->getFirstReceiver(); p; p = p->getNext())
00293         p->DeassertReady();
00294       if(process)
00295         delete process;
00296       process = 0;
00297       return oSUCCESS;
00298     }
00299 
00300     /**
00301      * The function destroys the process.
00302      * It is called by OObject::Destroy(). However, OObject::Destroy() is 
00303      * never called. Therefore, this function is called neither.
00304      * @param event An Open-R event.
00305      * @return The status. Currently, the function always reports success.
00306      */
00307     virtual OStatus DoDestroy(const OSystemEvent& event) {return oSUCCESS;}
00308 
00309     /**
00310      * The function is called once for each frame.
00311      * It calls Process::main() and will start a timer if Process::main()
00312      * returned a nonzero value.
00313      */
00314     void processNextFrame()
00315     {
00316       int frameTime = process->processMain();
00317       if(getProcess()->getFirstSender())
00318         getProcess()->getFirstSender()->finishFrame();
00319       if(getProcess()->getFirstReceiver())
00320         process->getFirstReceiver()->finishFrame();
00321       resetEventMask();
00322       int currentTime = SystemCall::getCurrentSystemTime();
00323       if(frameTime < 0)
00324         frameTime = lastTime - frameTime - currentTime;
00325       if(frameTime)
00326       {
00327         if(frameTime < 4)
00328           frameTime = 4;
00329         TimeEventInfoWithRelativeTime timeEvent(RelativeTime(frameTime / 1000,frameTime % 1000));
00330         EventID eventId;
00331         VERIFY(SetTimeEvent(&timeEvent,myOID_,Selector(4),0,0,&eventId) == sSUCCESS);
00332       }
00333       setBlockingId(31,frameTime != 0);
00334       lastTime = currentTime;
00335     }
00336   
00337     /**
00338      * The function returns the address of the associated process.
00339      * @return The address of the object.
00340      */
00341     virtual PlatformProcess* getProcess() {return process;}
00342 
00343   public:
00344     /**
00345      * Constuctor. 
00346      * It is only called from MAKE_PROCESS.
00347      * @param name The name of the process.
00348      */
00349     ProcessCreator(const char* name)
00350     {
00351       this->name = name;
00352       VERIFY(process = new T);
00353       init();
00354       lastTime = 0;
00355     }
00356 };
00357 
00358 /**
00359  * The macro MAKE_PROCESS instantiates a class as an Aperios process.
00360  * As a convention, it should be used in the last line of the 
00361  * source file. In each Aperios process, MAKE_PROCESS must exactly be used
00362  * once.
00363  * @param theClass The type of the class to be instantiated.
00364  */
00365 #define MAKE_PROCESS(theClass) \
00366   ProcessCreator<theClass> theProcess(#theClass)
00367 
00368 /**
00369  * All process-local global variable declarations have to be preceeded 
00370  * by this macro. Only variables of simple types can be defined, i.e. 
00371  * no class instantiations are allowed.
00372  */
00373 #define GT_GLOBAL /**/
00374 
00375 #endif //__ProcessFramework_h__

Generated on Mon Mar 20 22:00:00 2006 for GT2005 by doxygen 1.3.6