40.4 Setting Up DataReaderListeners

DataReaders may optionally have Listeners. A DataReaderListener is a collection of callback methods; these methods are invoked by Connext 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 15.8.8.1 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 39.6 Setting Up SubscriberListeners and 16.3.6 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 41. 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 40.1 Creating DataReaders). You can also set one up after creation by using the DataReader’s get_listener() and set_listener() operations. Connext will invoke a DataReader’s Listener to report the status changes listed in Table 40.2 DataReaderListener Callbacks (if the Listener is set up to handle the particular status, see 40.4 Setting Up DataReaderListeners).

Table 40.2 DataReaderListener Callbacks

This DataReaderListener callback...

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

on_data_available()

40.7.1 DATA_AVAILABLE Status

on_liveliness_changed()

40.7.4 LIVELINESS_CHANGED Status

on_requested_deadline_missed()

40.7.5 REQUESTED_DEADLINE_MISSED Status

on_requested_incompatible_qos()

40.7.6 REQUESTED_INCOMPATIBLE_QOS Status

on_sample_lost()

40.7.7 SAMPLE_LOST Status

on_sample_rejected()

40.7.8 SAMPLE_REJECTED Status

on_subscription_matched()

40.7.9 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 15.8 Listeners.

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

Figure 40.2: 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 41.5  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);
    }
}