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

# Platform/Aperios1.3.2/Sender.h

Go to the documentation of this file.

    00001 /**
    00002  * @file Platform/Aperios1.3.2/Sender.h
    00003  * This file contains classes related to senders.
    00004  * @author Thomas Röfer
    00005  */
    00006 #ifndef __SENDER_H__
    00007 #define __SENDER_H__
    00008
    00009 #ifndef __ProcessFramework_h__
    00010 #error Never include this file directly. Include ProcessFramework.h instead.
    00011 #endif
    00012
    00013 #include "Tools/MessageQueue/MessageQueue.h"
    00014 #include "Platform/GTAssert.h"
    00015
    00016 const int RECEIVERS_MAX = 20; /**< The maximum number of receivers connected to a single sender */
    00017
    00018 /**
    00019  * The class is the base class for senders.
    00020  * A sender is an object that sends packages to an Aperios queue.
    00021  * The class manages a global list of all senders in an Aperios process.
    00022  */
    00023 class SenderList : public OSubject
    00024 {
    00025   private:
    00026     PlatformProcess* process;   /**< The process this sender is associated with. */
    00027     SenderList* next;           /**< The successor of the current sender. */
    00028     char name[NAME_LENGTH_MAX]; /**< The name of a sender without the module's name. */
    00029
    00030   protected:
    00031     int eventId;                /**< The id of the current sender in the range [0..30]. */
    00032     bool blocking;              /**< Stores whether this is a blocking sender. */
    00033
    00034     /**
    00035      * The function sends a package to all receivers that requested it.
    00036      */
    00037     virtual void sendPackage() = 0;
    00038
    00039   public:
    00040     /**
    00041      * The constructor.
    00042      * @param process The process this sender is associated with.
    00043      * @param senderName The Aperios connection name of the sender without the process name.
    00044      * @param blocking Decides whether this sender blocks the execution of the next frame
    00045      *                 until all connected receivers have requested a new package.
    00046      */
    00047     SenderList(PlatformProcess* process,const char* senderName,bool blocking);
    00048
    00049     /**
    00050      * Returns the begin of the list of all senders.
    00051      * @return The first sender in the list, or 0 if the list ist empty.
    00052      */
    00053     SenderList*& getFirst();
    00054
    00055     /**
    00056      * Returns the next sender in the list.
    00057      * @return The next sender in the list, or 0 if this sender is the last one.
    00058      */
    00059     SenderList* getNext() const {return next;}
    00060
    00061     /**
    00062      * Returns the Aperios connection name of the sender.
    00063      * @return The Aperios connection name without the process name ("Sender.type.O")
    00064      */
    00065     const char* getName() const {return name;}
    00066
    00067     /**
    00068      * Fills the Aperios entry table for global functions.
    00069      * The function will write two entries into the table.
    00070      * @param entryTable The Aperios entry table.
    00071      * @param id The first empty id in the entry table.
    00072      * @return The new first empty id in the entry table.
    00073      */
    00074     virtual int fillEntryTable(ObjectEntry* entryTable,int id) = 0;
    00075
    00076     /**
    00077      * The function must be called to finish the current frame.
    00078      */
    00079     void finishFrame();
    00080
    00081     /**
    00082      * The functions sets or resets a bit in the blocking mask.
    00083      * After a bit is set in the blocking mask for a certain
    00084      * sender or receiver, a new frame will not be started before
    00085      * this sender or receiver received an event.
    00086      * @param id The id of the sender or receiver.
    00087      * @param block Should it block or not?
    00088      */
    00089     static void setBlockingId(int id,bool block = true);
    00090
    00091     /**
    00092      * The function is called when an event was received.
    00093      * If this was the last event the process was waiting for, the next
    00094      * frame is started, i.e. NextFrame() is called.
    00095      * @param id The id of the sender or receiver that received an event.
    00096      */
    00097     static void setEventId(int id);
    00098 };
    00099
    00100 /**
    00101  * The class implements a the base class for senders.
    00102  * A sender is an object that sends packages to an Aperios queue.
    00103  * Note that the template parameter is required to force a different
    00104  * instantiation of the static members for each package type.
    00105  */
    00106 template<class T> class SenderBase : public SenderList, public T
    00107 {
    00108   private:
    00109     static SenderBase<T>* theInstance;         /**< The only instance of SenderBase<T>. */
    00110     ObserverID receiver[RECEIVERS_MAX],        /**< A list of all receivers that are ready to receive a package. */
    00111                alreadyReceived[RECEIVERS_MAX]; /**< A list of all receivers that have already received the current package. */
    00112     int numOfReceivers,                        /**< The number of entries in the receiver list. */
    00113         numOfAlreadyReceived;                  /**< The number of entries in the alreadyReceived list. */
    00114
    00115   private:
    00116     /**
    00117      * The function is called when a receiver announces that it is ready to receive a package.
    00118      * @param msg An Open-R message that contains the object id of the receiver.
    00119      */
    00120     void handleMessage(OReadyMessage& msg)
    00121     {
    00122       ReadyHandler(msg);
    00123       /**
    00124        * @todo Currently, assert fails in conjunction with wlan, so avoid crash!
    00125        * However, it may work correctly, because TCPGateway will be the only
    00126        * receiver.
    00127        */
    00128       ASSERT(numOfReceivers < RECEIVERS_MAX);
    00129       int i = 0;
    00130       while(i < numOfReceivers && !(receiver[i] == msg.observerID))
    00131         ++i;
    00132       if(i == numOfReceivers && numOfReceivers < NumberOfObservers())
    00133         numOfReceivers++;
    00134       receiver[i] = msg.observerID;
    00135       if(numOfReceivers == NumberOfObservers())
    00136         setEventId(eventId);
    00137     }
    00138
    00139     /**
    00140      * The Aperios control handler.
    00141      * @param msg A message provided by Aperios.
    00142      */
    00143     static void aperiosControl(OControlMessage* msg)
    00144     {
    00145       theInstance->ControlHandler(*msg);
    00146       Return();
    00147     }
    00148
    00149     /**
    00150      * The Aperios handler that is called when a receiver announces that it is ready to receive a package.
    00151      * @param msg An Open-R message that contains the object id of the receiver.
    00152      */
    00153     static void aperiosReady(OReadyMessage* msg)
    00154     {
    00155       theInstance->handleMessage(*msg);
    00156       Return();
    00157     }
    00158
    00159   protected:
    00160     /**
    00161      * The function prepares a package.
    00162      * The function should be pure virtual, but GreenHills does not like that.
    00163      */
    00164     virtual void preparePackage() {}
    00165
    00166     /**
    00167      * The functions sets a package for a receiver.
    00168      * The function should be pure virtual, but GreenHills does not like that.
    00169      * @param receiver The receive the package will be sent to.
    00170      */
    00171     virtual void setPackage(const ObserverID& receiver) {}
    00172
    00173     /**
    00174      * The function frees the package.
    00175      * The function should be pure virtual, but GreenHills does not like that.
    00176      */
    00177     virtual void freePackage() {}
    00178
    00179   private:
    00180     /**
    00181      * The function sends a package to all receivers that requested it.
    00182      */
    00183     void sendPackage()
    00184     {
    00185       if(numOfAlreadyReceived != -1)
    00186       { // send() has been called at least once
    00187         int i;
    00188         for(i = 0; i < numOfReceivers; ++i)
    00189         {
    00190           int j;
    00191           for(j = 0; j < numOfAlreadyReceived; ++j)
    00192             if(receiver[i] == alreadyReceived[j])
    00193               break;
    00194           if(j == numOfAlreadyReceived)
    00195             break; // receiver[i] has not received its requested package yet
    00196         }
    00197         if(i < numOfReceivers)
    00198         { // at least one receiver has not received its requested package, so prepare one
    00199           preparePackage();
    00200           // Send this package to all the receivers that requested it and that have not received it yet
    00201           i = 0;
    00202           while(i < numOfReceivers)
    00203           {
    00204             int j;
    00205             for(j = 0; j < numOfAlreadyReceived; ++j)
    00206               if(receiver[i] == alreadyReceived[j])
    00207                 break;
    00208             if(j == numOfAlreadyReceived)
    00209             { // receiver[i] has not received its requested package yet
    00210               setPackage(receiver[i]);
    00211               VERIFY(NotifyObserver(receiver[i]) == oSUCCESS);
    00212               // note that receiver[i] has received the current package
    00213               ASSERT(numOfAlreadyReceived < RECEIVERS_MAX);
    00214               alreadyReceived[numOfAlreadyReceived++] = receiver[i];
    00215               // remove receiver[i] from the list
    00216               receiver[i] = receiver[--numOfReceivers];
    00217             }
    00218             else
    00219               ++i;
    00220           }
    00221           // The sender does not need the package anymore
    00222           freePackage();
    00223         }
    00224       }
    00225     }
    00226
    00227
    00228   public:
    00229     /**
    00230      * The constructor.
    00231      * @param process The process this sender is associated with.
    00232      * @param senderName The Aperios connection name of the sender without the process name.
    00233      * @param blocking Decides whether this sender blocks the execution of the next frame
    00234      *                 until all connected receivers have requested a new package.
    00235      */
    00236     SenderBase(PlatformProcess* process,const char* senderName,bool blocking)
    00237     : SenderList(process,senderName,blocking)
    00238     {
    00239       theInstance = this;
    00240       numOfReceivers = 0;
    00241       numOfAlreadyReceived = -1;
    00242     }
    00243
    00244     /**
    00245      * Fills the Aperios entry table for global functions.
    00246      * The function will write two entries into the table.
    00247      * @param entryTable The Aperios entry table.
    00248      * @param id The first empty id in the entry table.
    00249      * @return The new first empty id in the entry table.
    00250      */
    00251     int fillEntryTable(ObjectEntry* entryTable,int id)
    00252     {
    00253       eventId = (id - ENTRY_TABLE_MIN) / 2;
    00254       ASSERT(eventId <= 31); // should test on < 31
    00255       setBlockingId(eventId,blocking);
    00256       entryTable[id].selector = id;
    00257       entryTable[id++].entry = (Entry) aperiosControl;
    00258       entryTable[id].selector = id;
    00259       entryTable[id++].entry = (Entry) aperiosReady;
    00260       return id;
    00261     }
    00262
    00263     /**
    00264      * Returns whether a new package was requested from the sender.
    00265      * This is always true if this is a blocking sender.
    00266      * @return Has a new package been requested?
    00267      */
    00268     bool requestedNew() const {return numOfReceivers > 0;}
    00269
    00270     /**
    00271      * Marks the package for sending and transmits it to all receivers that already requested for it.
    00272      * All other receiver may get it later if they request for it before the package is changed.
    00273      */
    00274     void send()
    00275     {
    00276       setBlockingId(eventId,blocking);
    00277       numOfAlreadyReceived = 0;
    00278       sendPackage();
    00279     }
    00280 };
    00281
    00282 template<class T> SenderBase<T>* SenderBase<T>::theInstance = 0;
    00283
    00284 /**
    00285  * The class implements the default sender for packages.
    00286  */
    00287 template<class T> class Sender : public SenderBase<T>
    00288 {
    00289   private:
    00290     RCRegion* package; /**< A pointer to the package. */
    00291
    00292   protected:
    00293     /**
    00294      * The function prepares a package.
    00295      */
    00296     virtual void preparePackage()
    00297     {
    00298       const T& data = *static_cast<const T*>(this);
    00299       OutBinarySize size;
    00300       size << data;
    00301       package = new RCRegion(size.getSize());
    00302       ASSERT(package);
    00303       OutBinaryMemory memory(package->Base());
    00304       memory << data;
    00305     }
    00306
    00307     /**
    00308      * The functions sets a package for a receiver.
    00309      * @param receiver The receive the package will be sent to.
    00310      */
    00311     virtual void setPackage(const ObserverID& receiver)
    00312     {
    00313       VERIFY(SetData(receiver,package) == oSUCCESS);
    00314     }
    00315
    00316     /**
    00317      * The function frees the package.
    00318      */
    00319     virtual void freePackage()
    00320     {
    00321       package->RemoveReference();
    00322     }
    00323
    00324   public:
    00325     /**
    00326      * The constructor.
    00327      * @param process The process this sender is associated with.
    00328      * @param senderName The Aperios connection name of the sender without the process name.
    00329      * @param blocking Decides whether this sender blocks the execution of the next frame
    00330      *                 until all connected receivers have requested a new package.
    00331      */
    00332     Sender(PlatformProcess* process,const char* senderName,bool blocking)
    00333     : SenderBase<T>(process,senderName,blocking)
    00334     {
    00335     }
    00336 };
    00337
    00338 #endif