44.2 Loaning and Returning Data and SampleInfo Sequences

44.2.1 C, Traditional C++, Java and .NET

The read() and take() operations (and their variations) return information to your application in two sequences:

  • Received DDS data samples in a sequence of the data type
  • Corresponding information about each DDS sample in a SampleInfo sequence

These sequences are parameters that are passed by your code into the read() and take() operations. If you use empty sequences (sequences that are initialized but have a maximum length of 0), Connext will fill those sequences with memory directly loaned from the receive queue itself. There is no copying of the data or of SampleInfo when the contents of the sequences are loaned. This is certainly the most efficient way for your code to retrieve the data.

However when you do so, your code must return the loaned sequences back to Connext so that they can be reused by the receive queue. If your code does not return the loan by calling the FooDataReader’s return_loan() method, then Connext will eventually run out of memory to store DDS data samples received from the network for that DataReader. See Figure 44.1: Using Loaned Sequences in read() and take() for an example of borrowing and returning loaned sequences.

DDS_ReturnCode_t return_loan(
    FooSeq &received_data, DDS_SampleInfoSeq &info_seq);

Figure 44.1: Using Loaned Sequences in read() and take()

// In C++ and Java, sequences are automatically initialized
// to be empty
FooSeq data_seq;
DDS_SampleInfoSeq info_seq;
DDS_ReturnCode_t retcode;
...
// with empty sequences, a take() or read() will return loaned
// sequence elements
retcode = Foo_reader->take(data_seq, info_seq,
	DDS_LENGTH_UNLIMITED, DDS_ANY_SAMPLE_STATE,
	DDS_ANY_VIEW_STATE, DDS_ANY_INSTANCE_STATE);
	... // process the returned data
// must return the loaned sequences when done processing
Foo_reader->return_loan(data_seq, info_seq);
...

For the C API, you must use the FooSeq_initialize() and DDS_SampleInfoSeq_initialize() operations or the macro DDS_SEQUENCE_INITIALIZER to initialize the FooSeq and DDS_SampleInfoSeq to be empty. For example, DDS_SampleInfoSeq infoSeq; DDS_SampleInfoSeq_initialize(&infoSeq); or FooSeq fooSeq = DDS_SEQUENCE_INITIALIZER;

If your code provides its own sequences to the read/take operations, then Connext will copy the data from the receive queue. In that case, you do not have to call return_loan() when you are finished with the data. However, you must make sure the following is true, or the read/take operation will fail with a return code of DDS_RETCODE_PRECONDITION_NOT_MET:

  • The received_data of type FooSeq and info_seq of type DDS_SampleInfoSeq passed in as parameters have the same maximum size (length).
  • The maximum size (length) of the sequences are less than or equal to the passed in parameter, max_samples.

44.2.2 Modern C++

The read() and take() operations (and their variations) return LoanedSamples, an iterable collection of loaned, read-only samples each containing the actual data and meta-information about the sample. A LoanedSamples collection automatically returns the loan to the middleware in its destructor. You can also explicitly call LoanedSamples::return_loan().

Figure 44.2: Using LoanedSamples to read data

dds::sub::LoanedSamples<Foo> samples = reader.take();
for (auto sample : samples) { // process the data
    if (sample.info().valid()) {
        std::cout << sample.data() << std::endl;
    }
}