VR-Link C# API Documentation
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Events Macros Pages
5.6 - 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 4.6.7 Learning when Entities Join or Leave an Exercise.

Note
If you are using ownership management, it is recommended that you 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 5.5.4 Reflecting Locally-Generated Updates.

To maintain backward compatibility with 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 unless self reflecting is turned on. If self reflecting is not turned on, you must manually manage your publish and reflected lists when an object transfer occurs. This would involve moving objects between reflected and publisher lists whenever an object's ownership changes. The Ownership Handler example shows how this management is done.

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.

The first two functions, acquireObject() and divestObject() provide the easiest most straightforward way to do ownership management. Calling one of these functions will immediately attempt to acquire or divest all the attributes of a specific object. If you do not need objects to have multiple simultaneous owners, it is recommended that you use those two functions. The remaining functions allow individual attributes to be transferred, as well as provide an HLA level of control over how ownership management will be done.

When using individual attribute ownership transfer, 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 ownershipHandler.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().)

The DtOwnershipHandler class allows you to receive ownership-related callbacks, such as notification that you have successfully acquired or divested ownership of a set of attributes, or a query to allow or disallow a requested ownership. We provide three different DtOwnershipHandler classes: DtDefaultOwnershipHandler, DtPartialOwnershipHandler, and DtRprOwnershipHandler. All three classes provide callbacks that notify your application when an acquisition or a divestiture occurs. These callbacks can be optionally defined by the type of object being transferred. They also contain functions allow you to accept, or deny all requests for ownership transfer. You may instead add a callback so you can decide to accept or deny conditionally at runtime.

The DtDefaultOwnershipHandler is built for simplicity and assumes that all ownership transfer is on an object level. If you need to transfer only some attributes, it is recommended that instead you use DtPartialOwnershipHandler which contains extra callbacks for that situation. The third class, DtRprOwnershipHandler, automatically sends acquire interactions when a transfer is successful or unsuccessful as defined by the RPR standard. Alternatively, you may write your own DtOwnershipHandler, but in most cases this is not necessary.

There are two ways to register your ownership handler. You may do so globally by calling setDefaultOwnershipHandler in your DtExerciseConn. If you do it that way, every object created or reflected after the call will be set with the ownership handler you defined. You can also register individual objects by 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."

5.6.1 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.

5.6.1.2 Example: Acquiring Objects

You discover an object, and want to acquire all of it's 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::acquireObject().
  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), you must create a DtOwnershipHandler and attach it to your object.

    void gainedOwnership(DtHlaObject* hlaObject, void* usr)
    {
    DtInfo << "Gained Ownership!" << std::endl;
    // 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.
    DtDefaultOwnershipHandler defaultHandler;
    defaultHandler.setOwnershipAcquisitionAction(OWNERSHIP_ACCEPT_ALL);
    defaultHandler.setAcquireOwnershipCallback(&gainedOwnership, 0));
    obj->setOwnershipHandler(&defaultHandler);
    // Create a publisher for the object
    DtEntityPublisher pub(obj, obj->exerciseConn());
    // Initiate the acquisition.
    obj->acquireObject();

5.6.1.1 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. If you do not care about individual attributes and just want to divest the entire object, you should instead call divestObject()
  3. If you want to be notified when another federate assumes ownership, you must create a DtOwnershipHandler and attach it to your object.

    void lostOwnership(DtHlaObject* hlaObject, void* usr)
    {
    DtInfo << "Lost Ownership!" << std::endl;
    // 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.
    DtDefaultOwnershipHandler defaultHandler;
    defaultHandler.setOwnershipDivestitudeAction(OWNERSHIP_ACCEPT_ALL);
    defaultHandler.setDivestOwnershipCallback(&lostOwnership, 0));
    obj->setOwnershipHandler(&defaultHandler);
    // 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;

5.6.1.3 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. Create a DtOwnershipHandler for your publisher that accepts all divestitude actions

    void lostOwnership(DtHlaObject* hlaObject, void* usr)
    {
    DtInfo << "Lost Ownership!" << std::endl;
    // 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.
    DtDefaultOwnershipHandler defaultHandler;
    defaultHandler.setOwnershipDivestitudeAction(OWNERSHIP_ACCEPT_ALL);
    defaultHandler.setDivestOwnershipCallback(&lostOwnership, 0));
    obj->setOwnershipHandler(&defaultHandler);

5.6.1.4 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 a default ownership handler and assign it to your exercise connection. All objects, reflected or published will now use this handler
  2. Set the default acquisition action of this handler to always accept all acquisitions
  3. Add a callback informing you when an aquisition is successful
  4. Create the reflected object list as usual.

    void gainedOwnership(DtHlaObject* hlaObject, void* usr)
    {
    DtInfo << "Gained Ownership!" << std::endl;
    // Do Something
    }
    DtDefaultOwnershipHandler defaultHandler;
    defaultHandler.setOwnershipAcquisitionAction(OWNERSHIP_ACCEPT_ALL);
    defaultHandler.setAcquireOwnershipCallback(&gainedOwnership, 0));
    myExerciseConnection->setOwnershipHandler(&defaultHandler);
    // Create the reflected entity list,
    DtReflectedEntityList rel(...);

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


Document ID: Generated on Thu Oct 16 00:12:25 EDT 2025 from SVN revision 280738
Copyright © 1992-2025 MAK Technologies. All Rights Reserved (www.mak.com)