Skip to content

Commit

Permalink
Zero-Copy documentation (#223)
Browse files Browse the repository at this point in the history
* Refs #10215: Addded zero-copy documentation

Signed-off-by: RaulSanchez <raul@eprosima.com>

* Refs #10215: Added links to the API reference

Signed-off-by: RaulSanchez <raul@eprosima.com>

* Refs #10215: Added return_loan alias

Signed-off-by: RaulSanchez <raul@eprosima.com>

* Refs #10215: apply changes before data sharing

Signed-off-by: jparisu <javierparis@eprosima.com>

* Refs #10215: Rework after data sharing

Signed-off-by: Iker Luengo <ikerluengo@eprosima.com>

* Refs #10215: move to use case

Signed-off-by: Iker Luengo <ikerluengo@eprosima.com>

* Refs #10215: review suggestions

Signed-off-by: Iker Luengo <ikerluengo@eprosima.com>

* Refs #10215: review suggestions

Signed-off-by: Iker Luengo <ikerluengo@eprosima.com>

Co-authored-by: jparisu <javierparis@eprosima.com>
Co-authored-by: Iker Luengo <ikerluengo@eprosima.com>
  • Loading branch information
3 people authored Jan 29, 2021
1 parent 647c373 commit f5d8217
Show file tree
Hide file tree
Showing 9 changed files with 407 additions and 12 deletions.
227 changes: 227 additions & 0 deletions code/DDSCodeTester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4081,3 +4081,230 @@ void dds_persistence_examples()
DataReader* reader = subscriber->create_datareader(topic, drqos);
//!--
}

class LoanableHelloWorldPubSubType : public eprosima::fastdds::dds::TopicDataType
{
public:

LoanableHelloWorldPubSubType()
: TopicDataType()
{
setName("LoanableHelloWorld");
}

bool serialize(
void* /*data*/,
eprosima::fastrtps::rtps::SerializedPayload_t* /*payload*/) override
{
return true;
}

bool deserialize(
eprosima::fastrtps::rtps::SerializedPayload_t* /*payload*/,
void* /*data*/) override
{
return true;
}

std::function<uint32_t()> getSerializedSizeProvider(
void* /*data*/) override
{
return std::function<uint32_t()>();
}

void* createData() override
{
return nullptr;
}

void deleteData(
void* /*data*/) override
{
}

bool getKey(
void* /*data*/,
eprosima::fastrtps::rtps::InstanceHandle_t* /*ihandle*/,
bool /*force_md5*/) override
{
return true;
}

MD5 m_md5;
unsigned char* m_keyBuffer;
};

class LoanableHelloWorld
{
public:

LoanableHelloWorld()
{
m_index = 0;
memset(&m_message, 0, (256) * 1);
}

uint32_t& index()
{
return m_index;
}

uint32_t index() const
{
return m_index;
}

const std::array<char, 256>& message() const
{
return m_message;
}

std::array<char, 256>& message()
{
return m_message;
}

private:

uint32_t m_index;
std::array<char, 256> m_message;
};

