Accessing received data

The application can access and consume the data values received on the DataReader by taking a sample. Using the DataReader::take_next_sample reads the next, non-previously accessed data value available on the DataReader, and stores it in the provided data object.

When taking data, the returned samples are also removed from the DataReader, so they are no longer accessible.

When there is no data in the DataReader matching the required conditions, all the operations will return NO_DATA and output parameter will remain unchanged.

In addition to the data values, the data access operations also provide SampleInfo instances with additional information that help interpreting the returned data values, like the originating DataWriter or the publication time stamp. Refer to the SampleInfo section for an extensive description of its contents.

Using the TypedDataReader

Safe DDS Usage

In order to provide a type safe API, Safe DDS provides a TypedDataReader class.

TypedDataReader class is a specialization of the DataReader class, and it is obtained by calling the TypedDataReader::downcast method and its constructed using a Typesupport class that must be previously registered in the DomainParticipant with a Topic name that matches the one used to create the DataReader.

Once the TypedDataReader reference is obtained, the take_next_sample method can be used to retrieve data.

The take_next_sample function takes two arguments:

  • A reference to a typed object to be used as output argument.

  • A SampleInfo reference to be used as output argument.

Safe DDS Usage

If Safe DDS Static API is used, there is no need to use the TypedDataReader::downcast method, since the StaticDataReader is already a TypedDataReader.

Example

// Obtain a reference to a TypedDataReader
auto typedreader = TypedDataReader<CustomTypeSupport>::downcast(*datareader);

// Check if the TypedDataReader was obtained
if (nullptr == typedreader)
{
    std::cout << "Error obtaining TypedDataReader" << std::endl;
}

// Read the sample
CustomTypeSupport::DataType sample = {};
SampleInfo sample_info = {};
dds::ReturnCode ret = typedreader->take_next_sample(sample, sample_info);

// Check if the sample was read
if (dds::ReturnCode::OK == ret)
{
    std::cout << "Received sample: " << sample.index << std::endl;
}

Accessing data on callbacks

When the DataReader receives new data values from any matching DataWriter, it informs the application through two Listener callbacks:

  • DataReaderListener::on_data_available.

  • SubscriberListener::on_data_on_readers.

These callbacks can be used to retrieve the newly arrived data

Note

If several new data changes are received at once, the callbacks may be triggered just once, instead of once per change. The application must keep taking until no new changes are available.

Example

class ApplicationDataReaderListener : public DataReaderListener
{
    void on_data_available(
            DataReader& reader) noexcept override
    {
        // Obtain a reference to a TypedDataReader
        auto typedreader = TypedDataReader<CustomTypeSupport>::downcast(reader);

        // Check if the TypedDataReader was obtained
        if (nullptr == typedreader)
        {
            std::cout << "Error obtaining TypedDataReader" << std::endl;
        }

        // Read all available samples
        dds::ReturnCode ret = dds::ReturnCode::OK;
        while (dds::ReturnCode::OK == ret)
        {
            CustomTypeSupport::DataType sample = {};
            SampleInfo sample_info = {};
            ret = typedreader->take_next_sample(sample, sample_info);

            // Check if the sample was read
            if (dds::ReturnCode::OK == ret)
            {
                std::cout << "Received sample: " << sample.index << std::endl;
            }
        }
    }

};