3.3.7. Publishing data

The user informs of a change in the value of a data instance with the write() member function on the DataWriter. This change will then be communicated to every DataReader matched with the DataWriter. As a side effect, this operation asserts liveliness on the DataWriter itself, the Publisher and the DomainParticipant.

The function takes two arguments:

  • A pointer to the data instance with the new values.

  • The handler to the instance.

An empty (i.e., default constructed InstanceHandle_t) instance handler can be used for the argument handle. This indicates that the identity of the instance should be automatically deduced from the key of the instance data. Alternatively, the member function write() is overloaded to take only the pointer to the data instance, which will always deduced the identity from the key of the instance data.

If the handle is not empty, then it must correspond to the value obtained with the getKey() of the TypeSupport instance. Otherwise the write function will fail with RETCODE_PRECONDITION_NOT_MET.

// Register the data type in the DomainParticipant.
TypeSupport custom_type_support(new CustomDataType());
custom_type_support.register_type(participant, custom_type_support.get_type_name());

// Create a Topic with the registered type.
Topic* custom_topic =
        participant->create_topic("topic_name", custom_type_support.get_type_name(), TOPIC_QOS_DEFAULT);
if (nullptr == custom_topic)
{
    // Error
    return;
}

// Create a DataWriter
DataWriter* data_writer =
        publisher->create_datawriter(custom_topic, DATAWRITER_QOS_DEFAULT);
if (nullptr == data_writer)
{
    // Error
    return;
}

// Get a data instance
void* data = custom_type_support->createData();

// Fill the data values
// (...)

// Publish the new value, deduce the instance handle
if (data_writer->write(data, eprosima::fastrtps::rtps::InstanceHandle_t()) != ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}

// The data instance can be reused to publish new values,
// but delete it at the end to avoid leaks
custom_type_support->deleteData(data);

3.3.7.1. Blocking of the write operation

If the reliability kind is set to RELIABLE on the DataWriterQos, the write() operation may block. Specifically, if the limits specified in the configured resource limits have been reached, the write() operation will block waiting for space to become available. Under these circumstances, the reliability max_blocking_time configures the maximum time the write operation may block waiting. If max_blocking_time elapses before the DataWriter is able to store the modification without exceeding the limits, the write operation will fail and return TIMEOUT.

3.3.7.2. Borrowing a data buffer

When the user calls write() with a new sample value, the data is copied from the given sample to the DataWriter’s memory. For large data types this copy can consume significant time and memory resources. Instead, the DataWriter can loan a sample from its memory to the user, and the user can fill this sample with the required values. When write() is called with such a loaned sample, the DataWriter does not copy its contents, as it already owns the buffer.

To use loaned data samples in publications, perform the following steps:

  1. Get a reference to a loaned sample using loan_sample().

  2. Use the reference to build the data sample.

  3. Write the sample using write().

Once write() has been called with a loaned sample, the loan is considered returned, and it is not safe to make any changes on the contents of the sample.

If function loan_sample() is called but the sample is never written, the loan must be returned to the DataWriter using discard_loan(). Otherwise the DataWriter may run out of samples.

    // Borrow a data instance
    void* data = nullptr;
    if (ReturnCode_t::RETCODE_OK == data_writer->loan_sample(data))
    {
        bool error = false;

        // Fill the data values
        // (...)

        if (error)
        {
            // Return the loan without publishing
            data_writer->discard_loan(data);
            return;
        }

        // Publish the new value
        if (data_writer->write(data, eprosima::fastrtps::rtps::InstanceHandle_t()) != ReturnCode_t::RETCODE_OK)
        {
            // Error
            return;
        }
    }

    // The data instance can be reused to publish new values,
    // but delete it at the end to avoid leaks
    custom_type_support->deleteData(data);