Index

Package: DDS.Listener

Description

package DDS.Listener is

Summary: <<interface>> Abstract base class for all Listener interfaces.

Entity:
DDS.Entity

QoS:
DDSQosTypesModule

Status:
DDSStatusTypesModule

All the supported kinds of concrete DDS.Listener interfaces (one per concrete DDS.Entity type) derive from this root and add procedures whose prototype depends on the concrete Listener.

Listeners provide a way for RTI Connext to asynchronously alert the application when there are relevant status changes.

Almost every application will have to implement listener interfaces.

Each dedicated listener presents a list of operations that correspond to the relevant communication status changes to which an application may respond.

The same DDS.Listener instance may be shared among multiple entities if you so desire. Consequently, the provided parameter contains a reference to the concerned DDS.Entity.

Access to Plain Communication Status

The general mapping between the plain communication statuses (see DDSStatusTypesModule) and the listeners' operations is as follows:

  • For each communication status, there is a corresponding operation whose name is on_<communication_status>(), which takes a parameter of type <communication_status> as listed in DDSStatusTypesModule.

  • on_<communication_status> is available on the relevant DDS.Entity as well as those that embed it, as expressed in the following figure:


    Hierarchical listener processing. The most specific relevant enabled listener is called.

  • When the application attaches a listener on an entity, it must set a mask. The mask indicates to RTI Connext which operations are enabled within the listener (cf. operation DDS.Entity set_listener() ).

  • When a plain communication status changes, RTI Connext triggers the most specific relevant listener operation that is enabled. In case the most specific relevant listener operation corresponds to an application-installed 'nil' listener the operation will be considered handled by a NO-OP operation that does not reset the communication status.

    This behavior allows the application to set a default behavior (e.g., in the listener associated with the DDS.DomainParticipant) and to set dedicated behaviors only where needed.

    Access to Read Communication Status

    The two statuses related to data arrival are treated slightly differently. Since they constitute the core purpose of the Data Distribution Service, there is no need to provide a default mechanism (as is done for the plain communication statuses above).

    The rule is as follows. Each time the read communication status changes:

  • First, RTI Connext tries to trigger the DDS.SubscriberListener.on_data_on_readers with a parameter of the related DDS.Subscriber;

  • If this does not succeed (there is no listener or the operation is not enabled), RTI Connext tries to trigger DDS.DataReaderListener.on_data_available on all the related DDS.DataReaderListener objects, with a parameter of the related DDS.DataReader.

    The rationale is that either the application is interested in relations among data arrivals and it must use the first option (and then get the corresponding DDS.DataReader objects by calling DDS.Subscriber.get_datareaders on the related DDS.Subscriber and then get the data by calling FooDataReader.read or FooDataReader.take on the returned DDS.DataReader objects), or it wants to treat each DDS.DataReader independently and it may choose the second option (and then get the data by calling FooDataReader.read or FooDataReader.take on the related DDS.DataReader).

    Note that if DDS.SubscriberListener.on_data_on_readers is called, RTI Connext will not try to call DDS.DataReaderListener.on_data_available. However, an application can force a call to the DDS.DataReader objects that have data by calling DDS.Subscriber.notify_datareaders.

    Operations Allowed in Listener Callbacks

    The operations that are allowed in DDS.Listener callbacks depend on the DDS.ExclusiveAreaQosPolicy QoS policy of the DDS.Entity to which the DDS.Listener is attached -- or in the case of a DDS.DataWriter of DDS.DataReader listener, on the DDS.ExclusiveAreaQosPolicy QoS of the parent DDS.Publisher or DDS.Subscriber. For instance, the DDS.ExclusiveAreaQosPolicy settings of a DDS.Subscriber will determine which operations are allowed within the callbacks of the listeners associated with all the DataReaders created through that DDS.Subscriber.

    Note: these restrictions do not apply to builtin topic listener callbacks.

    Regardless of whether DDS.ExclusiveAreaQosPolicy.use_shared_exclusive_area is set to DDS.BOOLEAN_TRUE or DDS.BOOLEAN_FALSE, the following operations are not allowed:

    • Within any listener callback, deleting the entity to which the DDS.Listener is attached
    • Within a DDS.Topic listener callback, any operations on any subscribers, readers, publishers or writers
    An attempt to call a disallowed procedure from within a callback will result in DDS.RETCODE_ILLEGAL_OPERATION.

    If DDS.ExclusiveAreaQosPolicy.use_shared_exclusive_area is set to DDS.BOOLEAN_FALSE, the setting which allows more concurrency among RTI Connext threads, the following are not allowed:

    • Within any listener callback, creating any entity
    • Within any listener callback, deleting any entity
    • Within any listener callback, enabling any entity
    • Within any listener callback, setting the QoS of any entities
    • Within a DDS.DataReader or DDS.Subscriber listener callback, invoking any operation on any other DDS.Subscriber or on any DDS.DataReader belonging to another DDS.Subscriber.
    • Within a DDS.DataReader or DDS.Subscriber listener callback, invoking any operation on any DDS.Publisher (or on any DDS.DataWriter belonging to such a DDS.Publisher) that has DDS.ExclusiveAreaQosPolicy.use_shared_exclusive_area set to DDS.BOOLEAN_TRUE.
    • Within a DDS.DataWriter of DDS.Publisher listener callback, invoking any operation on another Publisher or on a DDS.DataWriter belonging to another DDS.Publisher.
    • Within a DDS.DataWriter of DDS.Publisher listener callback, invoking any operation on any DDS.Subscriber or DDS.DataReader.
    An attempt to call a disallowed procedure from within a callback will result in DDS.RETCODE_ILLEGAL_OPERATION.

    The above limitations can be lifted by setting DDS.ExclusiveAreaQosPolicy.use_shared_exclusive_area to DDS.BOOLEAN_TRUE on the DDS.Publisher or DDS.Subscriber (or on the DDS.Publisher or DDS.Subscriber of the DDS.DataWriter or DDS.DataReader) to which the listener is attached. However, the application will pay the cost of reduced concurrency between the affected publishers and subscribers.

    Best Practices with Listeners

    Note that all the issues described below are avoided by using DDS.WaitSet.

    Avoid blocking or performing a lot of processing in Listener callbacks

    Listeners are invoked by internal threads that perform critical functions within the middleware and need to run in a timely manner. By default, Connext DDS creates a few threads to use to receive data and only a single thread to handle periodic events.

    Because of this, user applications installing Listeners should never block in a Listener callback. There are several negative consequences of blocking in a listener callback:

    • The application may lose data for the DataReader the listener is installed on, because the receive thread is not removing it from the socket buffer and it gets overwritten.
    • The application may receive strictly reliable data with a delay, because the receive thread is not removing it from the socket buffer and if it gets overwritten it must be re-sent.
    • The application may lose or delay data for other DataReaders, because by default all DataReaders created with the same DomainParticipant share the same threads.
    • The application may not be notified of periodic events on time

    If the application needs to make a blocking call when data is available, or when another event occurs, the application should use DDS.WaitSet.

    Avoid taking application mutexes/semaphores in Listener callbacks

    Taking application mutexes/sempahores within a Listener callback may lead to unexpected deadlock scenarios.

    When a Listener callback is invoked the EA (Exclusive Area) of the Entity 'E' to which the callback applies is taken by the middleware.

    If the application takes an application mutex 'M' within a critical section in which the application makes DDS calls affecting 'E', this may lead to following deadlock:

    The middleware thread is within the entity EA trying to acquire the mutex 'M'. At the same time, the application thread has acquired 'M' and is blocked trying to acquire the entity EA.

    Do not write data with a DataWriter within the on_data_available callback

    Avoid writing data with a DataWriter within the DDS.DataReaderListener::on_data_available() callback. If the write operation blocks because e.g. the send window is full, this will lead to a deadlock.

    Do not call wait_for_acknowledgements within the on_data_available callback

    Do not call the DDS.DataWriter.wait_for_acknowledgments within the DDS.DataReaderListener::on_data_available() callback. This will lead to deadlock.


    See also: DDSExclusiveAreaQosModule
    See also: DDSStatusTypesModule
    See also: DDS.WaitSet, DDS.Condition

  • Types

    Ref (abstract)

    type Ref is limited interface;

    Ref_Access

    type Ref_Access is access all Ref'Class;