VR-Link API Documentation for DIS
Ownership Management

Table of Contents

VR-Link supports HLA ownership management services, which allow you to transfer the responsibility for sending updates for particular object attributes from one federate to another.

Most ownership management functionality is accessed through the DtHlaObject class. Recall that both DtObjectPublishers and DtReflectedObjects have member functions called hlaObject() that return the DtHlaObject that is being published or reflected. DtHlaObject encapsulates the HLA details of an object.

One conceptual change necessitated by support for ownership management is that the line between a locally simulated object and a reflected object is blurred. It is possible to have both a DtObjectPublisher and a DtReflectedObject associated with the same HLA object. That is, they share a DtHlaObject.

The publisher is still responsible for sending out updates for owned attributes. If you want to own and update any attributes of a particular object, you must create a publisher for that object, even if you are not the federate that registers the object with the RTI. DtObjectPublisher and its subclasses have a constructor that allows you to create a publisher for an existing DtHlaObject.

The reflected object is still responsible for collecting attribute updates sent by the owners of the various attributes, and presenting the reflected view of the object's current state through its state repository. However, now there may not be a single federate sending all of the attribute updates for an object, and some of the updates may even be coming from the local federate.

When a publisher's destructor is called, VR-Link will, by default, delete the corresponding HLA object if and only if the local federate owns the privilegeToDelete attribute. (And of course, because the HLA object gets deleted, the corresponding DtReflectedObject will be deleted and removed from your reflected object lists.) You can use DtObjectPublisher's setDeleteObjInDtorFlag() to change this behavior so that VR-Link does not delete the HLA object even if the local application owns the privilegeToDelete attribute. Use deleteObjInDtorFlag() to check the current status of the flag.

Because you can have a publisher for an object for which you do not own the privilege to delete, it is possible for your publisher's underlying HLA object to be deleted by a remote federate. When this occurs, your publisher's DtHlaObject pointer is set to NULL, and subsequent ticks will effectively be no-ops. To be notified when a

DtHlaObject is deleted so that you can delete the corresponding publisher (which is now useless), you can register a removeObject() callback with the DtHlaObject using its addRemoveObjectCb() function. Alternatively, you can register an objectRemoval() callback for the corresponding DtReflectedObject with your DtReflectedObjectList. For more information, please see Learning when Entities Join or Leave an Exercise.

To maintain backward compatibility with older releases for federates that do not use ownership management, creating a publisher and updating attributes does NOT, by default, result in the creation of a corresponding reflected object in the reflected object list, and the reflection of locally generated attribute updates.

Note:
If you are using ownership management, you must call DtExerciseConn::set-Reflecting() to enable these things to happen. Failing to call setReflecting() means that a DtReflectedObject only processes attributes updates generated by remote federates, so that the reflected object may not contain the complete current state of the object. For more information, please see Reflecting Locally-Generated Updates.

DtHlaObject has the following member functions that wrap the RTI's federate-initiated ownership management services:

In general, you should use VR-Link's ownership-related functions rather than calling the RTI's functions directly, to insure that VR-Link can keep its ownership information consistent with the RTI's.

VR-Link keeps track of the locally-owned attributes of each object, and its publishers send attribute updates only for owned attributes. The current set of owned attributes for a particular DtHlaObject is obtained using its ownedAttributes() member function.

RTI-initiated ownership management services (the RTI-callbacks) are intercepted by VR-Link (again to keep VR-Link's ownership information current), and then passed along to application code through a class called DtOwnershipHandler (defined in ownerHandler.h). (Remember, all RTI-initiated callbacks, including these ownership management calls, are called from within the RTI's tick function, which is called by DtExerciseConn::drainInput().)

To receive ownership-related callbacks, such as notification that you have successfully acquired or divested ownership of a set of attributes, you must subclass DtOwnershipHandler, overriding VR-Link's virtual functions with versions that you want to have called when these events occur. You then register an instance of your subclass with a particular DtHlaObject, using DtHlaObject's setOwnershipHandler() member function. By doing so, you are saying to VR-Link: "This is the object I want you to use to handle incoming ownership information for this particular HLA object."

