diff --git a/examples/c/domains/src/publisher.c b/examples/c/domains/src/publisher.c index d0e164454..0ffefc71c 100644 --- a/examples/c/domains/src/publisher.c +++ b/examples/c/domains/src/publisher.c @@ -99,7 +99,7 @@ int main(int argc, char** argv) { // loan sample iox2_sample_mut_h sample = NULL; - if (iox2_publisher_loan(&publisher, NULL, &sample) != IOX2_OK) { + if (iox2_publisher_loan_slice_uninit(&publisher, NULL, &sample, 1) != IOX2_OK) { printf("Failed to loan sample\n"); goto drop_publisher; } diff --git a/examples/c/publish_subscribe/src/publisher.c b/examples/c/publish_subscribe/src/publisher.c index e3282b2bd..ead151e30 100644 --- a/examples/c/publish_subscribe/src/publisher.c +++ b/examples/c/publish_subscribe/src/publisher.c @@ -79,7 +79,7 @@ int main(void) { // loan sample iox2_sample_mut_h sample = NULL; - if (iox2_publisher_loan(&publisher, NULL, &sample) != IOX2_OK) { + if (iox2_publisher_loan_slice_uninit(&publisher, NULL, &sample, 1) != IOX2_OK) { printf("Failed to loan sample\n"); goto drop_publisher; } diff --git a/examples/c/publish_subscribe_with_user_header/src/publisher.c b/examples/c/publish_subscribe_with_user_header/src/publisher.c index 3e13075c8..b5b7d9103 100644 --- a/examples/c/publish_subscribe_with_user_header/src/publisher.c +++ b/examples/c/publish_subscribe_with_user_header/src/publisher.c @@ -92,7 +92,7 @@ int main(void) { // loan sample iox2_sample_mut_h sample = NULL; - if (iox2_publisher_loan(&publisher, NULL, &sample) != IOX2_OK) { + if (iox2_publisher_loan_slice_uninit(&publisher, NULL, &sample, 1) != IOX2_OK) { printf("Failed to loan sample\n"); goto drop_publisher; } diff --git a/examples/cxx/publish_subscribe_dynamic_data/src/publisher.cpp b/examples/cxx/publish_subscribe_dynamic_data/src/publisher.cpp index bae023812..7a59db602 100644 --- a/examples/cxx/publish_subscribe_dynamic_data/src/publisher.cpp +++ b/examples/cxx/publish_subscribe_dynamic_data/src/publisher.cpp @@ -38,19 +38,19 @@ auto main() -> int { .create() .expect("successful publisher creation"); - auto counter = 1; + auto counter = 0; while (node.wait(CYCLE_TIME).has_value()) { - counter += 1; - - auto required_memory_size = (8 + counter) % 16; // NOLINT + auto required_memory_size = (counter % 16) + 1; // NOLINT auto sample = publisher.loan_slice_uninit(required_memory_size).expect("acquire sample"); sample.write_from_fn([&](auto byte_idx) { return (byte_idx + counter) % 255; }); // NOLINT auto initialized_sample = assume_init(std::move(sample)); send(std::move(initialized_sample)).expect("send successful"); - std::cout << "Send sample " << counter << "..." << std::endl; + std::cout << "Send sample " << counter << " with " << required_memory_size << " bytes..." << std::endl; + + counter++; } std::cout << "exit" << std::endl; diff --git a/examples/cxx/publish_subscribe_dynamic_data/src/subscriber.cpp b/examples/cxx/publish_subscribe_dynamic_data/src/subscriber.cpp index fee340f43..593d00f35 100644 --- a/examples/cxx/publish_subscribe_dynamic_data/src/subscriber.cpp +++ b/examples/cxx/publish_subscribe_dynamic_data/src/subscriber.cpp @@ -17,6 +17,7 @@ #include "iox2/service_type.hpp" #include +#include #include constexpr iox::units::Duration CYCLE_TIME = iox::units::Duration::fromSeconds(1); @@ -35,9 +36,9 @@ auto main() -> int { while (node.wait(CYCLE_TIME).has_value()) { auto sample = subscriber.receive().expect("receive succeeds"); while (sample.has_value()) { - std::cout << "received " << sample->payload().size() << " bytes: "; - for (auto byte : sample->payload()) { - std::cout << std::hex << byte << " "; + std::cout << "received " << std::dec << static_cast(sample->payload_slice().size()) << " bytes: "; + for (auto byte : sample->payload_slice()) { + std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast(byte) << " "; } std::cout << std::endl; sample = subscriber.receive().expect("receive succeeds"); diff --git a/iceoryx2-ffi/cxx/include/iox/slice.hpp b/iceoryx2-ffi/cxx/include/iox/slice.hpp index 961b9ba7d..7d903bfa1 100644 --- a/iceoryx2-ffi/cxx/include/iox/slice.hpp +++ b/iceoryx2-ffi/cxx/include/iox/slice.hpp @@ -28,18 +28,48 @@ class Slice { Slice(const T* data, uint64_t number_of_elements); + /// @brief Returns the size of the slice in bytes. + /// @return The size of the slice in bytes. auto size() const -> uint64_t; + + /// @brief Returns the number of elements in the slice. + /// @return The number of elements in the slice. auto number_of_elements() const -> uint64_t; + /// @brief Accesses the element at the specified index (const version). + /// @param[in] n The index of the element to access. + /// @return A const reference to the element at the specified index. + /// @pre The index must be less than the number of elements in the slice. auto operator[](uint64_t n) const -> const T&; + + /// @brief Accesses the element at the specified index (non-const version). + /// @param[in] n The index of the element to access. + /// @return A reference to the element at the specified index. + /// @pre The index must be less than the number of elements in the slice. auto operator[](uint64_t n) -> T&; + /// @brief Returns an iterator to the beginning of the slice. + /// @return An iterator pointing to the first element of the slice. auto begin() -> Iterator; + + /// @brief Returns a const iterator to the beginning of the slice. + /// @return A const iterator pointing to the first element of the slice. auto begin() const -> ConstIterator; + + /// @brief Returns an iterator to the end of the slice. + /// @return An iterator pointing one past the last element of the slice. auto end() -> Iterator; + + /// @brief Returns a const iterator to the end of the slice. + /// @return A const iterator pointing one past the last element of the slice. auto end() const -> ConstIterator; + /// @brief Returns a pointer to the underlying data of the slice. + /// @return A pointer to the first element of the slice. auto data() -> T*; + + /// @brief Returns a const pointer to the underlying data of the slice. + /// @return A const pointer to the first element of the slice. auto data() const -> const T*; private: diff --git a/iceoryx2-ffi/cxx/include/iox2/sample_mut_uninit.hpp b/iceoryx2-ffi/cxx/include/iox2/sample_mut_uninit.hpp index ec4020063..392743c41 100644 --- a/iceoryx2-ffi/cxx/include/iox2/sample_mut_uninit.hpp +++ b/iceoryx2-ffi/cxx/include/iox2/sample_mut_uninit.hpp @@ -173,13 +173,17 @@ template template inline void SampleMutUninit::write_from_fn( const iox::function& initializer) { - IOX_TODO(); + auto slice = payload_slice_mut(); + for (uint64_t i = 0; i < slice.number_of_elements(); ++i) { + slice[i] = initializer(i); + } } template template inline void SampleMutUninit::write_from_slice(const T& value) { - IOX_TODO(); + auto dest = payload_slice_mut(); + std::memcpy(dest.begin(), value.begin(), std::min(dest.size(), value.size()) * sizeof(typename T::ValueType)); } } // namespace iox2 diff --git a/iceoryx2-ffi/cxx/tests/src/service_publish_subscribe_tests.cpp b/iceoryx2-ffi/cxx/tests/src/service_publish_subscribe_tests.cpp index 6b1dacdb3..d0020d656 100644 --- a/iceoryx2-ffi/cxx/tests/src/service_publish_subscribe_tests.cpp +++ b/iceoryx2-ffi/cxx/tests/src/service_publish_subscribe_tests.cpp @@ -248,6 +248,105 @@ TYPED_TEST(ServicePublishSubscribeTest, slice_copy_send_receive_works) { ASSERT_THAT(iterations, Eq(SLICE_MAX_LENGTH)); } +TYPED_TEST(ServicePublishSubscribeTest, write_from_fn_send_receive_works) { + constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; + constexpr auto SLICE_MAX_LENGTH = 10; + + constexpr uint64_t DEFAULT_VALUE_A = 42; + constexpr uint64_t DEFAULT_VALUE_B = 777; + constexpr uint64_t DEFAULT_VALUE_Z = 21; + struct MyNestedStruct { + uint64_t a { DEFAULT_VALUE_A }; + uint64_t b { DEFAULT_VALUE_B }; + }; + struct MyStruct { + uint64_t z { DEFAULT_VALUE_Z }; + MyNestedStruct data; + }; + + const auto service_name = iox2_testing::generate_service_name(); + + auto node = NodeBuilder().create().expect(""); + auto service = + node.service_builder(service_name).template publish_subscribe>().create().expect(""); + + auto sut_publisher = service.publisher_builder().max_slice_len(SLICE_MAX_LENGTH).create().expect(""); + auto sut_subscriber = service.subscriber_builder().create().expect(""); + + auto send_sample = sut_publisher.loan_slice_uninit(SLICE_MAX_LENGTH).expect(""); + send_sample.write_from_fn([](auto index) { + std::cout << index << std::endl; + return MyStruct { DEFAULT_VALUE_Z + index, + MyNestedStruct { DEFAULT_VALUE_A + index, DEFAULT_VALUE_B + index } }; + }); + send(assume_init(std::move(send_sample))).expect(""); + + auto recv_result = sut_subscriber.receive().expect(""); + ASSERT_TRUE(recv_result.has_value()); + auto recv_sample = std::move(recv_result.value()); + + auto iterations = 0; + for (const auto& item : recv_sample.payload_slice()) { + ASSERT_THAT(item.z, Eq(DEFAULT_VALUE_Z + iterations)); + ASSERT_THAT(item.data.a, Eq(DEFAULT_VALUE_A + iterations)); + ASSERT_THAT(item.data.b, Eq(DEFAULT_VALUE_B + iterations)); + ++iterations; + } + + ASSERT_THAT(recv_sample.payload_slice().number_of_elements(), Eq(SLICE_MAX_LENGTH)); + ASSERT_THAT(iterations, Eq(SLICE_MAX_LENGTH)); +} + +TYPED_TEST(ServicePublishSubscribeTest, write_from_slice_send_receive_works) { + constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; + constexpr auto SLICE_MAX_LENGTH = 10; + + constexpr uint64_t DEFAULT_VALUE_A = 42; + constexpr uint64_t DEFAULT_VALUE_B = 777; + constexpr uint64_t DEFAULT_VALUE_Z = 21; + struct MyNestedStruct { + uint64_t a { DEFAULT_VALUE_A }; + uint64_t b { DEFAULT_VALUE_B }; + }; + struct MyStruct { + uint64_t z { DEFAULT_VALUE_Z }; + MyNestedStruct data; + }; + + const auto service_name = iox2_testing::generate_service_name(); + + auto node = NodeBuilder().create().expect(""); + auto service = + node.service_builder(service_name).template publish_subscribe>().create().expect(""); + + auto sut_publisher = service.publisher_builder().max_slice_len(SLICE_MAX_LENGTH).create().expect(""); + auto sut_subscriber = service.subscriber_builder().create().expect(""); + + iox::UninitializedArray elements; + for (auto& item : elements) { + new (&item) MyStruct {}; + } + auto payload = iox::Slice(elements.begin(), SLICE_MAX_LENGTH); + auto send_sample = sut_publisher.loan_slice_uninit(SLICE_MAX_LENGTH).expect(""); + send_sample.write_from_slice(payload); + send(assume_init(std::move(send_sample))).expect(""); + + auto recv_result = sut_subscriber.receive().expect(""); + ASSERT_TRUE(recv_result.has_value()); + auto recv_sample = std::move(recv_result.value()); + + auto iterations = 0; + for (const auto& item : recv_sample.payload_slice()) { + ASSERT_THAT(item.z, Eq(DEFAULT_VALUE_Z)); + ASSERT_THAT(item.data.a, Eq(DEFAULT_VALUE_A)); + ASSERT_THAT(item.data.b, Eq(DEFAULT_VALUE_B)); + ++iterations; + } + + ASSERT_THAT(recv_sample.payload_slice().number_of_elements(), Eq(SLICE_MAX_LENGTH)); + ASSERT_THAT(iterations, Eq(SLICE_MAX_LENGTH)); +} + TYPED_TEST(ServicePublishSubscribeTest, loan_slice_send_receive_works) { constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; constexpr uint64_t PAYLOAD_ALIGNMENT = 8;