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 00339 00340 /* 00341 * Change log : 00342 * 00343 * $Log: Sender.h,v $ 00344 * Revision 1.1.1.1 2004/05/22 17:23:35 cvsadm 00345 * created new repository GT2004_WM 00346 * 00347 * Revision 1.2 2003/11/21 20:27:43 kerdels 00348 * Kommentare hinzugefügt 00349 * 00350 * Revision 1.1 2003/10/07 10:06:59 cvsadm 00351 * Created GT2004 (M.J.) 00352 * 00353 * Revision 1.1.1.1 2003/07/02 09:40:24 cvsadm 00354 * created new repository for the competitions in Padova from the 00355 * tamara CVS (Tuesday 2:00 pm) 00356 * 00357 * removed unused solutions 00358 * 00359 * Revision 1.3 2003/04/04 21:28:35 roefer 00360 * Communication protocol changed 00361 * 00362 * Revision 1.2 2002/12/02 11:00:13 dueffert 00363 * doxygen docu corrected 00364 * 00365 * Revision 1.1 2002/09/10 15:40:04 cvsadm 00366 * Created new project GT2003 (M.L.) 00367 * - Cleaned up the /Src/DataTypes directory 00368 * - Removed challenge related source code 00369 * - Removed processing of incoming audio data 00370 * - Renamed AcousticMessage to SoundRequest 00371 * 00372 * Revision 1.7 2002/08/14 17:11:00 dueffert 00373 * adapted by Thomas Roefer to OPENR_SDK-1.1.3-r1 and OPENR_SYS-007 00374 * 00375 * Revision 1.6 2002/07/23 13:39:39 loetzsch 00376 * - new streaming classes 00377 * - removed many #include statements 00378 * - new design of debugging architecture 00379 * - exchanged StaticQueue with MessageQueue 00380 * 00381 * Revision 1.5 2002/07/13 10:54:58 roefer 00382 * New command and sound sender 00383 * 00384 * Revision 1.4 2002/07/06 20:08:10 roefer 00385 * Advances towards gcc 00386 * 00387 * Revision 1.3 2002/07/06 15:28:28 roefer 00388 * Prologue function removed 00389 * 00390 * Revision 1.2 2002/05/25 22:52:18 roefer 00391 * WLan, first working approach 00392 * 00393 * Revision 1.1.1.1 2002/05/10 12:40:18 cvsadm 00394 * Moved GT2002 Project from ute to tamara. 00395 * 00396 * Revision 1.11 2002/05/06 16:01:44 hebbel 00397 * Added buffered Sender 00398 * 00399 * Revision 1.10 2002/04/28 19:18:18 giese 00400 * SoundPlay added... 00401 * 00402 * Revision 1.9 2002/04/21 16:09:02 roefer 00403 * Anchor removed 00404 * 00405 * Revision 1.8 2001/12/15 20:32:08 roefer 00406 * Senders and receivers are now part of the processes 00407 * 00408 * Revision 1.7 2001/12/12 13:25:02 roefer 00409 * Blocking sender fixed 00410 * 00411 * Revision 1.6 2001/12/10 17:47:08 risler 00412 * change log added 00413 * 00414 */