Most DtOwnershipHandler functions that you may want to override have the same names as their corresponding RTI services:

In addition, gainOwnership and loseOwnership are called whenever the federate actually gains or loses attributes, regardless of which ownership management mechanisms were used to effect the transfer.

Implementing Ownership Management

HLA allows a transfer of ownership to be initiated by either the potential acquirer or divestor. On the following pages, we describe a few examples that use the various mechanisms.

Example: Divesting Attributes

You register an object, and then want to give up some attributes:

  1. Create the publisher as usual, which results in the registration of a new object with the RTI, and the creation of a DtHlaObject by VR-Link.
  2. In order to initiate the divestiture of attributes, call either unconditionalDivest() or negotiatedDivest() on the publisher's DtHlaObject. With unconditionalDivest(), the attributes immediately become unowned, and remain unowned until someone acquires them. With negotiatedDivest(), the divesting federate retains ownership until another federate agrees to assume ownership of them.
  3. If you want to be notified when another federate assumes ownership, you need to subclass DtOwnershipHandler, and override the virtual function attributeOwnershipDivestitureNotification().

    // Your subclass of DtOwnershipHandler
    class MyOwnershipHandler : public DtOwnershipHandler
    {
    public:
    
       virtual void attributeOwnershipDivestitureNotification(
          const RTI::AttributeHandleSet& attributes)
       {
          // Do something
       }
    };
    
    // Create the publisher, and grab its DtHlaObject
    DtEntityPublisher pub(classHandle, conn);
    DtHlaObjectWithStateRep* obj = pub.hlaObject();
    
    // Instantiate your handler class, and tell the DtHlaObject to use the
    // instance.
    MyOwnershipHandler handler;
    obj->setOwnershipHandler(&handler);
    
    // Initiate the divest
    // ******************** RTI 1.3 only *********************
    // The rest of this example is for RTI 1.3 only
    RTI::AttributeHandleSet* hSet =
       RTI::AttributeHandleSetFactory::create(3);
    hSet->add(1);
    hSet->add(2);
    hSet->add(3);
    obj->negotiatedDivest(*hSet);
    delete hSet;
    

Example: Acquiring Attributes

You discover an object, and want to acquire some attributes:

  1. Create the reflected object list as usual.
  2. At some point after you have discovered the object in question, create a publisher for the object, passing the reflected object's DtHlaObject to the publisher's constructor. This publisher constructor will not try to register the object, since it already exists.
  3. Call DtHlaObject::acquireAttributes(). The ifAvailable flag indicates whether or not you want to acquire only attributes that are currently unowned. Your publisher is automatically notified when the acquisition succeeds.
  4. If you want your application code to be notified when the acquisition succeeds (so that you know, for example, to start actually simulating the relevant parts of the object), subclass DtOwnershipHandler. In this case, override attributeOwnershipAcquisitionNotification().

    // Your subclass of DtOwnershipHandler
    class MyOwnershipHandler : public DtOwnershipHandler
    {
    public:
    
       virtual void attributeOwnershipAcquisitionNotification(
          const RTI::AttributeHandleSet& attributes)
       {
          // Do something
       }
    };
    
    // Create the reflected entity list
    DtReflectedEntityList rel(...);
    ...
    // Find the entity you are interested in, and grab its DtHlaObject
    DtReflectedEntity* ent = rel.lookup(...);
    DtHlaObjectWithStateRep* obj = ent->hlaObject();
    
    // Instantiate your handler class, and tell the DtHlaObject to use the
    // instance.
    MyOwnershipHandler handler;
    obj->setOwnershipHandler(&handler);
    
    // Create a publisher for the object
    DtEntityPublisher pub(obj, obj->exerciseConn());
    
    // Initiate the acquisition.
    // ******************** RTI 1.3 only *********************
    // The rest of this example is for RTI 1.3 only
    RTI::AttributeHandleSet* hSet =
       RTI::AttributeHandleSetFactory::create(3);
    hSet->add(1);
    hSet->add(2);
    hSet->add(3);
    obj->acquireAttributes(*hSet);
    