void dds_zero_copy_example()
{
{
//LOANABLE_HELLOWORLD_EXAMPLE_WRITER
// CREATE THE PARTICIPANT
DomainParticipantQos pqos;
pqos.name("Participant_pub");
DomainParticipant* participant = DomainParticipantFactory::get_instance()->create_participant(0, pqos);

// REGISTER THE TYPE
TypeSupport type(new LoanableHelloWorldPubSubType());
type.register_type(participant);

// CREATE THE PUBLISHER
Publisher* publisher = participant->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr);

// CREATE THE TOPIC
Topic* topic = participant->create_topic(
"LoanableHelloWorldTopic",
type.get_type_name(),
TOPIC_QOS_DEFAULT);

// CREATE THE WRITER
DataWriterQos wqos = publisher->get_default_datawriter_qos();
wqos.history().depth = 10;
wqos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS;
// DataSharingQosPolicy has to be set to AUTO (the default) or ON to enable Zero-Copy
wqos.data_sharing().on("shared_directory");

DataWriter* writer = publisher->create_datawriter(topic, wqos);

std::cout << "LoanableHelloWorld DataWriter created." << std::endl;

int msgsent = 0;
void* sample = nullptr;
// Always call loan_sample() before writing a new sample.
// This function will provide the user with a pointer to an internal buffer where the data type can be
// prepared for sending.
if (ReturnCode_t::RETCODE_OK == writer->loan_sample(sample))
{
// Modify the sample data
LoanableHelloWorld* data = static_cast<LoanableHelloWorld*>(sample);
data->index() = msgsent + 1;
memcpy(data->message().data(), "LoanableHelloWorld ", 20);

std::cout << "Sending sample (count=" << msgsent
<< ") at address " << &data << std::endl
<< " index=" << data->index() << std::endl
<< " message=" << data->message().data() << std::endl;

// Write the sample.
// After this function returns, the middleware owns the sample.
writer->write(sample);
}
//!--
}
{
class SubListener : public eprosima::fastdds::dds::DataReaderListener
{
public:

SubListener() = default;

~SubListener() override = default;

//LOANABLE_HELLOWORLD_EXAMPLE_LISTENER_READER
void on_data_available(
eprosima::fastdds::dds::DataReader* reader)
{
// Declare a LoanableSequence for a data type
FASTDDS_SEQUENCE(DataSeq, LoanableHelloWorld);

DataSeq data;
SampleInfoSeq infos;
// Access to the collection of data-samples and its corresponding collection of SampleInfo structures
while (ReturnCode_t::RETCODE_OK == reader->take(data, infos))
{
// Iterate over each LoanableCollection in the SampleInfo sequence
for (LoanableCollection::size_type i = 0; i < infos.length(); ++i)
{
// Check whether the DataSample contains data or is only used to communicate of a
// change in the instance
if (infos[i].valid_data)
{
// Print the data.
const LoanableHelloWorld& sample = data[i];

++samples;
std::cout << "Sample received (count=" << samples
<< ") at address " << &sample << std::endl
<< " index=" << sample.index() << std::endl
<< " message=" << sample.message().data() << std::endl;
}
}
// Indicate to the DataReader that the application is done accessing the collection of
// data values and SampleInfo, obtained by some earlier invocation of read or take on the
// DataReader.
reader->return_loan(data, infos);
}
}
//!--

int matched = 0;
uint32_t samples = 0;
}
datareader_listener;

//LOANABLE_HELLOWORLD_EXAMPLE_READER
// CREATE THE PARTICIPANT
DomainParticipantQos pqos;
pqos.name("Participant_sub");
DomainParticipant* participant = DomainParticipantFactory::get_instance()->create_participant(0, pqos);

// REGISTER THE TYPE
TypeSupport type(new LoanableHelloWorldPubSubType());
type.register_type(participant);

// CREATE THE SUBSCRIBER
Subscriber* subscriber = participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT, nullptr);

// CREATE THE TOPIC
Topic* topic = participant->create_topic(
"LoanableHelloWorldTopic",
type.get_type_name(),
TOPIC_QOS_DEFAULT);

// CREATE THE READER
DataReaderQos rqos = subscriber->get_default_datareader_qos();
rqos.history().depth = 10;
rqos.reliability().kind = RELIABLE_RELIABILITY_QOS;
rqos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS;
// DataSharingQosPolicy has to be set to AUTO (the default) or ON to enable Zero-Copy
rqos.data_sharing().automatic();

DataReader* reader = subscriber->create_datareader(topic, rqos, &datareader_listener);
//!--
}
}
Binary file not shown.
13 changes: 6 additions & 7 deletions docs/01-figures/fast_dds/transport/transport_comparison.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions docs/03-exports/aliases-api.include
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,11 @@
.. |DataWriter::write-api| replace:: :cpp:func:`write()<eprosima::fastdds::dds::DataWriter::write>`
.. |DataWriter::loan_sample-api| replace:: :cpp:func:`loan_sample()<eprosima::fastdds::dds::DataWriter::loan_sample>`
.. |DataWriter::discard_loan-api| replace:: :cpp:func:`discard_loan()<eprosima::fastdds::dds::DataWriter::discard_loan>`
.. |DataWriterListener-api| replace:: :cpp:class:`DataWriterListener <eprosima::fastdds::dds::DataWriterListener>`

