-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add loaned sample zero-copy API support #297
Conversation
a8fd9dc
to
348985a
Compare
I have only had a quick look for now, but there clearly is an issue if a serdata is constructed from a loan (whether or not Iceoryx), and Cyclone then needs to invoke one of the operations that accesses the serialized representation. For example, the Something like the below would do, it basically performs the serialization on-demand. It is clearly broken because: (1) there are more functions that access it, and (2) there is always the possibility of multiple threads forcing the serialization at the same time. I would address (1) by going over the code and doing the serialization wherever it is needed 🙃 and address (2) by checking whether diff --git a/rmw_cyclonedds_cpp/src/serdata.cpp b/rmw_cyclonedds_cpp/src/serdata.cpp
index 496da75a..a5c7a84e 100644
--- a/rmw_cyclonedds_cpp/src/serdata.cpp
+++ b/rmw_cyclonedds_cpp/src/serdata.cpp
@@ -181,15 +181,11 @@ static struct ddsi_serdata * serdata_rmw_from_keyhash(
return new serdata_rmw(type, SDK_KEY);
}
-static struct ddsi_serdata * serdata_rmw_from_sample(
- const struct ddsi_sertype * typecmn,
- enum ddsi_serdata_kind kind,
- const void * sample)
+static void serdata_rmw_serialize_into(serdata_rmw *d, const void *sample)
{
+ const struct sertype_rmw * type = static_cast<const struct sertype_rmw *>(d->type);
try {
- const struct sertype_rmw * type = static_cast<const struct sertype_rmw *>(typecmn);
- auto d = std::make_unique<serdata_rmw>(type, kind);
- if (kind != SDK_DATA) {
+ if (d->kind != SDK_DATA) {
/* ROS 2 doesn't do keys, so SDK_KEY is trivial */
} else if (!type->is_request_header) {
size_t sz = type->cdr_writer->get_serialized_size(sample);
@@ -204,8 +200,21 @@ static struct ddsi_serdata * serdata_rmw_from_sample(
d->resize(sz);
type->cdr_writer->serialize(d->data(), wrap);
}
- return d.release();
+ } catch (std::exception & e) {
+ RMW_SET_ERROR_MSG(e.what());
+ }
+}
+static struct ddsi_serdata * serdata_rmw_from_sample(
+ const struct ddsi_sertype * typecmn,
+ enum ddsi_serdata_kind kind,
+ const void * sample)
+{
+ try {
+ const struct sertype_rmw * type = static_cast<const struct sertype_rmw *>(typecmn);
+ auto d = std::make_unique<serdata_rmw>(type, kind);
+ serdata_rmw_serialize_into(d.get(), sample);
+ return d.release();
} catch (std::exception & e) {
RMW_SET_ERROR_MSG(e.what());
return nullptr;
@@ -214,7 +223,7 @@ static struct ddsi_serdata * serdata_rmw_from_sample(
static struct ddsi_serdata * serdata_rmw_from_iox(
const struct ddsi_sertype * typecmn,
- enum ddsi_serdata_kind kind, iox_sub_t * sub, void * iox_buffer)
+ enum ddsi_serdata_kind kind, void * sub, void * iox_buffer)
{
static_cast<void>(sub); // unused
const struct sertype_rmw * type = static_cast<const struct sertype_rmw *>(typecmn);
@@ -252,6 +261,10 @@ static struct ddsi_serdata * serdata_rmw_to_untyped(const struct ddsi_serdata *
static void serdata_rmw_to_ser(const struct ddsi_serdata * dcmn, size_t off, size_t sz, void * buf)
{
auto d = static_cast<const serdata_rmw *>(dcmn);
+ if (d->iox_chunk && d->data() == nullptr) {
+ // FIXME: this needs to protected so it doesn't happen multiple times
+ serdata_rmw_serialize_into(const_cast<serdata_rmw *>(d), SHIFT_PAST_ICEORYX_HEADER(d->iox_chunk));
+ }
memcpy(buf, byte_offset(d->data(), off), sz);
}
@@ -260,6 +273,10 @@ static struct ddsi_serdata * serdata_rmw_to_ser_ref(
size_t sz, ddsrt_iovec_t * ref)
{
auto d = static_cast<const serdata_rmw *>(dcmn);
+ if (d->iox_chunk && d->data() == nullptr) {
+ // FIXME: this needs to protected so it doesn't happen multiple times
+ serdata_rmw_serialize_into(const_cast<serdata_rmw *>(d), SHIFT_PAST_ICEORYX_HEADER(d->iox_chunk));
+ }
ref->iov_base = byte_offset(d->data(), off);
ref->iov_len = (ddsrt_iov_len_t) sz;
return ddsi_serdata_ref(d); |
Signed-off-by: Sumanth Nirmal <[email protected]>
…ssage Signed-off-by: Sumanth Nirmal <[email protected]>
Signed-off-by: Sumanth Nirmal <[email protected]>
Signed-off-by: Sumanth Nirmal <[email protected]>
Signed-off-by: Sumanth Nirmal <[email protected]>
Signed-off-by: Sumanth Nirmal <[email protected]>
Signed-off-by: Sumanth Nirmal <[email protected]>
Signed-off-by: Sumanth Nirmal <[email protected]>
Signed-off-by: Sumanth Nirmal <[email protected]>
- Remove storing of the iox_chunk in rmw and update it directly in ddsi_serdata - Use write_cdr/take_cdr with zero-copy path Signed-off-by: Sumanth Nirmal <[email protected]>
Signed-off-by: Sumanth Nirmal <[email protected]>
Signed-off-by: Sumanth Nirmal <[email protected]>
…eware Signed-off-by: Sumanth Nirmal <[email protected]>
1467a42
to
fe08c61
Compare
Signed-off-by: Sumanth Nirmal <[email protected]>
fe08c61
to
9dd7f2b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't say I love the #ifdef
jungle, but we can fix that up later.
I've got one comment inline about reducing code duplication, but that can be follow-up work.
I'm going to approve this, but the following needs to happen to merge:
- CI needs to come back green.
- Open an issue to fix up the follow-up items: removing the
ifdef
jungle, and reducing code duplication. - We need to figure out what the situation is with the branches on cyclonedds (that is, whether we should be building this against the
master
branch of cyclonedds or theiceoryx
branch. If we are doing the latter, we also need an update to https://github.com/ros2/ros2/blob/master/ros2.repos to change branches). - I'd really prefer if @eboasson gives his approval on this.
const rosidl_message_type_support_t * ts = get_message_typesupport_handle( | ||
type_supports, rosidl_typesupport_introspection_cpp::typesupport_identifier); | ||
if (ts != nullptr) { | ||
auto members = | ||
static_cast<const rosidl_typesupport_introspection_cpp::MessageMembers *>(ts->data); | ||
return members->size_of_; | ||
} else { | ||
// handle C Typesupport | ||
const rosidl_message_type_support_t * ts_c = get_message_typesupport_handle( | ||
type_supports, rosidl_typesupport_introspection_c__identifier); | ||
if (ts_c != nullptr) { | ||
auto members = | ||
static_cast<const rosidl_typesupport_introspection_c__MessageMembers *>(ts_c->data); | ||
return members->size_of_; | ||
} else { | ||
throw std::runtime_error("get_message_size, unsupported typesupport"); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pattern of:
ts = get_typesupport(C++);
if (ts != nullptr) {
do_c++_thing;
} else {
ts = get_typesupport(C);
do_C_thing;
}
Is really common in the codebase. It would be really nice to come up with a common method for this (maybe that takes a std::function
to "do-the-thing"?).
@sumanth-nirmal It looks like we are getting segfaults in some tests on aarch64. Can you take a look? |
…urn RMW_RET_UNSUPPORTED Signed-off-by: Sumanth Nirmal <[email protected]>
@clalancette I pushed the changes, can we start a new CI pipeline? |
Signed-off-by: Sumanth Nirmal <[email protected]>
@clalancette I am in agreement with your review notes. It is not polished yet, but it works and any shortcomings can be dealt with in the coming days. So it has my approval (pending the same items that you listed).
It is meant to be used with cyclonedds' |
All right, all is green. Going ahead and merging this one and ros2/ros2#1126 |
* Add an API to determine if a type is self contained Add helper functions for getting message size and for ini, fini of message Add additional serdata_ops conditionally when SHM is enabled Update sertype initialization flags with msg fixed type information Update serdata_rmw to hold iceoryx chunk pointer Update to_sample and from_sample for zero-copy path Update Publish path for the zero-copy loaned API Update Subscription path for the zero-copy loaned API Avoid using of from_sample and to_sample in the zero-copy path Update sertype init flags with fixed type Fix the serdata_rmw_from_iox signature Update can_loan_messages only when the loaning is possible from middleware Enable loaned message APIs only if the DDS supports it Updates checks for loaning, if the loaning is not supported, then return RMW_RET_UNSUPPORTED Use extracted message typesupport for checking if a type is fixed Signed-off-by: Sumanth Nirmal <[email protected]>
* Add an API to determine if a type is self contained Add helper functions for getting message size and for ini, fini of message Add additional serdata_ops conditionally when SHM is enabled Update sertype initialization flags with msg fixed type information Update serdata_rmw to hold iceoryx chunk pointer Update to_sample and from_sample for zero-copy path Update Publish path for the zero-copy loaned API Update Subscription path for the zero-copy loaned API Avoid using of from_sample and to_sample in the zero-copy path Update sertype init flags with fixed type Fix the serdata_rmw_from_iox signature Update can_loan_messages only when the loaning is possible from middleware Enable loaned message APIs only if the DDS supports it Updates checks for loaning, if the loaning is not supported, then return RMW_RET_UNSUPPORTED Use extracted message typesupport for checking if a type is fixed Signed-off-by: Sumanth Nirmal <[email protected]>
This PR adds support for the zero-copy API.