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__