.. |DataWriter::get_offered_deadline_missed_status-api| replace:: :cpp:func:`get_offered_deadline_missed_status()<eprosima::fastdds::dds::DataWriter::get_offered_deadline_missed_status>`
.. |DataWriter::get_offered_incompatible_qos_status-api| replace:: :cpp:func:`get_offered_incompatible_qos_status()<eprosima::fastdds::dds::DataWriter::get_offered_incompatible_qos_status>`
.. |DataWriter::get_publication_matched_status-api| replace:: :cpp:func:`get_publication_matched_status()<eprosima::fastdds::dds::DataWriter::get_publication_matched_status>`
.. |DataWriter::get_liveliness_lost_status-api| replace:: :cpp:func:`get_liveliness_lost_status()<eprosima::fastdds::dds::DataWriter::get_liveliness_lost_status>`
.. |DataWriterListener-api| replace:: :cpp:class:`DataWriterListener <eprosima::fastdds::dds::DataWriterListener>`

.. |DataWriterQos-api| replace:: :cpp:class:`DataWriterQos <eprosima::fastdds::dds::DataWriterQos>`
.. |DataWriterQos::DataWriterQos-api| replace:: :cpp:func:`DataWriterQos()<eprosima::fastdds::dds::DataWriterQos::DataWriterQos>`
Expand Down Expand Up @@ -148,6 +147,9 @@
.. |DomainParticipantQos::user_data-api| replace:: :cpp:func:`user_data()<eprosima::fastdds::dds::DomainParticipantQos::user_data>`
.. |DomainParticipantQos::wire_protocol-api| replace:: :cpp:func:`wire_protocol()<eprosima::fastdds::dds::DomainParticipantQos::wire_protocol>`
.. |DomainParticipants-api| replace:: :cpp:class:`DomainParticipants <eprosima::fastdds::dds::DomainParticipant>`

.. |LoanableSequence-api| replace:: :cpp:class:`LoanableSequence <eprosima::fastdds::dds::LoanableSequence>`

.. |Publisher-api| replace:: :cpp:class:`Publisher <eprosima::fastdds::dds::Publisher>`
.. |Publisher::create_datawriter_with_profile-api| replace:: :cpp:func:`create_datawriter_with_profile()<eprosima::fastdds::dds::Publisher::create_datawriter_with_profile>`
.. |Publisher::create_datawriter-api| replace:: :cpp:func:`create_datawriter()<eprosima::fastdds::dds::Publisher::create_datawriter>`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

.. rst-class:: api-ref

DataSharingqosPolicy
DataSharingQosPolicy
--------------------

.. doxygenclass:: eprosima::fastdds::dds::DataSharingQosPolicy
Expand Down
2 changes: 1 addition & 1 deletion docs/fastdds/transport/datasharing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ effectively avoiding any data copy between DataWriter and DataReader.

Use of Data-sharing delivery does not prevent data copies between the application
and the DataReader and DataWriter.
These can be avoided in some cases using Zero-Copy delivery.
These can be avoided in some cases using :ref:`use-case-zero-copy`.

.. note::
Although Data-sharing delivery uses shared memory,
Expand Down
2 changes: 1 addition & 1 deletion docs/fastdds/transport/transport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ The figure below shows a comparison between the different transports available i
/fastdds/transport/udp/udp.rst
/fastdds/transport/tcp/tcp.rst
/fastdds/transport/shared_memory/shared_memory.rst
/fastdds/transport/intraprocess.rst
/fastdds/transport/datasharing.rst
/fastdds/transport/intraprocess.rst
/fastdds/transport/tcp/tls.rst
/fastdds/transport/listening_locators.rst
/fastdds/transport/whitelist.rst
Expand Down
5 changes: 5 additions & 0 deletions docs/fastdds/use_cases/use_cases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ with distributed systems:
For use cases with memory consumption constraints, *Fast DDS* can be configured to reduce memory footprint
to a minimum by adjusting different QoS policies.

+ :ref:`use-case-zero-copy`.
Under certain constraints, *Fast DDS* can provide application level communication
between publishing and subscribing nodes avoiding any data copy during the process.

+ :ref:`ros2`.
Since *Fast DDS* is the default middleware implementation in the `OSRF`_ `Robot Operation System 2 (ROS 2)`_,
this documentation includes a whole independent section to show the use of the library in ROS 2,
Expand All @@ -73,3 +77,4 @@ with distributed systems:
/fastdds/use_cases/many_subscribers/many_subscribers.rst
/fastdds/use_cases/realtime/realtime.rst
/fastdds/use_cases/reduce_memory/reduce_memory.rst
/fastdds/use_cases/zero_copy/zero_copy.rst
Loading

0 comments on commit f5d8217

Please sign in to comment.