Setting Up DataReaderListeners

DataReaders may optionally have Listeners. A DataReaderListener is a collection of callback methods; these methods are invoked by Connext DDS when DDS data samples are received or when there are status changes for the DataReader.

Note: Some operations cannot be used within a listener callback, see Restricted Operations in Listener Callbacks.

If you do not implement a DataReaderListener, the associated Subscriber’s Listener is used instead. If that Subscriber does not have a Listener either, then the DomainParticipant’s Listener is used if one exists (see Setting Up SubscriberListeners and Setting Up DomainParticipantListeners).

If you do not require asynchronous notification of data availability or status changes, you do not need to set a Listener for the DataReader. In that case, you will need to periodically call one of the read() or take() operations described in Using DataReaders to Access Data (Read & Take) to access the data that has been received.

Listeners are typically set up when the DataReader is created (see Creating DataReaders). You can also set one up after creation by using the DataReader’s get_listener() and set_listener() operations. Connext DDS will invoke a DataReader’s Listener to report the status changes listed in DataReaderListener Callbacks (if the Listener is set up to handle the particular status, see Setting Up DataReaderListeners).

DataReaderListener Callbacks

This DataReaderListener callback...

...is triggered by a change in this status:

on_data_available()

DATA_AVAILABLE Status

on_liveliness_changed()

LIVELINESS_CHANGED Status

on_requested_deadline_missed()

REQUESTED_DEADLINE_MISSED Status

on_requested_incompatible_qos()

REQUESTED_INCOMPATIBLE_QOS Status

on_sample_lost()

SAMPLE_LOST Status

on_sample_rejected()

SAMPLE_REJECTED Status

on_subscription_matched()

SUBSCRIPTION_MATCHED Status

Note that the same callbacks can be implemented in the SubscriberListener or DomainParticipantListener instead. There is only one SubscriberListener callback that takes precedence over a DataReaderListener’s. An on_data_on_readers() callback in the SubscriberListener (or DomainParticipantListener) takes precedence over the on_data_available() callback of a DataReaderListener.

If the SubscriberListener implements an on_data_on_readers() callback, it will be invoked instead of the DataReaderListener’s on_data_available() callback when new data arrives. The on_data_on_readers() operation can in turn cause the on_data_available() method of the appropriate DataReaderListener to be invoked by calling the Subscriber’s notify_datareaders() operation. For more information on status and Listeners, see Listeners.

Figure: Simple DataReaderListener shows a DataReaderListener that simply prints the data it receives.

Figure: Simple DataReaderListener

class MyReaderListener : public DDSDataReaderListener {
    public:
        virtual void on_data_available(DDSDataReader* reader);
    // don’t do anything for the other callbacks
};
void MyReaderListener::on_data_available(DDSDataReader* reader)
{
    FooDataReader *Foo_reader = NULL;
    FooSeq data_seq; // In C, sequences have to be initialized
    DDS_SampleInfoSeq info_seq; // before use, see The Sequence Data Structure
    DDS_ReturnCode_t retcode;
    int i;
    // Must cast generic reader into reader of specific type
    Foo_reader = FooDataReader::narrow(reader);
    if (Foo_reader == NULL) {
        printf("DataReader narrow error\n");
        return;
    }
    retcode = Foo_reader->take(data_seq, info_seq,
        DDS_LENGTH_UNLIMITED, DDS_ANY_SAMPLE_STATE,
        DDS_ANY_VIEW_STATE, DDS_ANY_INSTANCE_STATE);
    if (retcode == DDS_RETCODE_NO_DATA) {
        return;
    } else if (retcode != DDS_RETCODE_OK) {
        printf("take error %d\n", retcode);
        return;
    }
    for (i = 0; i < data_seq.length(); ++i) {
        // the data may not be valid if the DDS sample is 
        // meta information about the creation or deletion 
        // of an instance
        if (info_seq[i].valid_data) {
           FooTypeSupport::print_data(&data_seq[i]);
        }
    }
    // Connext DDS gave a pointer to internal memory via
    // take(), must return the memory when finished processing the data
    retcode = Foo_reader->return_loan(data_seq, info_seq);
    if (retcode != DDS_RETCODE_OK) {
        printf("return loan error %d\n", retcode);
    }
}

© 2018 RTI