00001 #ifndef HLA_OBJECT_INSTANCE_H_ 00002 #define HLA_OBJECT_INSTANCE_H_ 00003 00004 #include "base/cleancontainers.h" 00005 #include <queue> 00006 00007 #include "ftk.h" 00008 #include "base/msftypes.h" 00009 00010 // forward declaration 00011 class HLAObjectClass; 00012 class InstanceClient; 00013 class MessageClient; 00014 class MethodMessage; 00015 00016 /** 00017 * This class represents an instance of an HLA object. 00018 * @ingroup ftk 00019 */ 00020 class HLAObjectInstance 00021 { 00022 public: 00023 /** 00024 * Constructor - creates an object instance of class @a clname. 00025 * 00026 * This constructor is used by a federate which wants to create 00027 * its own local objects in order to register them with the RFI 00028 * (by using RFI::registerObjectInstance()). 00029 * 00030 * @see RFI::registerObjectInstance() 00031 */ 00032 HLAObjectInstance (const char* clname); 00033 00034 /** 00035 * Contructor - creates an object instance having an object handle 00036 * and an HLAObjectClass. 00037 * 00038 * This constructor is used by the Federate Ambassador when it 00039 * discovers an object and wants to add it to the local object list 00040 * (by using RFI::addObjectInstance()). 00041 * 00042 * @see RFI::addObjectInstance() 00043 */ 00044 HLAObjectInstance (ftk::HANDLE objHandle, ftk::HANDLE classHandle); 00045 00046 /** 00047 * Destructor. 00048 * 00049 * Does some cleaning and removes the object instance from the 00050 * federation. 00051 */ 00052 virtual ~HLAObjectInstance (void); 00053 00054 /** 00055 * Removes this object from the Federation. 00056 */ 00057 void removeFromFederation (void); 00058 00059 /** 00060 * Returns the class (HLAObjectClass) of the object instance. 00061 */ 00062 HLAObjectClass* getObjectClass (void); 00063 00064 /** 00065 * Returns the class handle for this object instance. 00066 */ 00067 ftk::HANDLE classHandleGet (void); 00068 00069 /** 00070 * Returns the class name of this object instance. 00071 */ 00072 const char* classNameGet (void); 00073 00074 /** 00075 * Sets the handle for this object instance. 00076 * 00077 * This should be done only by a method which get this handle 00078 * from the RTI. 00079 */ 00080 void handleSet (ftk::HANDLE id); 00081 00082 /** 00083 * Returns the handle for this object instance. 00084 */ 00085 ftk::HANDLE handleGet (void); 00086 00087 /** 00088 * Sets boolean defining whether or not this object has been 00089 * discovered. 00090 * 00091 * @param d @c true signifies that this object has been 00092 * discovered. 00093 * @c false signifies that this object has been 00094 * created by this federate. 00095 */ 00096 void discovered (bool d); 00097 00098 /** 00099 * Tests whether or not this object has been discovered. 00100 * 00101 * @return @c true if this object has been discovered by 00102 * the federate, @c false if this object was 00103 * created by the federate itself. 00104 */ 00105 bool discovered (void); 00106 00107 /** Mark the instance as zombie or not. 00108 * An instance is considered as zombie when it still exist in the LRC, but 00109 * not in the RTIexec database. This situation typically occurs after a 00110 * reset. A zombie instance will not try to remove itself from the 00111 * federation a destruction. */ 00112 void zombie(bool z); 00113 00114 /** Return the zombie state of the instance (see above method). */ 00115 bool zombie(); 00116 00117 bool isAttributeInitialized(ftk::ATTRIBUTE_INDEX index); 00118 00119 bool isAttributeInitialized(ftk::HANDLE h) { 00120 map<ftk::HANDLE, bool>::iterator it = initialized_attributes.find(h); 00121 if ( it != initialized_attributes.end() ) return (*it).second; 00122 else return false; 00123 } 00124 00125 /** 00126 * Returns the data corresponding to the given handle. 00127 * 00128 * This method is purely virtual and has to be implemented by 00129 * derived classes which know about the queried data. 00130 * 00131 * @param h attribute handle 00132 * @param data reference to a pointer to a char buffer 00133 * @param size the size of the buffer containing the desired 00134 * data 00135 * @warning The caller of this function just provides a 00136 * pointer to the buffer. The memory for the data 00137 * should then be allocated. (In normal FTK usage 00138 * this is done by the XDRmessage.getBuffer(data) 00139 * call.) <b>But it is up to the caller to delete the 00140 * allocated memory.</b> 00141 * 00142 * @see HLAObjectInstance::processPendingUpdates() for 00143 * a correct example. 00144 */ 00145 virtual bool getAttributeData (ftk::HANDLE h, 00146 char*& data, 00147 unsigned int& size) = 0; 00148 00149 /** 00150 * Sets the data corresponding to a given handle. 00151 * 00152 * This method is purely virtual and has to be implemented by 00153 * derived classes: making this call causes the concerned sub-class 00154 * to set its correct data member (identified by h) with the given 00155 * data. 00156 * 00157 * @param h attribute handle 00158 * @param data pointer to the buffer containing the data to 00159 * set 00160 * @param size size of the data to set 00161 */ 00162 virtual bool setAttributeData (ftk::HANDLE h, 00163 const char* data, 00164 unsigned int size) = 0; 00165 00166 /** 00167 * Pushes the request for an update for the attribute with the given 00168 * handle to a local queue. 00169 * Clients of this objectinstance will be notified that all updates 00170 * requests have been performed with the attributesInitialized callback. 00171 */ 00172 // inline void queueAttributeRequest (ftk::HANDLE handle); 00173 void queueAttributeRequest (ftk::HANDLE handle); 00174 00175 /** 00176 * Pushes the action to update the attribute with the given handle to 00177 * a local queue. 00178 */ 00179 // inline void queueAttributeUpdate (ftk::HANDLE handle); 00180 void queueAttributeUpdate (ftk::HANDLE handle); 00181 00182 /** 00183 * Pushes the request to acquire the ownership of 00184 * the attribute with the given handle to a local queue. 00185 * Clients of this objectinstance will be notified that all acquisitions 00186 * requests have been performed with the onwershipsAcquired callback. 00187 */ 00188 // inline void queueAttributeAcquisition (ftk::HANDLE handle); 00189 void queueAttributeAcquisition (ftk::HANDLE handle); 00190 00191 /** 00192 * Pushes the action to release the ownership of 00193 * the attribute with the given handle to a local queue. 00194 */ 00195 // inline void queueAttributeRelease (ftk::HANDLE handle); 00196 void queueAttributeRelease (ftk::HANDLE handle); 00197 00198 /** 00199 * Processes the pending update actions. 00200 */ 00201 int processPendingUpdates (void); 00202 00203 /** 00204 * Processes the pending update request(s). 00205 */ 00206 int processPendingRequests (void); 00207 00208 /** 00209 * Processes the pending ownership release(s). 00210 */ 00211 int processPendingReleases (void); 00212 00213 /** 00214 * Processes the pending ownership acquisitiions(s). 00215 */ 00216 int processPendingAcquisitions (void); 00217 00218 /** 00219 * Processes all the pending actions present in the local queues. 00220 */ 00221 int processPendings (unsigned char what); 00222 00223 /** 00224 * Sends a request for ownership of a given set of attributes to the 00225 * RTI. 00226 * 00227 * The attribute ownership acquisition is perfomed on the basis of 00228 * the priority argument. The federate can acquire the attribute 00229 * only if the given priority is higher than the priority that 00230 * the owning federate has given to this object class. 00231 */ 00232 bool attributeOwnershipAcquisition (set<ftk::ATTRIBUTE_INDEX>& attr, 00233 unsigned char priority); 00234 00235 /** 00236 * Unconditionally releases a set of attributes. 00237 */ 00238 bool unconditionalAttributeOwnershipDivestiture (set<ftk::ATTRIBUTE_INDEX>& attr); 00239 00240 /** 00241 * Sets a boolean defining whether or not an object is owned. 00242 * 00243 * This call assigns the value of @c o to @b all the attributes 00244 * of this object. 00245 */ 00246 // void owned (bool o); 00247 00248 /** 00249 * Tests whether or not the attribute with the given handle is owned 00250 * by the federate. 00251 * 00252 * @return @c true if the attribute is owned by the 00253 * federate, @c false otherwise 00254 */ 00255 bool attributeOwned (ftk::HANDLE h); 00256 00257 /** 00258 * Sets the boolean defining whether or not the attribute with the 00259 * given handle is owned by the federate. 00260 */ 00261 void attributeOwned (ftk::HANDLE h, bool o); 00262 00263 /** Return the number of clients this object instance has. */ 00264 size_t getNumberOfClients(); 00265 00266 /** Set a new client of this object instance. 00267 * Return false if the client is already in the list, true otherwise 00268 * (after insertion). */ 00269 bool addClient(MessageClient *client); 00270 00271 /** Remove a client from the list of this object instance. 00272 * Return false if the client was not in the list, false otherwise 00273 * (after deletion). */ 00274 bool removeClient(MessageClient *client); 00275 00276 00277 bool addClient(InstanceClient *client); 00278 00279 bool removeClient(InstanceClient *client); 00280 00281 void notifyRemoval(void); 00282 00283 /** Return a pointer on the first client of this object instance. */ 00284 MessageClient* getFirstClient(); 00285 00286 /** Return a pointer on the next client of this object instance. */ 00287 MessageClient* getNextClient(); 00288 00289 /** 00290 * Tests whether or not the object instance has been marked as 00291 * identified. 00292 * 00293 * "Identified" means that all the necessary attributes to completely 00294 * identify this object instance have been initialized. 00295 */ 00296 bool isIdentified (void) { 00297 return _identified; 00298 } 00299 00300 /** Returns if the object is ready to use or not. 00301 * The significance of ready is application dependent. 00302 */ 00303 bool isReady(void) { 00304 return _ready; 00305 } 00306 00307 /** 00308 * Tests whether or not this object instance has been fully 00309 * initialized. 00310 * 00311 * @return @c true when all the attributes of this object 00312 * have received at least one valid update, 00313 * @c false otherwise. 00314 */ 00315 bool isComplete (void) { 00316 return _complete; 00317 } 00318 00319 /** 00320 * Tests whether or not this object instance has been represented by 00321 * this federate. 00322 * 00323 * "Represented" could be used for any purpose by the federate. 00324 * Normally it is used to determine if the federate has created a 00325 * specific object to represent/manage its HLA equivalent. 00326 */ 00327 bool isRepresented (void) { 00328 return _represented; 00329 } 00330 00331 /** Set the object as represented. */ 00332 void setRepresented (void) { 00333 _represented = true; 00334 } 00335 00336 void setIdentifierAttribute (ftk::HANDLE h); 00337 00338 void addReadyRequiredAttribute (ftk::HANDLE h); 00339 00340 /** This method will be called when the instance has been identified. 00341 * This is to derived classes of HLAObjectInstance to initiate this call 00342 * (for example when it receive an relection for an identifier). The 00343 * method should be implemented by derived classes. 00344 */ 00345 virtual void identified(void) { /* do nothing */ }; 00346 00347 /** This method will be called when the instance is ready to use by a 00348 * specific federate. 00349 */ 00350 virtual void ready(void) { /* do nothing */ }; 00351 00352 /** This method will be called when all the attributes of this instance 00353 * have been initialized. 00354 * This method is called from the HLAObjectInstance level: developper 00355 * of derived classes does not have to initiate this call, but can 00356 * implement the method itself. 00357 */ 00358 virtual void complete(void) { /* do nothing */ }; 00359 00360 #if defined(_MIPS_SIM) 00361 // Suppress REMARK 3201: The parameter "h" was never referenced. 00362 #pragma set woff 3201 00363 #endif 00364 00365 /** This method will be called when the federateambassador process 00366 * an attribute reflection. */ 00367 virtual void reflect(ftk::HANDLE h) { /* do nothing */ }; 00368 00369 /** This method could be implemented by derived classes to handle 00370 * message attached to an instance. */ 00371 virtual void messageReceived(MethodMessage* msg) { /* do nothing */ }; 00372 00373 #if defined(_MIPS_SIM) 00374 #pragma reset woff 3201 00375 #endif 00376 00377 /** Check if the attribute reflection satisfies any request and make 00378 * the object fully identified and propagate the attribute inside 00379 * the object and its clients. */ 00380 void processReflection(ftk::HANDLE h); 00381 00382 /** Check the status of pendinf acquisitions. 00383 Using the given handle, this method checks if after this ownership 00384 acquisition notification there is still pending acquisitions. If not, 00385 then the method will notify all clients that all the acquisitions 00386 requests have been satisfied (with onwershipsAcquired). 00387 */ 00388 void checkPendingAcquisitions(ftk::HANDLE h); 00389 00390 /** Set the full name of the entity */ 00391 void nameSet(std::string name); 00392 00393 /** Return the full name of the entity (with its hierachy). 00394 K9:HazCam:Physical -> K9:HazCam:Physical 00395 */ 00396 std::string nameGet() const; 00397 00398 /** Return the short name of the entity. 00399 K9:HazCam:Physical -> Physical 00400 */ 00401 std::string entityNameGet(void); 00402 00403 /** Return the parent full name of the entity. 00404 K9:HazCam:Physical -> K9:HazCam 00405 */ 00406 std::string parentNameGet(void); 00407 00408 /** Return the depth of the hierachy where this object is located. 00409 K9:HazCam:Physical -> 3 00410 */ 00411 size_t hierachyLevelGet(void); 00412 00413 /** Return the name of the parent at the given level. 00414 (K9:HazCam:Physical,1) -> K9 00415 (K9:HazCam:Physical,2) -> HazCam 00416 (K9:HazCam:Physical,3) -> Physical 00417 */ 00418 std::string nameLevelGet(size_t level); 00419 00420 virtual void print(ostream& w = cout); 00421 //##Documentation 00422 //## Set the time of the attribute update. 00423 void setAttributeTimestamp( 00424 //##Documentation 00425 //## RTI handle of the attribute 00426 ftk::HANDLE attributeHandle, 00427 //##Documentation 00428 //## Time of the update. 00429 double timeStamp); 00430 00431 00432 //##Documentation 00433 //## Return the time of the most recent update or -1 00434 //## if there is no time stamp. 00435 double getAttributeTimestamp( 00436 //##Documentation 00437 //## RTI handle of the desired attribute. 00438 ftk::HANDLE attributeHandle); 00439 00440 protected: 00441 /** 00442 * Marks the attribute with the given handle as initialized, then 00443 * checks if all the attributes have been initialized, and if so, 00444 * marks this object as initialized. 00445 * @todo: This method should go in the private section and allow only 00446 * ftkfederateambassador to call it... 00447 */ 00448 void checkInitializedAttributes (ftk::HANDLE h); 00449 00450 /** Check the status of the pending updates. 00451 Using the given handle, this method checks if after this update 00452 there is still pending updates. If not, then the method will 00453 notify all clients that all the update requests have been 00454 satisfied (with attributesInitialized). 00455 */ 00456 void checkPendingUpdates(ftk::HANDLE h); 00457 00458 /** Pointer to the class of this object */ 00459 HLAObjectClass* _objectClassPtr; 00460 00461 /** The handle of this object instance (defined by the RTI). */ 00462 ftk::HANDLE _objectHandle; 00463 00464 /** full name of this object instance. 00465 this name should be unique among the federation. 00466 this name contains the hierachy of objects. */ 00467 std::string _name; 00468 00469 /** name of the object instance without the full hierachy. */ 00470 std::string _entityName; 00471 00472 /** Full name of the parent of this object instance. */ 00473 std::string _parentName; 00474 00475 /** Depth of the hierachy */ 00476 size_t _hierarchyLevel; 00477 00478 /** A queue of the attributes to update. 00479 * This queue is needed because the RTI is not reentrant. Then if the 00480 * federateAmbassador receive a request to update an attribute, then 00481 * the application can not call right away a method to the rtiAmbassador 00482 * to provide the requested update: the federateAmbassador put 00483 * this update request in a queue which will then be processed outside 00484 * the federateAmbassador and then avoid the reentrant call to the RTI. 00485 * @todo Continue comment editing from this point [MDW] 00486 */ 00487 set<ftk::HANDLE> attributes2update; 00488 00489 /** A queue of the attribute for which this object require updates. */ 00490 queue<ftk::HANDLE> attributes2request; 00491 00492 /** A queue of the attributes to release. 00493 * This queue is needed for the same reason than attributes2update. 00494 * In this case, we maintain a queue of all the attributes for which 00495 * this federate should release the ownership. */ 00496 queue<ftk::HANDLE> attributes2release; 00497 00498 /** A queue of the attributes to acquire. */ 00499 queue<ftk::HANDLE> attributes2acquire; 00500 00501 /** This map maintained a list of the status of each attributes 00502 * regarding their ownership. 00503 * A @c true value associated with a attribute handle means that this 00504 * attribute is owned by this federate, a @c false value mean that it 00505 * is not owned by this federate. */ 00506 map<ftk::HANDLE, bool> owned_attributes; 00507 00508 /** List of clients of this message instance. */ 00509 list<MessageClient*> _msgClients; 00510 00511 /** Last returned client. */ 00512 list<MessageClient*>::iterator _currentClient; 00513 00514 list<InstanceClient*> _objClients; 00515 00516 void markAttributeInitialized(ftk::HANDLE h); 00517 00518 private: 00519 /** Define if this object been discovered (@ c true) or created by this 00520 * federate (@c false) */ 00521 bool _discovered; 00522 00523 /** Flag to store if this object instance is identified or not. */ 00524 bool _identified; 00525 00526 /** Flag to store if this object instance is ready to be used or not. */ 00527 bool _ready; 00528 00529 /** Flag to store if this object has been fully initialized or not */ 00530 bool _complete; 00531 00532 /** Flag to store if this object instance has been represented or not. */ 00533 bool _represented; 00534 00535 bool _zombie; 00536 00537 /** This method extract information from the name: entityName, 00538 parentName and hierachyLevel. */ 00539 void parseName(void); 00540 00541 /** Handle of the attribute marking the instance as identified. */ 00542 ftk::HANDLE _identifierHandle; 00543 00544 /** Set of handles marking the instance as ready.*/ 00545 set<ftk::HANDLE> _readyRequiredHandles; 00546 00547 /** Map to store if the attributes of this object instance have 00548 * been initialized or not. */ 00549 map<ftk::HANDLE, bool> initialized_attributes; 00550 00551 set<ftk::HANDLE> _pendingUpdates; 00552 set<ftk::HANDLE> _pendingAcquisitions; 00553 map<ftk::HANDLE,double> _timeStamps; 00554 00555 00556 }; 00557 00558 #endif // HLA_OBJECT_INSTANCE_H_ 00559