Skip to content
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

[#210] Make C sample movable #358

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions iceoryx2-ffi/cxx/include/iox2/publisher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,12 @@ template <ServiceType S, typename Payload, typename UserHeader>
inline auto Publisher<S, Payload, UserHeader>::loan_uninit()
-> iox::expected<SampleMut<S, Payload, UserHeader>, PublisherLoanError> {
auto* ref_handle = iox2_cast_publisher_ref_h(m_handle);
iox2_sample_mut_h sample_handle {};
SampleMut<S, Payload, UserHeader> sample;

auto result = iox2_publisher_loan(ref_handle, nullptr, &sample_handle);
auto result = iox2_publisher_loan(ref_handle, &sample.m_sample, &sample.m_handle);

if (result == IOX2_OK) {
return iox::ok(SampleMut<S, Payload, UserHeader>(sample_handle));
return iox::ok(std::move(sample));
}

return iox::err(iox::into<PublisherLoanError>(result));
Expand Down
20 changes: 13 additions & 7 deletions iceoryx2-ffi/cxx/include/iox2/sample.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace iox2 {
///
/// DO NOT MOVE THE SAMPLE INTO ANOTHER THREAD!
template <ServiceType, typename Payload, typename UserHeader>
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init) 'm_sample' is not used directly but only via the initialized 'm_handle'; furthermore, it will be initialized on the call site
class Sample {
public:
Sample(Sample&& rhs) noexcept;
Expand Down Expand Up @@ -64,17 +65,14 @@ class Sample {
template <ServiceType, typename, typename>
friend class Subscriber;

explicit Sample(iox2_sample_h handle);
// The sample is defaulted since both members are initialized in Subscriber::receive
explicit Sample() = default;
void drop();

iox2_sample_t m_sample;
iox2_sample_h m_handle { nullptr };
};

template <ServiceType S, typename Payload, typename UserHeader>
inline Sample<S, Payload, UserHeader>::Sample(iox2_sample_h handle)
: m_handle { handle } {
}

template <ServiceType S, typename Payload, typename UserHeader>
inline void Sample<S, Payload, UserHeader>::drop() {
if (m_handle != nullptr) {
Expand All @@ -83,16 +81,24 @@ inline void Sample<S, Payload, UserHeader>::drop() {
}
}

// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init) m_sample will be initialized in the move assignment operator
template <ServiceType S, typename Payload, typename UserHeader>
inline Sample<S, Payload, UserHeader>::Sample(Sample&& rhs) noexcept {
*this = std::move(rhs);
}

namespace internal {
extern "C" {
void iox2_sample_move(iox2_sample_t*, iox2_sample_t*, iox2_sample_h*);
}
} // namespace internal

template <ServiceType S, typename Payload, typename UserHeader>
inline auto Sample<S, Payload, UserHeader>::operator=(Sample&& rhs) noexcept -> Sample& {
if (this != &rhs) {
drop();
m_handle = std::move(rhs.m_handle);

internal::iox2_sample_move(&rhs.m_sample, &m_sample, &m_handle);
rhs.m_handle = nullptr;
}

Expand Down
21 changes: 14 additions & 7 deletions iceoryx2-ffi/cxx/include/iox2/sample_mut.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace iox2 {
///
/// DO NOT MOVE THE SAMPLE INTO ANOTHER THREAD!
template <ServiceType S, typename Payload, typename UserHeader>
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init) 'm_sample' is not used directly but only via the initialized 'm_handle'; furthermore, it will be initialized on the call site
class SampleMut {
public:
SampleMut(SampleMut&& rhs) noexcept;
Expand Down Expand Up @@ -100,17 +101,15 @@ class SampleMut {
template <ServiceType ST, typename PayloadT, typename UserHeaderT>
friend auto send_sample(SampleMut<ST, PayloadT, UserHeaderT>&& sample) -> iox::expected<size_t, PublisherSendError>;

explicit SampleMut(iox2_sample_mut_h handle);
// The sample is defaulted since both members are initialized in Subscriber::receive
explicit SampleMut() = default;
void drop();

// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init) will not be accessed directly but only via m_handle and will be set together with m_handle
iox2_sample_mut_t m_sample;
iox2_sample_mut_h m_handle { nullptr };
};

template <ServiceType S, typename Payload, typename UserHeader>
inline SampleMut<S, Payload, UserHeader>::SampleMut(iox2_sample_mut_h handle)
: m_handle { handle } {
}

template <ServiceType S, typename Payload, typename UserHeader>
inline void SampleMut<S, Payload, UserHeader>::drop() {
if (m_handle != nullptr) {
Expand All @@ -119,16 +118,24 @@ inline void SampleMut<S, Payload, UserHeader>::drop() {
}
}

// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init) m_sample will be initialized in the move assignment operator
template <ServiceType S, typename Payload, typename UserHeader>
inline SampleMut<S, Payload, UserHeader>::SampleMut(SampleMut&& rhs) noexcept {
*this = std::move(rhs);
}

namespace internal {
extern "C" {
void iox2_sample_mut_move(iox2_sample_mut_t*, iox2_sample_mut_t*, iox2_sample_mut_h*);
}
} // namespace internal

template <ServiceType S, typename Payload, typename UserHeader>
inline auto SampleMut<S, Payload, UserHeader>::operator=(SampleMut&& rhs) noexcept -> SampleMut& {
if (this != &rhs) {
drop();
m_handle = std::move(rhs.m_handle);

internal::iox2_sample_mut_move(&rhs.m_sample, &m_sample, &m_handle);
rhs.m_handle = nullptr;
}

Expand Down
9 changes: 5 additions & 4 deletions iceoryx2-ffi/cxx/include/iox2/subscriber.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,14 @@ template <ServiceType S, typename Payload, typename UserHeader>
inline auto Subscriber<S, Payload, UserHeader>::receive() const
-> iox::expected<iox::optional<Sample<S, Payload, UserHeader>>, SubscriberReceiveError> {
auto* ref_handle = iox2_cast_subscriber_ref_h(m_handle);

Sample<S, Payload, UserHeader> sample;
iox2_sample_h sample_handle {};
auto result = iox2_subscriber_receive(ref_handle, nullptr, &sample_handle);
auto result = iox2_subscriber_receive(ref_handle, &sample.m_sample, &sample.m_handle);

if (result == IOX2_OK) {
if (sample_handle != nullptr) {
return iox::ok(
iox::optional<Sample<S, Payload, UserHeader>>(Sample<S, Payload, UserHeader>(sample_handle)));
if (sample.m_handle != nullptr) {
return iox::ok(iox::optional<Sample<S, Payload, UserHeader>>(std::move(sample)));
}
return iox::ok(iox::optional<Sample<S, Payload, UserHeader>>(iox::nullopt));
}
Expand Down
34 changes: 34 additions & 0 deletions iceoryx2-ffi/ffi/src/api/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,40 @@ pub unsafe extern "C" fn iox2_cast_sample_ref_h(handle: iox2_sample_h) -> iox2_s
(*handle.as_type()).as_ref_handle() as *mut _ as _
}

/// cbindgen:ignore
/// Internal API - do not use
/// # Safety
///
/// * `source_struct_ptr` must not be `null` and the struct it is pointing to must be initialized and valid, i.e. not moved or dropped.
/// * `dest_struct_ptr` must not be `null` and the struct it is pointing to must not contain valid data, i.e. initialized. It can be moved or dropped, though.
/// * `dest_handle_ptr` must not be `null`
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn iox2_sample_move(
source_struct_ptr: *mut iox2_sample_t,
dest_struct_ptr: *mut iox2_sample_t,
dest_handle_ptr: *mut iox2_sample_h,
) {
debug_assert!(!source_struct_ptr.is_null());
debug_assert!(!dest_struct_ptr.is_null());
debug_assert!(!dest_handle_ptr.is_null());

let source = &mut *source_struct_ptr;
let dest = &mut *dest_struct_ptr;

dest.service_type = source.service_type;
dest.value.init(
source
.value
.as_option_mut()
.take()
.expect("Source must have a valid sample"),
);
dest.deleter = source.deleter;

*dest_handle_ptr = (*dest_struct_ptr).as_handle();
}

/// Acquires the samples header.
///
/// # Safety
Expand Down
34 changes: 34 additions & 0 deletions iceoryx2-ffi/ffi/src/api/sample_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,40 @@ pub unsafe extern "C" fn iox2_cast_sample_mut_ref_h(
(*handle.as_type()).as_ref_handle() as *mut _ as _
}

/// cbindgen:ignore
/// Internal API - do not use
/// # Safety
///
/// * `source_struct_ptr` must not be `null` and the struct it is pointing to must be initialized and valid, i.e. not moved or dropped.
/// * `dest_struct_ptr` must not be `null` and the struct it is pointing to must not contain valid data, i.e. initialized. It can be moved or dropped, though.
/// * `dest_handle_ptr` must not be `null`
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn iox2_sample_mut_move(
source_struct_ptr: *mut iox2_sample_mut_t,
dest_struct_ptr: *mut iox2_sample_mut_t,
dest_handle_ptr: *mut iox2_sample_mut_h,
) {
debug_assert!(!source_struct_ptr.is_null());
debug_assert!(!dest_struct_ptr.is_null());
debug_assert!(!dest_handle_ptr.is_null());

let source = &mut *source_struct_ptr;
let dest = &mut *dest_struct_ptr;

dest.service_type = source.service_type;
dest.value.init(
source
.value
.as_option_mut()
.take()
.expect("Source must have a valid sample"),
);
dest.deleter = source.deleter;

*dest_handle_ptr = (*dest_struct_ptr).as_handle();
}

/// Acquires the samples user header.
///
/// # Safety
Expand Down