Understanding Instance States

This article explains what Instances and Instance States are, describes how they apply whether you use them or not, and clears up some common configurations affecting Instance States.

Instances

An Instance is defined as representing a unique object within a Topic, identified by unique values of key fields. Instances are useful if your data model describes individual real-world objects; Instances represent these individual objects on a DDS level. Take the following IDL data type, for example: 

struct VehicleData
{
    @key int32 vehichleId;
    float velocity;
    // ... Additional information
};   

Here the data type has a single key field, vehicleId, which forms a Key, meaning that all data samples that share a vehicleId represent the same vehicle. In more generic terms, all data samples that have the same Key represent the same Instance.

Many QoS settings and APIs work on a per-Instance basis allowing you to, for example, set the maximum history depth per-Instance instead of per-Topic, or read the latest sample from a given Instance. In our vehicle example above, this means that we can easily keep track of the latest velocity of each individual vehicle -- if the history QoS worked per-Topic we would only have the most recent velocity published for one vehicle instead of all the individual vehicles.

However, defining key fields for a data type is not mandatory and, depending on your data model, may not be necessary. The RTI Connext Getting Started Guide has some useful overview information about Instances in Introduction to Keys and Instances.

Instance States

There are three possible Instance States for an Instance that are defined by the OMG DDS Standard: ALIVE, NOT_ALIVE_DISPOSED, and NOT_ALIVE_NO_WRITERS.

An Instance will enter the ALIVE state upon being written to by a DataWriter, and will enter one of the two NOT_ALIVE_ states if it is no longer expecting to be written to. An Instance will transition to NOT_ALIVE_DISPOSED if one DataWriter disposes of the Instance (*see the section ‘Ownership’ below). An Instance will transition to NOT_ALIVE_NO_WRITERS if all DataWriters that have written to that Instance unregister from it or lose liveliness.

As one might expect, Instance States are useful for determining the state of a real-world object that an Instance represents. Without Instance States, you would have to track these states at the application level. While the semantic meaning of dispose varies from system to system, it generally indicates that an object/Instance no longer exists for the purposes of a system. An unregister or loss of liveliness means that an object/Instance will not be updated by a given DataWriter.

If we take the previous VehicleData data type example and assume that it is being used to track cars in a car park, then an Instance entering the NOT_ALIVE_DISPOSED state could indicate that the Instance (a specific car) has been detected leaving the car park and thus no longer exists within the context of the system. An Instance in the NOT_ALIVE_NO_WRITERS state means that there are no sensors currently responsible for updating information regarding that vehicle.

Configuration options affecting instances

There are various QoS settings that modify the transition between Instance States. Some of these are:

Transitions between NOT_ALIVE Instance states

By default, there is no state transition between the NOT_ALIVE_NO_WRITERS and NOT_ALIVE_DISPOSED states. However there are QoS settings that can modify the behavior of Instance State transitions. Some of these include:

  • propagate_dispose_of_unregistered_instances: When set to true, allows transitions from NOT_ALIVE_NO_WRITERS to NOT_ALIVE_DISPOSED, or allows the initial state to be NOT_ALIVE_DISPOSED. With this it is also possible that the first message a DataReader receives about an instance is NOT_ALIVE_DISPOSED.
  • propagate_unregister_of_disposed_instances: When set to true, allows transitions from NOT_ALIVE_DISPOSED to NOT_ALIVE_NO_WRITERS.
  • autodispose_unregistered_instances: When set to false, unregistering an instance will set the Instance State to NOT_ALIVE_NO_WRITERS. If set to true, unregistering an Instance (either manually or implicitly by deleting a DataWriter), will set the Instance State to NOT_ALIVE_DISPOSED instead. Note: in versions of RTI Connext prior to 6.1.0, the autodispose_unregistered_instances QoS is set to true by default.
  • ownership: If set to EXCLUSIVE, only the DataWriter with the highest ownership_strength can dispose an Instance and thus transition to the NOT_ALIVE_DISPOSED state. See below for more detail on how exclusive ownership affects instance state transitions.