Example: Giving Up Attributes if Requested

You do not want to initiate a divestiture, but you want to give up attributes of an object if another federate requests them:

  1. Create the publisher as usual.
  2. Subclass DtOwnershipHandler.
  3. Tell the publisher's DtHlaObject to use an instance of your subclass.
  4. In your subclass, override the function requestAttributeOwnershipRelease() with an implementation that calls unconditionalDivest() on the requested attributes. When a remote federate attempts to acquire attributes that you own, your function is called, which allows the transaction to complete.

    // Your subclass of DtOwnershipHandler
    class MyOwnershipHandler : public DtOwnershipHandler
    {
    public:
    
       virtual void requestAttributeOwnershipRelease(
          const RTI::AttributeHandleSet& attributes,
          const char* tag)
       {
          // As a result of being asked to release some attributes, 
          // go ahead and release them.
          hlaObject()->unconditionalDivest(attributes);
       }
    };
    
    // Create the publisher, and grab its DtHlaObject
    DtEntityPublisher pub(classHandle, conn);
    DtHlaObjectWithStateRep* obj = pub.hlaObject();
    
    // Instantiate your handler class, and tell the DtHlaObject to use the
    // instance.
    MyOwnershipHandler handler;
    obj->setOwnershipHandler(&handler);
    

Example: Acquiring Attributes if Offered

You do not want to initiate an acquisition, but you want to acquire attributes of an object if another federate initiates a divest:

  1. Create the reflected object list as usual.
  2. Once you have discovered the object in question, grab a pointer to its DtHlaObject.
  3. Subclass DtOwnershipHandler.
  4. Tell the DtHlaObject to use an instance of your subclass.
  5. In your subclass, override the function requestAttributeOwnershipAssumption() with an implementation that calls acquireAttributes() on the requested attributes. When a remote federate attempts to divest ownership of some attributes that you are capable of updating (that is, attributes that you have published) your function will be called, allowing you to indicate that you are willing to take ownership of the attributes.
  6. Override attributeOwnershipAcquisitionNotification(), to be notified if the transaction has actually completed, because if another federate responded to the request before you, you will not actually receive ownership of the attributes.
  7. At some point, create a publisher for the object, passing the DtHlaObject in question to the publisher's constructor. You can either do this before acquiring the attributes, or once you know that you have secured the attributes.

    class MyOwnershipHandler : public DtOwnershipHandler
    {
    public:
    
       virtual void requestAttributeOwnershipAssumption(
          const RTI::AttributeHandleSet& attributes,
          const char* tag)
       {
          // As a result of being asked to acquire some attributes, 
          // go ahead and acquire them.
          hlaObject()->acquireAttributes(releasedAttributes);
       }
    
       virtual void attributeOwnershipAcquisitionNotification(
          const RTI::AttributeHandleSet& attributes)
       {
          // You might want to create the publisher here, now that you
          // know you will actually need it.
          pub = new DtEntityPublisher(
             hlaObject(), hlaObject()->exerciseConn());
       }
    };
    
    // Create the reflected entity list, 
    DtReflectedEntityList rel(...);
    ...
    // Find the entity you're interested in, and grab its DtHlaObject
    DtReflectedEntity* ent = rel.lookup(...);
    DtHlaObjectWithStateRep* obj = ent->hlaObject();
    
    // Instantiate your handler class, and tell the DtHlaObject to use the
    // instance.
    MyOwnershipHandler handler;
    obj->setOwnershipHandler(&handler);
    

[<< Managing HLA Objects] [Home] [Top of Page] [Using DDM >>]


Document ID: Generated on Mon May 14 08:06:18 EDT 2012 from SVN revision 114750
Copyright © 2005-2012 VT MÄK Inc. All Rights Reserved (www.mak.com)