A full list of QoS settings that affect instances can be found under “QoS Configuration and Instances” in the Core Libraries User’s Manual.

Ownership

The OWNERSHIP Qos Policy specifies whether a DataReader receives data for an instance of a Topic sent by multiple DataWriters.

When the DataWriters’ OWNERSHIP is set to EXCLUSIVE, only the DataWriter with the highest OWNERSHIP_STRENGTH that has written the instance is the owner of the instance. It will remain the owner unless it unregisters the instance, loses liveliness, or is deleted.

Hence, it is also the only DataWriter that can dispose the instance (it does not lose ownership by disposing). Other DataWriters with a lower OWNERSHIP_STRENGTH can call dispose(), but their dispose will have no effect on the instance state.

Instance state consistency

A common misunderstanding are the Instance State transitions when a DataWriter’s liveliness is lost. This is controlled by the instance_state_consistency_kind in the 47.21 RELIABILITY QosPolicy

By default (instance_state_consistency_kind=NO_RECOVER_INSTANCE_STATE_CONSISTENCY), when liveliness is recovered between the DataWriter and DataReader, an Instance will not transition out of the NOT_ALIVE_NO_WRITERS state until that instance is updated.

With instance_state_consistency_kind=RECOVER_INSTANCE_STATE_CONSISTENCY, the Instance state is restored on the DataReader when liveliness is recovered, even before the DataWriter sends a new sample.

Note: the instance_state_consistency_kind was introduced in Connext 7. In prior versions the state of the instance stays in the NOT_ALIVE_NO_WRITERS state until the DataWriter updates the instance.

Attached vs detached instances

An instance can be considered attached or detached. This is composed of two parts, which make up the instance metadata: an active state and a minimum state:

  • Attached: the DataReader is actively managing all possible state that can be associated with an instance
  • Detached: the DataReader is only maintaining the minimum state for the instance.

When instances are removed from the DataReader queue (either because they are replaced or purged), the minimum state is kept around (and only the active state is removed). This can be controlled with keep_minimum_state_for_instances.

You can find more information about attached/detached instances in the section Active State and Minimum State from the Core Libraries User's Manual.

Instance replacement

The instance_replacement field controls whether instances can be replaced to make room for new ones. This Resource Limit can be configured for both DataWriters and DataReaders. The possible values are:

  • DDS_UNREGISTERED_INSTANCE_REPLACEMENT (default)
  • DDS_ALIVE_INSTANCE_REPLACEMENT
  • DDS_DISPOSED_INSTANCE_REPLACEMENT
  • DDS_ALIVE_THEN_DISPOSED_INSTANCE_REPLACEMENT
  • DDS_DISPOSED_THEN_ALIVE_INSTANCE_REPLACEMENT
  • DDS_ALIVE_OR_DISPOSED_INSTANCE_REPLACEMENT

Note: Unregistered instances are always replaced first even if you don't choose DDS_UNREGISTERED_INSTANCE_REPLACEMENT.

This setting can be applied on the DataWriter and DataReader. Learn more in the User’s Manual:

Overview of instance states and transitions

With the previous configurations in mind, the following diagram shows how RTI Connext handles the different possible transitions between Instance States:

  • (1) Depends on RECOVER_INSTANCE_STATE_CONSISTENCY as explained in the ‘Instance State Consistency’ section from this article.
  • (2) If reader_qos.protocol.propagate_unregister_of_disposed_instances is set to TRUE. See the ‘Transitions between NOT_ALIVE Instance states’ section above.
  • (3) If reader_qos.protocol.propagate_dispose_of_unregistered_instances is set to TRUE. See the ‘Transitions between NOT_ALIVE Instance states’ section above.

This has been a quick overview with basic information regarding the use of Instances. Some details, such as the impact of Instances on memory or information on the APIs that can be used with Instances, have been omitted for the sake of simplicity. For a more in-depth guide to Instances, see the following sections of the Core Libraries User's Manual: