diff --git a/.azure/templates/build-test.yml b/.azure/templates/build-test.yml index bb1263cf..047589a4 100644 --- a/.azure/templates/build-test.yml +++ b/.azure/templates/build-test.yml @@ -86,8 +86,8 @@ steps: mkdir iceoryx/build cd iceoryx/build cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ - -DCMAKE_BUILD_SHARED_LIBS=on \ -DCMAKE_INSTALL_PREFIX=install \ + -DBUILD_SHARED_LIBS=on \ -DROUDI_ENVIRONMENT=on \ ${GENERATOR:+-G} "${GENERATOR}" -A "${PLATFORM}" -T "${TOOLSET}" ../iceoryx_meta cmake --build . --config ${BUILD_TYPE} --target install -- ${BUILD_TOOL_OPTIONS} @@ -105,7 +105,7 @@ steps: -DCMAKE_INSTALL_PREFIX=install \ -DCMAKE_PREFIX_PATH="${BUILD_SOURCESDIRECTORY}/iceoryx/build/install" \ -DSANITIZER=${SANITIZER:-none} \ - -DENABLE_SHM=${ICEORYX:-off} \ + -DENABLE_ICEORYX=${ICEORYX:-off} \ -DENABLE_TYPELIB=${TYPELIB:-on} \ -DENABLE_TOPIC_DISCOVERY=${TOPIC_DISCOVERY:-on} \ ${GENERATOR:+-G} "${GENERATOR}" -A "${PLATFORM}" -T "${TOOLSET}" .. @@ -120,7 +120,7 @@ steps: -DCMAKE_PREFIX_PATH="${BUILD_SOURCESDIRECTORY}/cyclonedds/build/install;${BUILD_SOURCESDIRECTORY}/iceoryx/build/install;${BUILD_SOURCESDIRECTORY}/googletest/build/install" \ -DANALYZER=${ANALYZER:-off} \ -DSANITIZER=${SANITIZER:-none} \ - -DENABLE_SHM=${ICEORYX:-off} \ + -DENABLE_ICEORYX=${ICEORYX:-off} \ -DENABLE_COVERAGE=${COVERAGE:-off} \ -DENABLE_LEGACY=${LEGACY:-off} \ -DBUILD_TESTING=on \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 785bb52b..aea72fd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,6 +172,8 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") # By default building the testing tree is enabled by including CTest, but # since it is not required to build the project, switch to off by default. option(BUILD_TESTING "Build the testing tree." OFF) +option(ENABLE_ICEORYX "Enable testing PSMX with Iceoryx plugin" OFF) + # Disable building the examples by default until the Idlpp-cxx has been # deprecated. option(BUILD_EXAMPLES "Build examples." OFF) @@ -223,26 +225,6 @@ install( COMPONENT dev) find_package(CycloneDDS REQUIRED) -# Support for shared memory in Cyclone DDS C++ depends on support for shared -# memory being compiled into Cyclone DDS and iceoryx_binding_c being available -# If Cyclone DDS is compiled with support for shared memory, Cyclone DDS C++ -# must be compiled with shared memory too and vice versa. -get_target_property(cyclonedds_has_shm CycloneDDS::ddsc SHM_SUPPORT_IS_AVAILABLE) -mark_as_advanced(cyclonedds_has_shm) - -option(ENABLE_SHM "Enable shared memory support" ${cyclonedds_has_shm}) -if(ENABLE_SHM) - if(NOT cyclonedds_has_shm) - message(FATAL_ERROR "Cyclone DDS is NOT compiled with support for shared memory") - else() - find_package(iceoryx_binding_c REQUIRED) - endif() - message(STATUS "Found iceoryx_binding_c: (found version \"${iceoryx_binding_c_VERSION}\")") - set(ENABLE_SHM ON) - set(DDSCXX_HAS_SHM "1") -elseif(cyclonedds_has_shm) - message(FATAL_ERROR "Cyclone DDS is compiled with support for shared memory") -endif() get_target_property(cyclonedds_has_typelib CycloneDDS::ddsc TYPELIB_IS_AVAILABLE) mark_as_advanced(cyclonedds_has_typelib) diff --git a/PackageConfig.cmake.in b/PackageConfig.cmake.in index 54b37ed4..74e9a359 100644 --- a/PackageConfig.cmake.in +++ b/PackageConfig.cmake.in @@ -13,11 +13,6 @@ find_package(CycloneDDS REQUIRED) -if(@ENABLE_SHM@) - include(CMakeFindDependencyMacro) - find_dependency(iceoryx_binding_c) -endif() - if(@ENABLE_LEGACY@) include(CMakeFindDependencyMacro) find_dependency(Boost) diff --git a/README.md b/README.md index 3eb0dd10..86ab0720 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ There are some configuration options specified using CMake defines in addition t * `-DBUILD_TESTING=ON`: to build the testing tree * `-DBUILD_EXAMPLES=ON`: to build examples * `-DENABLE_LEGACY=YES`: to enable legacy c++11 mode, adds boost as dependency (otherwise it uses c++17) -* `-DENABLE_SHM=YES`: to enable shared memory support +* `-DENABLE_ICEORYX=YES`: to enable Iceoryx tests * `-DENABLE_TYPELIB=YES`: to enable type library support * `-DENABLE_TOPIC_DISCOVERY=YES`: to enable topic discovery support * `-DENABLE_COVERAGE=YES`: to enable coverage build diff --git a/features.hpp.in b/features.hpp.in index 9fabb50d..a95242d0 100644 --- a/features.hpp.in +++ b/features.hpp.in @@ -1,9 +1,6 @@ #ifndef __OMG_DDS_DDSCXX_FEATURES_HPP__ #define __OMG_DDS_DDSCXX_FEATURES_HPP__ -/* Whether or not support for shared memory is included */ -#cmakedefine DDSCXX_HAS_SHM @DDSCXX_HAS_SHM@ - /* Whether or not support for type discovery is included */ #cmakedefine DDSCXX_HAS_TYPELIB @DDSCXX_HAS_TYPELIB@ diff --git a/src/ddscxx/CMakeLists.txt b/src/ddscxx/CMakeLists.txt index 245b78de..65c63fe7 100644 --- a/src/ddscxx/CMakeLists.txt +++ b/src/ddscxx/CMakeLists.txt @@ -99,12 +99,6 @@ target_include_directories( $ $) -if(ENABLE_SHM) - # TODO: Ideally the C++ language binding shouldn't depend directly on - # Iceoryx, but should get it from Cyclone DDS - target_link_libraries(ddscxx PUBLIC iceoryx_binding_c::iceoryx_binding_c) -endif() - generate_export_header( ddscxx BASE_NAME OMG_DDS_API_DETAIL diff --git a/src/ddscxx/include/dds/core/policy/CorePolicy.hpp b/src/ddscxx/include/dds/core/policy/CorePolicy.hpp index b56abca3..25d1c120 100644 --- a/src/ddscxx/include/dds/core/policy/CorePolicy.hpp +++ b/src/ddscxx/include/dds/core/policy/CorePolicy.hpp @@ -145,6 +145,9 @@ typedef dds::core::policy::detail::TypeConsistencyEnforcement TypeConsistencyEnforcement; #endif //OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT +typedef dds::core::policy::detail::PSMXInstances +PSMXInstances; + typedef dds::core::policy::detail::UserData UserData; @@ -195,6 +198,7 @@ OMG_DDS_POLICY_TRAITS(DataRepresentation, 23) OMG_DDS_POLICY_TRAITS(TypeConsistencyEnforcement, 24) #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT OMG_DDS_POLICY_TRAITS(WriterBatching, 25) +OMG_DDS_POLICY_TRAITS(PSMXInstances, 34) } } diff --git a/src/ddscxx/include/dds/core/policy/TCorePolicy.hpp b/src/ddscxx/include/dds/core/policy/TCorePolicy.hpp index a2e76ddc..c1cedaee 100644 --- a/src/ddscxx/include/dds/core/policy/TCorePolicy.hpp +++ b/src/ddscxx/include/dds/core/policy/TCorePolicy.hpp @@ -1887,6 +1887,58 @@ class TTypeConsistencyEnforcement : public dds::core::Value //============================================================================== + +/** + * @brief QoSPolicy indicating which PSMX instances to use (if present). + * + * Restricts the PSMX instances used for data exchange to the ones in this QoSPolicy, if populated by the user. + * Populating this QoSPolicy with an empty list means no PSMX exchange will be used. + * Will be default constructed, but not set as populated in the default constructed DataWriter and DataReader QoSes. + * In this manner default constructed QoSes will allow all PSMX forms of exchange available to CycloneDDS. + */ +template +class TPSMXInstances : public dds::core::Value +{ +public: + + /** + * Constructs a copy of a TPSMXInstances QoS instance + * + * @param other The instance to copy. + */ + TPSMXInstances(const TPSMXInstances& other); + + /** + * Constructs an initialized TPSMXInstances QoS instance + * + * @param instances the PSMX instances to support + */ + explicit TPSMXInstances(const dds::core::StringSeq &instances = {}); + + /** + * Copies a TPSMXInstances QoS instance + * + * @param other the instance to copy + */ + TPSMXInstances& operator=(const TPSMXInstances& other) = default; + + /** + * Sets which PSMX instances are supported + * + * @param instances which instances to support + * + * @return the psmx instances QoSPolicy that was changed + */ + TPSMXInstances& instances(const dds::core::StringSeq &instances); + + /** + * Get which PSMX instances are supported. + * + * @return sequence of strings of supported PSMX instances + */ + const dds::core::StringSeq instances() const; +}; + } } } diff --git a/src/ddscxx/include/dds/core/policy/detail/CorePolicy.hpp b/src/ddscxx/include/dds/core/policy/detail/CorePolicy.hpp index bba70300..00ab811c 100644 --- a/src/ddscxx/include/dds/core/policy/detail/CorePolicy.hpp +++ b/src/ddscxx/include/dds/core/policy/detail/CorePolicy.hpp @@ -98,6 +98,9 @@ namespace dds { namespace core { namespace policy { namespace detail { TypeConsistencyEnforcement; #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + typedef dds::core::policy::TPSMXInstances + PSMXInstances; + typedef dds::core::policy::TUserData UserData; diff --git a/src/ddscxx/include/dds/core/policy/detail/TCorePolicyImpl.hpp b/src/ddscxx/include/dds/core/policy/detail/TCorePolicyImpl.hpp index 32d25dc8..12c6ef72 100644 --- a/src/ddscxx/include/dds/core/policy/detail/TCorePolicyImpl.hpp +++ b/src/ddscxx/include/dds/core/policy/detail/TCorePolicyImpl.hpp @@ -1151,6 +1151,29 @@ bool TTypeConsistencyEnforcement::force_type_validation() const #endif // defined(OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT) +template +TPSMXInstances::TPSMXInstances(const TPSMXInstances& other): dds::core::Value(other) +{ +} + +template +TPSMXInstances::TPSMXInstances(const dds::core::StringSeq &instances): dds::core::Value(instances) +{ +} + +template +TPSMXInstances& TPSMXInstances::instances(const dds::core::StringSeq &instances) +{ + this->delegate().instances(instances); + return *this; +} + +template +const dds::core::StringSeq TPSMXInstances::instances() const +{ + return this->delegate().instances(); +} + } } } diff --git a/src/ddscxx/include/dds/sub/detail/SamplesHolder.hpp b/src/ddscxx/include/dds/sub/detail/SamplesHolder.hpp index 212ba67b..83b265d4 100644 --- a/src/ddscxx/include/dds/sub/detail/SamplesHolder.hpp +++ b/src/ddscxx/include/dds/sub/detail/SamplesHolder.hpp @@ -104,53 +104,13 @@ class CDRSamplesHolder : public SamplesHolder org::eclipse::cyclonedds::topic::CDRBlob & cdr_blob) const { // update the CDR header - memcpy(cdr_blob.encoding().data(), buffer, CDR_HEADER_SIZE); + memcpy(cdr_blob.encoding().data(), buffer, DDSI_RTPS_HEADER_SIZE); // if the data kind is not empty if (data_kind != org::eclipse::cyclonedds::topic::BlobKind::Empty) { // get the actual data from the buffer - cdr_blob.payload().assign(buffer + CDR_HEADER_SIZE, buffer + size); + cdr_blob.payload().assign(buffer + DDSI_RTPS_HEADER_SIZE, buffer + size); } } - - bool update_cdrblob_from_iox_chunk (ddsi_serdata & current_blob, - org::eclipse::cyclonedds::topic::CDRBlob &sample_data) { -#ifdef DDSCXX_HAS_SHM - // if the data is available on SHM - if (current_blob.iox_chunk && current_blob.iox_subscriber) { - // get the user iox header - auto iox_header = iceoryx_header_from_chunk(current_blob.iox_chunk); - // if the iox chunk has the data in serialized form - if (iox_header->shm_data_state == IOX_CHUNK_CONTAINS_SERIALIZED_DATA) { - copy_buffer_to_cdr_blob(reinterpret_cast(current_blob.iox_chunk), - iox_header->data_size, sample_data.kind(), sample_data); - } else if (iox_header->shm_data_state == IOX_CHUNK_CONTAINS_RAW_DATA) { - // serialize the data - auto serialized_size = ddsi_sertype_get_serialized_size(current_blob.type, - current_blob.iox_chunk); - // create a buffer to serialize - std::vector buffer(serialized_size); - // serialize into the buffer - ddsi_sertype_serialize_into(current_blob.type, current_blob.iox_chunk, buffer.data(), - serialized_size); - // update the CDR blob with the serialized data - copy_buffer_to_cdr_blob(buffer.data(), serialized_size, sample_data.kind(), sample_data); - } else { - // this shouldn't never happen - ISOCPP_THROW_EXCEPTION(ISOCPP_PRECONDITION_NOT_MET_ERROR, - "The received sample over SHM is not initialized"); - } - // release the chunk - free_iox_chunk(static_cast(current_blob.iox_subscriber), ¤t_blob.iox_chunk); - return true; - } else { - return false; - } -#else - (void) current_blob; - (void) sample_data; - return false; -#endif // DDSCXX_HAS_SHM - } }; template diff --git a/src/ddscxx/include/org/eclipse/cyclonedds/core/cdr/extended_cdr_v2_ser.hpp b/src/ddscxx/include/org/eclipse/cyclonedds/core/cdr/extended_cdr_v2_ser.hpp index 6c0e95b3..56f4f3b8 100644 --- a/src/ddscxx/include/org/eclipse/cyclonedds/core/cdr/extended_cdr_v2_ser.hpp +++ b/src/ddscxx/include/org/eclipse/cyclonedds/core/cdr/extended_cdr_v2_ser.hpp @@ -407,4 +407,5 @@ bool max(xcdr_v2_stream& str, const T& max_sz, size_t N = 1) { } } } /* namespace org / eclipse / cyclonedds / core / cdr */ -#endif \ No newline at end of file +#endif + diff --git a/src/ddscxx/include/org/eclipse/cyclonedds/core/policy/PolicyDelegate.hpp b/src/ddscxx/include/org/eclipse/cyclonedds/core/policy/PolicyDelegate.hpp index 657ed967..f65532be 100644 --- a/src/ddscxx/include/org/eclipse/cyclonedds/core/policy/PolicyDelegate.hpp +++ b/src/ddscxx/include/org/eclipse/cyclonedds/core/policy/PolicyDelegate.hpp @@ -991,6 +991,25 @@ class OMG_DDS_API TypeConsistencyEnforcementDelegate { #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT +class OMG_DDS_API PSMXInstancesDelegate { +public: + PSMXInstancesDelegate(const PSMXInstancesDelegate& other); + explicit PSMXInstancesDelegate(const dds::core::StringSeq &instances); + PSMXInstancesDelegate& operator=(const PSMXInstancesDelegate& other) = default; + + void instances(const dds::core::StringSeq &instances); + const dds::core::StringSeq instances() const; + + void check() const; + + bool operator == (const PSMXInstancesDelegate &other) const; + + void set_iso_policy(const dds_qos_t* qos); + void set_c_policy(dds_qos_t* qos) const; +private: + dds::core::StringSeq instances_; +}; + } } } diff --git a/src/ddscxx/include/org/eclipse/cyclonedds/pub/qos/DataWriterQosDelegate.hpp b/src/ddscxx/include/org/eclipse/cyclonedds/pub/qos/DataWriterQosDelegate.hpp index 11bc783d..725fc5f7 100644 --- a/src/ddscxx/include/org/eclipse/cyclonedds/pub/qos/DataWriterQosDelegate.hpp +++ b/src/ddscxx/include/org/eclipse/cyclonedds/pub/qos/DataWriterQosDelegate.hpp @@ -61,6 +61,7 @@ class OMG_DDS_API DataWriterQosDelegate void policy(const dds::core::policy::TypeConsistencyEnforcement& typeconsistencyenforcement); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT void policy(const dds::core::policy::WriterBatching& writerbatching); + void policy(const dds::core::policy::PSMXInstances& psmxinstances); template const POLICY& policy() const; template POLICY& policy(); @@ -104,6 +105,7 @@ class OMG_DDS_API DataWriterQosDelegate dds::core::policy::TypeConsistencyEnforcement typeconsistencyenforcement_; #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT dds::core::policy::WriterBatching writerbatching_; + dds::core::policy::PSMXInstances psmxinstances_; }; @@ -281,6 +283,17 @@ DataWriterQosDelegate::policy() const template<> OMG_DDS_API dds::core::policy::WriterBatching& DataWriterQosDelegate::policy(); +template<> +OMG_DDS_API dds::core::policy::PSMXInstances& +DataWriterQosDelegate::policy(); + +template<> +inline const dds::core::policy::PSMXInstances& +DataWriterQosDelegate::policy() const +{ + return psmxinstances_; +} + } } } diff --git a/src/ddscxx/include/org/eclipse/cyclonedds/sub/qos/DataReaderQosDelegate.hpp b/src/ddscxx/include/org/eclipse/cyclonedds/sub/qos/DataReaderQosDelegate.hpp index 293eab59..c643a882 100644 --- a/src/ddscxx/include/org/eclipse/cyclonedds/sub/qos/DataReaderQosDelegate.hpp +++ b/src/ddscxx/include/org/eclipse/cyclonedds/sub/qos/DataReaderQosDelegate.hpp @@ -53,6 +53,7 @@ class OMG_DDS_API DataReaderQosDelegate void policy(const dds::core::policy::DataRepresentation& datarepresentation); void policy(const dds::core::policy::TypeConsistencyEnforcement& typeconsistencyenforcement); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + void policy(const dds::core::policy::PSMXInstances& psmxinstances); template const POLICY& policy() const; template POLICY& policy(); @@ -88,6 +89,7 @@ class OMG_DDS_API DataReaderQosDelegate dds::core::policy::DataRepresentation datarepresentation_; dds::core::policy::TypeConsistencyEnforcement typeconsistencyenforcement_; #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + dds::core::policy::PSMXInstances psmxinstances_; }; @@ -238,6 +240,17 @@ OMG_DDS_API dds::core::policy::TypeConsistencyEnforcement& DataReaderQosDelegate::policy(); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT +template<> +OMG_DDS_API dds::core::policy::PSMXInstances& +DataReaderQosDelegate::policy(); + +template<> +inline const dds::core::policy::PSMXInstances& +DataReaderQosDelegate::policy() const +{ + return psmxinstances_; +} + } } } diff --git a/src/ddscxx/include/org/eclipse/cyclonedds/topic/datatopic.hpp b/src/ddscxx/include/org/eclipse/cyclonedds/topic/datatopic.hpp index e00772b5..f3f7464c 100644 --- a/src/ddscxx/include/org/eclipse/cyclonedds/topic/datatopic.hpp +++ b/src/ddscxx/include/org/eclipse/cyclonedds/topic/datatopic.hpp @@ -18,6 +18,9 @@ #include #include "dds/ddsrt/md5.h" +#include "dds/ddsc/dds_loaned_sample.h" +#include "dds/ddsc/dds_psmx.h" +#include "org/eclipse/cyclonedds/core/ReportUtils.hpp" #include "org/eclipse/cyclonedds/core/cdr/basic_cdr_ser.hpp" #include "org/eclipse/cyclonedds/core/cdr/extended_cdr_v1_ser.hpp" #include "org/eclipse/cyclonedds/core/cdr/extended_cdr_v2_ser.hpp" @@ -25,17 +28,41 @@ #include "org/eclipse/cyclonedds/topic/TopicTraits.hpp" #include "org/eclipse/cyclonedds/topic/hash.hpp" -#ifdef DDSCXX_HAS_SHM -#include "dds/ddsi/ddsi_shm_transport.h" -#endif +constexpr size_t DDSI_RTPS_HEADER_SIZE = 4u; + +#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN + +#define DDSI_RTPS_CDR_BE 0x0000u +#define DDSI_RTPS_CDR_LE 0x0100u +#define DDSI_RTPS_PL_CDR_BE 0x0200u +#define DDSI_RTPS_PL_CDR_LE 0x0300u +#define DDSI_RTPS_CDR2_BE 0x0600u +#define DDSI_RTPS_CDR2_LE 0x0700u +#define DDSI_RTPS_D_CDR2_BE 0x0800u +#define DDSI_RTPS_D_CDR2_LE 0x0900u +#define DDSI_RTPS_PL_CDR2_BE 0x0a00u +#define DDSI_RTPS_PL_CDR2_LE 0x0b00u +#define DDSI_RTPS_SAMPLE_NATIVE 0x00c0u + +#define DDSI_RTPS_CDR_ENC_LE(x) (assert((x) != DDSI_RTPS_SAMPLE_NATIVE), ((x) & 0x0100) == 0x0100) -constexpr size_t CDR_HEADER_SIZE = 4U; -#define BO_LITTLE 0X01 -#define PLAIN_CDR 0x00 -#define PL_CDR 0x02 -#define PLAIN_CDR2 0x06 -#define D_CDR 0x08 -#define PL_CDR2 0x0A +#else + +#define DDSI_RTPS_CDR_BE 0x0000u +#define DDSI_RTPS_CDR_LE 0x0001u +#define DDSI_RTPS_PL_CDR_BE 0x0002u +#define DDSI_RTPS_PL_CDR_LE 0x0003u +#define DDSI_RTPS_CDR2_BE 0x0006u +#define DDSI_RTPS_CDR2_LE 0x0007u +#define DDSI_RTPS_D_CDR2_BE 0x0008u +#define DDSI_RTPS_D_CDR2_LE 0x0009u +#define DDSI_RTPS_PL_CDR2_BE 0x000au +#define DDSI_RTPS_PL_CDR2_LE 0x000bu +#define DDSI_RTPS_SAMPLE_NATIVE 0xc000u + +#define DDSI_RTPS_CDR_ENC_LE(x) (assert((x) != DDSI_RTPS_SAMPLE_NATIVE), ((x) & 0x0001) == 0x0001) + +#endif // macro to check if a pointer is nullptr and return false #define CHECK_FOR_NULL(val) if ((val) == nullptr) return false; @@ -118,16 +145,10 @@ template(calc_offset(buffer, 1)); - + memset(buffer, 0, DDSI_RTPS_HEADER_SIZE); + auto hdr = static_cast(buffer); assert(TopicTraits::getExtensibility() == extensibility::ext_final); - *ptr = PLAIN_CDR; - - if (native_endianness() == endianness::little_endian) - *ptr |= BO_LITTLE; - + hdr[0] = native_endianness() == endianness::little_endian ? DDSI_RTPS_CDR_LE : DDSI_RTPS_CDR_BE; return true; } @@ -137,25 +158,20 @@ template(calc_offset(buffer, 1)); - + memset(buffer, 0, DDSI_RTPS_HEADER_SIZE); + auto hdr = static_cast(buffer); + auto le = native_endianness() == endianness::little_endian; switch (TopicTraits::getExtensibility()) { case extensibility::ext_final: - *ptr = PLAIN_CDR2; + hdr[0] = le ? DDSI_RTPS_CDR2_LE : DDSI_RTPS_CDR2_BE; break; case extensibility::ext_appendable: - *ptr = D_CDR; + hdr[0] = le ? DDSI_RTPS_D_CDR2_LE : DDSI_RTPS_D_CDR2_BE; break; case extensibility::ext_mutable: - *ptr = PL_CDR2; + hdr[0] = le ? DDSI_RTPS_PL_CDR2_LE : DDSI_RTPS_PL_CDR2_BE; break; } - - if (native_endianness() == endianness::little_endian) - *ptr |= BO_LITTLE; - return true; } @@ -165,23 +181,18 @@ template(calc_offset(buffer, 1)); - + memset(buffer, 0, DDSI_RTPS_HEADER_SIZE); + auto hdr = static_cast(buffer); + auto le = native_endianness() == endianness::little_endian; switch (TopicTraits::getExtensibility()) { case extensibility::ext_final: case extensibility::ext_appendable: - *ptr = PLAIN_CDR; + hdr[0] = le ? DDSI_RTPS_CDR_LE : DDSI_RTPS_CDR_BE; break; case extensibility::ext_mutable: - *ptr = PL_CDR; + hdr[0] = le ? DDSI_RTPS_PL_CDR_LE : DDSI_RTPS_PL_CDR_BE; break; } - - if (native_endianness() == endianness::little_endian) - *ptr |= BO_LITTLE; - return true; } @@ -190,10 +201,8 @@ bool finish_header(void *buffer, size_t bytes_written) { CHECK_FOR_NULL(buffer); auto alignbytes = static_cast((4 - (bytes_written % 4)) % 4); - auto ptr = static_cast(calc_offset(buffer, 3)); - - *ptr = alignbytes; - + auto hdr = static_cast(buffer); + hdr[3] = alignbytes; return true; } @@ -201,18 +210,13 @@ template bool read_header(const void *buffer, encoding_version &ver, endianness &end) { CHECK_FOR_NULL(buffer); - auto ptr = static_cast(calc_offset(buffer, 1)); - - if (*ptr & BO_LITTLE) - end = endianness::little_endian; - else - end = endianness::big_endian; - - auto field = *ptr & ~BO_LITTLE; + auto hdr = static_cast(buffer); + end = DDSI_RTPS_CDR_ENC_LE(hdr[0]) ? endianness::little_endian : endianness::big_endian; switch (TopicTraits::getExtensibility()) { case extensibility::ext_final: - switch (field) { - case PLAIN_CDR: + switch (hdr[0]) { + case DDSI_RTPS_CDR_LE: + case DDSI_RTPS_CDR_BE: /** this can either mean: * - legacy cdr encoding * - PLAIN_CDR xcdr_v1 encoding (deprecated) @@ -229,7 +233,8 @@ bool read_header(const void *buffer, encoding_version &ver, endianness &end) else ver = encoding_version::xcdr_v1; break; - case PLAIN_CDR2: + case DDSI_RTPS_CDR2_LE: + case DDSI_RTPS_CDR2_BE: ver = encoding_version::xcdr_v2; break; default: @@ -237,11 +242,13 @@ bool read_header(const void *buffer, encoding_version &ver, endianness &end) } break; case extensibility::ext_appendable: - switch (field) { - case PLAIN_CDR: + switch (hdr[0]) { + case DDSI_RTPS_CDR_LE: + case DDSI_RTPS_CDR_BE: ver = encoding_version::xcdr_v1; break; - case D_CDR: + case DDSI_RTPS_D_CDR2_LE: + case DDSI_RTPS_D_CDR2_BE: ver = encoding_version::xcdr_v2; break; default: @@ -249,11 +256,13 @@ bool read_header(const void *buffer, encoding_version &ver, endianness &end) } break; case extensibility::ext_mutable: - switch (field) { - case PL_CDR: + switch (hdr[0]) { + case DDSI_RTPS_PL_CDR_LE: + case DDSI_RTPS_PL_CDR_BE: ver = encoding_version::xcdr_v1; break; - case PL_CDR2: + case DDSI_RTPS_PL_CDR2_LE: + case DDSI_RTPS_PL_CDR2_BE: ver = encoding_version::xcdr_v2; break; default: @@ -306,6 +315,22 @@ bool get_serialized_size(const T& sample, size_t &sz) return true; } +template +bool serialize_into_impl(void *hdr, + void *buffer, + size_t buf_sz, + const T &sample, + key_mode mode) +{ + CHECK_FOR_NULL(buffer); + CHECK_FOR_NULL(hdr); + + S str; + str.set_buffer(buffer, buf_sz); + return (write_header(hdr) + && write(str, sample, mode) + && finish_header(hdr, buf_sz)); +} template bool serialize_into(void *buffer, @@ -313,14 +338,21 @@ bool serialize_into(void *buffer, const T &sample, key_mode mode) { - CHECK_FOR_NULL(buffer); - assert(buf_sz >= CDR_HEADER_SIZE); + assert(buf_sz >= DDSI_RTPS_HEADER_SIZE); + void *cdr_start = calc_offset(buffer, DDSI_RTPS_HEADER_SIZE); + return serialize_into_impl(buffer,cdr_start,buf_sz, sample, mode); +} - S str; - str.set_buffer(calc_offset(buffer, CDR_HEADER_SIZE), buf_sz-CDR_HEADER_SIZE); - return (write_header(buffer) - && write(str, sample, mode) - && finish_header(buffer, buf_sz)); +template +bool deserialize_sample_from_buffer_impl(void *buffer, + size_t buf_sz, + T &sample, + const ddsi_serdata_kind data_kind, + endianness end) +{ + S str(end); + str.set_buffer(buffer, buf_sz); + return read(str, sample, data_kind == SDK_KEY ? key_mode::unsorted : key_mode::not_key); } /// \brief De-serialize the buffer into the sample @@ -344,28 +376,15 @@ bool deserialize_sample_from_buffer(void *buffer, if (!read_header(buffer, ver, end)) return false; - const bool k = (data_kind == SDK_KEY); switch (ver) { case encoding_version::basic_cdr: - { - basic_cdr_stream str(end); - str.set_buffer(calc_offset(buffer, CDR_HEADER_SIZE), buf_sz-CDR_HEADER_SIZE); - return read(str, sample, k ? key_mode::unsorted : key_mode::not_key); - } + return deserialize_sample_from_buffer_impl(calc_offset(buffer, DDSI_RTPS_HEADER_SIZE), buf_sz - DDSI_RTPS_HEADER_SIZE, sample, data_kind, end); break; case encoding_version::xcdr_v1: - { - xcdr_v1_stream str(end); - str.set_buffer(calc_offset(buffer, CDR_HEADER_SIZE), buf_sz-CDR_HEADER_SIZE); - return read(str, sample, k ? key_mode::unsorted : key_mode::not_key); - } + return deserialize_sample_from_buffer_impl(calc_offset(buffer, DDSI_RTPS_HEADER_SIZE), buf_sz - DDSI_RTPS_HEADER_SIZE, sample, data_kind, end); break; case encoding_version::xcdr_v2: - { - xcdr_v2_stream str(end); - str.set_buffer(calc_offset(buffer, CDR_HEADER_SIZE), buf_sz-CDR_HEADER_SIZE); - return read(str, sample, k ? key_mode::unsorted : key_mode::not_key); - } + return deserialize_sample_from_buffer_impl(calc_offset(buffer, DDSI_RTPS_HEADER_SIZE), buf_sz - DDSI_RTPS_HEADER_SIZE, sample, data_kind, end); break; default: return false; @@ -477,7 +496,7 @@ ddsi_serdata *serdata_from_sample( (!k && !get_serialized_size(msg, sz))) goto failure; - sz += CDR_HEADER_SIZE; + sz += DDSI_RTPS_HEADER_SIZE; d->resize(sz); if (!serialize_into(d->data(), sz, msg, k ? key_mode::unsorted : key_mode::not_key)) @@ -551,12 +570,16 @@ ddsi_serdata *serdata_to_untyped(const ddsi_serdata* dcmn) auto d1 = new ddscxx_serdata(d->type, SDK_KEY); d1->type = nullptr; - auto t = d->getT(); + const T* t; + if (d->loan && (d->loan->metadata->sample_state == DDS_LOANED_SAMPLE_STATE_RAW_KEY || d->loan->metadata->sample_state == DDS_LOANED_SAMPLE_STATE_RAW_DATA)) + t = static_cast(d->loan->sample_ptr); + else + t = d->getT(); size_t sz = 0; if (t == nullptr || !get_serialized_size(*t, sz)) goto failure; - sz += CDR_HEADER_SIZE; + sz += DDSI_RTPS_HEADER_SIZE; d1->resize(sz); if (!serialize_into(d1->data(), sz, *t, key_mode::unsorted)) @@ -591,19 +614,7 @@ bool serdata_untyped_to_sample( template void serdata_free(ddsi_serdata* dcmn) { - auto* d = static_cast*>(dcmn); - -#ifdef DDSCXX_HAS_SHM - if (d->iox_chunk && d->iox_subscriber) - { - // Explicit cast to iox_subscriber is required here, since the C++ binding has no notion of - // iox subscriber, but the underlying C API expects this to be a typed iox_subscriber. - // TODO (Sumanth), Fix this when we cleanup the interfaces to not use iceoryx directly in - // the C++ plugin - free_iox_chunk(static_cast(d->iox_subscriber), &d->iox_chunk); - } -#endif - delete d; + delete static_cast*>(dcmn); } template @@ -638,55 +649,115 @@ void serdata_get_keyhash( } } -#ifdef DDSCXX_HAS_SHM -template -uint32_t serdata_iox_size(const struct ddsi_serdata* d) +template +struct ddsi_serdata* serdata_from_loaned_sample ( + const struct ddsi_sertype *type, + enum ddsi_serdata_kind kind, + const char *sample, + struct dds_loaned_sample *loan, + bool force_serialization) { - assert(sizeof(T) == d->type->iox_size); - return d->type->iox_size; + assert (loan->loan_origin.origin_kind == DDS_LOAN_ORIGIN_KIND_PSMX); + const bool serialize_data = force_serialization || !(type->data_type_props & DDS_DATA_TYPE_IS_MEMCPY_SAFE); + const T* sample_in = reinterpret_cast(sample); + ddscxx_serdata *d; + + if (!serialize_data) + d = new ddscxx_serdata(type, kind); + else + d = static_cast *>(serdata_from_sample(type, kind, sample)); + if (d == nullptr) + return nullptr; + + d->loan = loan; + if (d->loan->sample_ptr == sample || !serialize_data) + { + assert(type->data_type_props & DDS_DATA_TYPE_IS_MEMCPY_SAFE); + d->loan->metadata->sample_state = (kind == SDK_KEY ? DDS_LOANED_SAMPLE_STATE_RAW_KEY : DDS_LOANED_SAMPLE_STATE_RAW_DATA); + d->loan->metadata->cdr_identifier = DDSI_RTPS_SAMPLE_NATIVE; + d->loan->metadata->cdr_options = 0; + if (d->loan->sample_ptr != sample) { + memcpy (d->loan->sample_ptr, sample, d->loan->metadata->sample_size); + } + d->key_md5_hashed() = to_key(*sample_in, d->key()); + d->populate_hash(*sample_in); + } + else + { + d->loan->metadata->sample_state = (kind == SDK_KEY ? DDS_LOANED_SAMPLE_STATE_SERIALIZED_KEY : DDS_LOANED_SAMPLE_STATE_SERIALIZED_DATA); + const char *hdr = static_cast(d->data()); + memcpy (&d->loan->metadata->cdr_identifier, hdr, sizeof (d->loan->metadata->cdr_identifier)); + memcpy (&d->loan->metadata->cdr_options, hdr + 2, sizeof (d->loan->metadata->cdr_options)); + memcpy (d->loan->sample_ptr, calc_offset(d->data(), DDSI_RTPS_HEADER_SIZE), d->loan->metadata->sample_size); + } + + return d; } + template -ddsi_serdata * serdata_from_iox_buffer( - const struct ddsi_sertype * typecmn, enum ddsi_serdata_kind kind, - void * sub, void * iox_buffer) +struct ddsi_serdata* serdata_from_psmx ( + const struct ddsi_sertype *type, + struct dds_loaned_sample *loan) { - try { - auto d = new ddscxx_serdata(typecmn, kind); - - // serdata from the loaned sample (when using iceoryx) - d->iox_chunk = iox_buffer; + struct dds_psmx_metadata *md = loan->metadata; + enum ddsi_serdata_kind kind = SDK_EMPTY; + switch (md->sample_state) + { + case DDS_LOANED_SAMPLE_STATE_RAW_DATA: + case DDS_LOANED_SAMPLE_STATE_SERIALIZED_DATA: + kind = SDK_DATA; + break; + case DDS_LOANED_SAMPLE_STATE_RAW_KEY: + case DDS_LOANED_SAMPLE_STATE_SERIALIZED_KEY: + kind = SDK_KEY; + break; + default: + return nullptr; + } - // Update the iox subscriber, when constructing the serdata in the case of sample received - // from iceoryx - if (sub != nullptr) { - d->iox_subscriber = sub; + ddscxx_serdata *d = new ddscxx_serdata(type, kind); + if (DDS_LOANED_SAMPLE_STATE_RAW_DATA != md->sample_state && DDS_LOANED_SAMPLE_STATE_RAW_KEY != md->sample_state) + { + bool deser_result = false; + switch (md->cdr_identifier) + { + case DDSI_RTPS_CDR_LE: case DDSI_RTPS_CDR_BE: + if (TopicTraits::allowableEncodings() & DDS_DATA_REPRESENTATION_FLAG_XCDR1) + deser_result = deserialize_sample_from_buffer_impl(loan->sample_ptr, md->sample_size, *(d->getT(false)), kind, native_endianness()); + else + deser_result = deserialize_sample_from_buffer_impl(loan->sample_ptr, md->sample_size, *(d->getT(false)), kind, native_endianness()); + break; + case DDSI_RTPS_PL_CDR_LE: case DDSI_RTPS_PL_CDR_BE: + deser_result = deserialize_sample_from_buffer_impl(loan->sample_ptr, md->sample_size, *(d->getT(false)), kind, native_endianness()); + break; + case DDSI_RTPS_CDR2_LE: case DDSI_RTPS_CDR2_BE: + case DDSI_RTPS_D_CDR2_LE: case DDSI_RTPS_D_CDR2_BE: + case DDSI_RTPS_PL_CDR2_LE: case DDSI_RTPS_PL_CDR2_BE: + deser_result = deserialize_sample_from_buffer_impl(loan->sample_ptr, md->sample_size, *(d->getT(false)), kind, native_endianness()); + break; + default: + abort (); } - - // key handling - if (typecmn->fixed_size) { - const auto& msg = *static_cast(d->iox_chunk); - d->key_md5_hashed() = to_key(msg, d->key()); - d->populate_hash(); - } else { - T msg; - iceoryx_header_t *iox_header = iceoryx_header_from_chunk(d->iox_chunk); - if (deserialize_sample_from_buffer(d->iox_chunk, iox_header->data_size, msg, kind)) { - d->key_md5_hashed() = to_key(msg, d->key()); - d->populate_hash(); - } else { - delete d; - d = nullptr; - } + if (!deser_result) //deserialization unsuccesful, abort + { + delete d; + return nullptr; } - - return d; } - catch (std::exception&) { - return nullptr; + else + { + d->setLoan(loan); } + + + d->key_md5_hashed() = to_key(*(d->getT()), d->key()); + d->populate_hash(); + d->statusinfo = md->statusinfo; + d->timestamp.v = md->timestamp; + + return d; } -#endif template @@ -706,11 +777,9 @@ struct ddscxx_serdata_ops: public ddsi_serdata_ops { &serdata_untyped_to_sample, &serdata_free, &serdata_print, - &serdata_get_keyhash -#ifdef DDSCXX_HAS_SHM - , &serdata_iox_size - , &serdata_from_iox_buffer -#endif + &serdata_get_keyhash, + &serdata_from_loaned_sample, + &serdata_from_psmx } { ; } }; @@ -720,13 +789,12 @@ class ddscxx_serdata : public ddsi_serdata { std::unique_ptr m_data{ nullptr }; ddsi_keyhash_t m_key; bool m_key_md5_hashed = false; - std::atomic m_t{ nullptr }; + std::atomic m_t; //use a recursive mutex and do all modifications inside it? public: bool hash_populated = false; ddscxx_serdata(const ddsi_sertype* type, ddsi_serdata_kind kind); - ~ddscxx_serdata() { delete m_t.load(std::memory_order_acquire); } - + ~ddscxx_serdata(); void resize(size_t requested_size); size_t size() const { return m_size; } void* data() const { return m_data.get(); } @@ -734,23 +802,34 @@ class ddscxx_serdata : public ddsi_serdata { const ddsi_keyhash_t& key() const { return m_key; } bool& key_md5_hashed() { return m_key_md5_hashed; } const bool& key_md5_hashed() const { return m_key_md5_hashed; } + void populate_hash(const T & sample); void populate_hash(); T* setT(const T* toset); - T* getT(); + T* getT(bool force_deserialization = true); + void setLoan(dds_loaned_sample_t *newloan); private: - void deserialize_and_update_sample(uint8_t * buffer, size_t sz, T *& t); - void update_sample_from_iox_chunk(T *& t); + void deserialize_and_update_sample(uint8_t * buffer, size_t sz, T *& t, bool force_deserialization); }; template ddscxx_serdata::ddscxx_serdata(const ddsi_sertype* type, ddsi_serdata_kind kind) - : ddsi_serdata{} + : ddsi_serdata{}, m_t(nullptr) { memset(m_key.value, 0x0, 16); ddsi_serdata_init(this, type, kind); } +template +ddscxx_serdata::~ddscxx_serdata() +{ + T* t = m_t.load(std::memory_order_acquire); + if (!loan || loan->sample_ptr != t) + delete t; + if (loan) + dds_loaned_sample_unref (loan); +} + template void ddscxx_serdata::resize(size_t requested_size) { @@ -771,12 +850,12 @@ void ddscxx_serdata::resize(size_t requested_size) } template -void ddscxx_serdata::populate_hash() +void ddscxx_serdata::populate_hash(const T & sample) { if (hash_populated) return; - key_md5_hashed() = to_key(*getT(), key()); + key_md5_hashed() = to_key(sample, key()); if (!key_md5_hashed()) { ddsi_keyhash_t buf; @@ -795,6 +874,13 @@ void ddscxx_serdata::populate_hash() hash_populated = true; } +template +void ddscxx_serdata::populate_hash() +{ + if (hash_populated) + populate_hash(*getT()); +} + template T* ddscxx_serdata::setT(const T* toset) { @@ -814,27 +900,22 @@ T* ddscxx_serdata::setT(const T* toset) } template -T* ddscxx_serdata::getT() { +T* ddscxx_serdata::getT(bool force_deserialization) { // check if m_t is already set T *t = m_t.load(std::memory_order_acquire); // if m_t is not set if (t == nullptr) { - // if the data is available on iox_chunk, update and get the sample - update_sample_from_iox_chunk(t); - // if its not possible to get the sample from iox_chunk - if(t == nullptr) { - // deserialize and get the sample - deserialize_and_update_sample(static_cast(data()), size(), t); - } + deserialize_and_update_sample(static_cast(data()), size(), t, force_deserialization); } return t; } template -void ddscxx_serdata::deserialize_and_update_sample(uint8_t * buffer, size_t sz, T *& t) { +void ddscxx_serdata::deserialize_and_update_sample(uint8_t * buffer, size_t sz, T *& t, bool force_deserialization) { t = new T(); // if deserialization failed - if(!deserialize_sample_from_buffer(buffer, sz, *t, kind)) { + if (force_deserialization && + !deserialize_sample_from_buffer(buffer, sz, *t, kind)) { delete t; t = nullptr; } @@ -846,29 +927,20 @@ void ddscxx_serdata::deserialize_and_update_sample(uint8_t * buffer, size_t s } } -template -void ddscxx_serdata::update_sample_from_iox_chunk(T *& t) { -#ifdef DDSCXX_HAS_SHM - // if data is available on the iox_chunk (and doesn't have a serialized representation) - if (iox_chunk != nullptr && data() == nullptr) { - auto iox_header = iceoryx_header_from_chunk(iox_chunk); - // if the iox chunk has the data in serialized form - if (iox_header->shm_data_state == IOX_CHUNK_CONTAINS_SERIALIZED_DATA) { - deserialize_and_update_sample(static_cast(iox_chunk), iox_header->data_size, t); - } else if (iox_header->shm_data_state == IOX_CHUNK_CONTAINS_RAW_DATA) { - // get the chunk directly without any copy - t = static_cast(this->iox_chunk); - } else { - // Data is in un-initialized state, which shouldn't happen - t = nullptr; - } - } else { - // data is not available on iox_chunk - t = nullptr; - } -#else - t = nullptr; -#endif // DDSCXX_HAS_SHM +template +void ddscxx_serdata::setLoan(dds_loaned_sample_t *newloan) +{ + T *t = m_t.load(std::memory_order_acquire); + if (!loan || t != loan->sample_ptr) + delete t; + if (loan) + dds_loaned_sample_unref(loan); + + if (!m_t.compare_exchange_strong(t, static_cast(newloan->sample_ptr), std::memory_order_seq_cst)) + ISOCPP_THROW_EXCEPTION(ISOCPP_ERROR,"Could not store loaned sample."); + + dds_loaned_sample_ref(newloan); + loan = newloan; } template @@ -955,14 +1027,13 @@ size_t sertype_get_serialized_size(const ddsi_sertype*, const void * sample) { const auto& msg = *static_cast(sample); - // get the serialized size of the sample (with out serializing) + // get the serialized size of the sample (without serializing) size_t sz = 0; if (!get_serialized_size(msg, sz)) { // the max value is treated as an error in the Cyclone core - return SIZE_MAX; + sz = SIZE_MAX; } - - return sz + CDR_HEADER_SIZE; // Include the additional bytes for the CDR header + return sz; } template @@ -1023,27 +1094,21 @@ template ddscxx_sertype::ddscxx_sertype() : ddsi_sertype{} { - uint32_t flags = (TopicTraits::isKeyless() ? DDSI_SERTYPE_FLAG_TOPICKIND_NO_KEY : 0); -#ifdef DDSCXX_HAS_SHM - flags |= (TopicTraits::isSelfContained() ? - DDSI_SERTYPE_FLAG_FIXED_SIZE : 0); -#endif - - ddsi_sertype_init_flags( + dds_data_type_properties_t dtp = 0; + if (! TopicTraits::isKeyless()) + dtp |= DDS_DATA_TYPE_CONTAINS_KEY; + if (TopicTraits::isSelfContained()) + dtp |= DDS_DATA_TYPE_IS_MEMCPY_SAFE; + + ddsi_sertype_init_props( static_cast(this), TopicTraits::getTypeName(), &sertype_ops, &serdata_ops, - flags); - - allowed_data_representation = TopicTraits::allowableEncodings(); - -#ifdef DDSCXX_HAS_SHM - // update the size of the type, if its fixed - // this needs to be done after sertype init! TODO need an API in Cyclone DDS to set this - this->iox_size = - static_cast(TopicTraits::getSampleSize()); -#endif + sizeof(T), + dtp, + TopicTraits::allowableEncodings(), + 0); } #endif // DDSCXXDATATOPIC_HPP_ diff --git a/src/ddscxx/src/dds/core/policy/CorePolicy.cpp b/src/ddscxx/src/dds/core/policy/CorePolicy.cpp index 30f64da8..b500a215 100644 --- a/src/ddscxx/src/dds/core/policy/CorePolicy.cpp +++ b/src/ddscxx/src/dds/core/policy/CorePolicy.cpp @@ -48,3 +48,4 @@ OMG_DDS_DEFINE_POLICY_TRAITS(dds::core::policy::TypeConsistencyEnforcement, Type OMG_DDS_DEFINE_POLICY_TRAITS(dds::core::policy::DurabilityService, DurabilityService) #endif // OMG_DDS_PERSISTENCE_SUPPORT OMG_DDS_DEFINE_POLICY_TRAITS(dds::core::policy::WriterBatching, WriterBatching) +OMG_DDS_DEFINE_POLICY_TRAITS(dds::core::policy::PSMXInstances, PSMXInstances) diff --git a/src/ddscxx/src/org/eclipse/cyclonedds/core/policy/PolicyDelegate.cpp b/src/ddscxx/src/org/eclipse/cyclonedds/core/policy/PolicyDelegate.cpp index d0af7138..3595abe9 100644 --- a/src/ddscxx/src/org/eclipse/cyclonedds/core/policy/PolicyDelegate.cpp +++ b/src/ddscxx/src/org/eclipse/cyclonedds/core/policy/PolicyDelegate.cpp @@ -19,6 +19,7 @@ #include #include "dds/dds.h" #include "dds/ddsc/dds_public_qos.h" +#include "dds/ddsc/dds_psmx.h" namespace org { @@ -1914,6 +1915,63 @@ void TypeConsistencyEnforcementDelegate::set_c_policy(dds_qos_t* qos) const #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT +PSMXInstancesDelegate::PSMXInstancesDelegate(const PSMXInstancesDelegate& other): instances_(other.instances_) +{ +} + +PSMXInstancesDelegate::PSMXInstancesDelegate(const dds::core::StringSeq &instances): instances_(instances) +{ + this->check(); +} + +void PSMXInstancesDelegate::instances(const dds::core::StringSeq &instances) +{ + instances_ = instances; +} + +const dds::core::StringSeq PSMXInstancesDelegate::instances() const +{ + return instances_; +} + +void PSMXInstancesDelegate::check() const +{ + if (instances_.size() > DDS_MAX_PSMX_INSTANCES) + ISOCPP_THROW_EXCEPTION(ISOCPP_INVALID_ARGUMENT_ERROR, "Invalid size of PSMXInstances::instances value (%ld > %d).", instances_.size(), DDS_MAX_PSMX_INSTANCES); +} + +bool PSMXInstancesDelegate::operator == (const PSMXInstancesDelegate &other) const +{ + return other.instances_ == instances_; +} + +void PSMXInstancesDelegate::set_iso_policy(const dds_qos_t* qos) +{ + uint32_t n_out = 0; + char **values = NULL; + + if (dds_qget_psmx_instances(qos, + &n_out, + &values)) { + instances_.clear(); + for (uint32_t n = 0; n < n_out; n++) { + ISOCPP_BOOL_CHECK_AND_THROW(NULL != values[n], + ISOCPP_NULL_REFERENCE_ERROR, + "Invalid PSMX value returned."); + instances_.push_back(values[n]); + dds_string_free(values[n]); + } + } +} + +void PSMXInstancesDelegate::set_c_policy(dds_qos_t* qos) const +{ + std::vector values; + for (const auto &str:instances_) + values.push_back(str.c_str()); + dds_qset_psmx_instances (qos, static_cast(values.size()), values.data()); +} + } } } diff --git a/src/ddscxx/src/org/eclipse/cyclonedds/pub/AnyDataWriterDelegate.cpp b/src/ddscxx/src/org/eclipse/cyclonedds/pub/AnyDataWriterDelegate.cpp index 9127c0d8..e9dffe33 100644 --- a/src/ddscxx/src/org/eclipse/cyclonedds/pub/AnyDataWriterDelegate.cpp +++ b/src/ddscxx/src/org/eclipse/cyclonedds/pub/AnyDataWriterDelegate.cpp @@ -19,15 +19,10 @@ #include #include #include -#include #include "dds/ddsi/ddsi_protocol.h" #include "dds/features.hpp" -#ifdef DDSCXX_HAS_SHM -#include -#endif - namespace org { @@ -118,28 +113,6 @@ AnyDataWriterDelegate::write_cdr( ser_data->statusinfo = statusinfo; - // if shared memory is supported by the writer - if(dds_is_shared_memory_available(writer)) { -#ifdef DDSCXX_HAS_SHM - void *iox_chunk ; - // request a loan from the shared memory buffer - ret = dds_loan_shared_memory_buffer(writer, - data->payload().size() + data->encoding().size(), // include the size for the encoding (CDR header) - &iox_chunk); - ISOCPP_DDSC_RESULT_CHECK_AND_THROW(ret, "write_cdr - Loaning of chunk failed"); - ISOCPP_BOOL_CHECK_AND_THROW(iox_chunk, ISOCPP_NULL_REFERENCE_ERROR, "write_cdr - Loaning of chunk failed"); - // copy the header - memcpy(iox_chunk, data->encoding().data(), data->encoding().size()); - // copy the actual data - memcpy(static_cast(iox_chunk) + data->encoding().size(), - data->payload().data(), data->payload().size()); - // update SHM data state to serialized, since this API is used only to publish the serialized data - shm_set_data_state(iox_chunk, IOX_CHUNK_CONTAINS_SERIALIZED_DATA); - // update the loaned iox chunk in serdata - ser_data->iox_chunk = iox_chunk; -#endif - } - if (timestamp != dds::core::Time::invalid()) { dds_time_t ddsc_time = org::eclipse::cyclonedds::core::convertTime(timestamp); ser_data->timestamp.v = ddsc_time; @@ -148,18 +121,7 @@ AnyDataWriterDelegate::write_cdr( ret = dds_writecdr(writer, ser_data); } -#ifdef DDSCXX_HAS_SHM - if (ret != DDS_RETCODE_OK) { - if (ser_data->iox_chunk != nullptr) { - // write cdr failed, so free the chunk - ret = dds_return_loan(writer, &ser_data->iox_chunk, 1); - ISOCPP_DDSC_RESULT_CHECK_AND_THROW(ret, "write_cdr, freeing loan failed"); - } - ISOCPP_DDSC_RESULT_CHECK_AND_THROW(ret, "write_cdr failed."); - } -#else ISOCPP_DDSC_RESULT_CHECK_AND_THROW(ret, "write_cdr failed."); -#endif } void @@ -195,7 +157,9 @@ AnyDataWriterDelegate::unregister_instance_cdr( bool AnyDataWriterDelegate::is_loan_supported(const dds_entity_t writer) { - return dds_is_loan_available(writer); + DDSRT_WARNING_DEPRECATED_OFF + return dds_is_loan_available(writer); + DDSRT_WARNING_DEPRECATED_ON } void @@ -205,7 +169,7 @@ AnyDataWriterDelegate::loan_sample( { dds_return_t ret; - ret = dds_loan_sample(writer, sample); + ret = dds_request_loan(writer, sample); ISOCPP_DDSC_RESULT_CHECK_AND_THROW(ret, "sample loan failed."); } diff --git a/src/ddscxx/src/org/eclipse/cyclonedds/pub/qos/DataWriterQosDelegate.cpp b/src/ddscxx/src/org/eclipse/cyclonedds/pub/qos/DataWriterQosDelegate.cpp index e30b4f69..8372ca4e 100644 --- a/src/ddscxx/src/org/eclipse/cyclonedds/pub/qos/DataWriterQosDelegate.cpp +++ b/src/ddscxx/src/org/eclipse/cyclonedds/pub/qos/DataWriterQosDelegate.cpp @@ -193,6 +193,14 @@ DataWriterQosDelegate::policy(const dds::core::policy::WriterBatching& writerbat writerbatching_ = writerbatching; } +void +DataWriterQosDelegate::policy(const dds::core::policy::PSMXInstances& psmxinstances) +{ + psmxinstances.delegate().check(); + present_ |= DDSI_QP_PSMX; + psmxinstances_ = psmxinstances; +} + dds_qos_t* DataWriterQosDelegate::ddsc_qos() const { @@ -242,6 +250,8 @@ DataWriterQosDelegate::ddsc_qos() const #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT if (present_ & DDSI_QP_CYCLONE_WRITER_BATCHING) writerbatching_.delegate().set_c_policy(qos); + if (present_ & DDSI_QP_PSMX) + psmxinstances_.delegate().set_c_policy(qos); return qos; } @@ -292,6 +302,8 @@ DataWriterQosDelegate::ddsc_qos(const dds_qos_t* qos) #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT if (present_ & DDSI_QP_CYCLONE_WRITER_BATCHING) writerbatching_.delegate().set_iso_policy(qos); + if (present_ & DDSI_QP_PSMX) + psmxinstances_.delegate().set_iso_policy(qos); } void @@ -327,6 +339,7 @@ DataWriterQosDelegate::named_qos(const struct _DDS_NamedDataWriterQos &qos) typeconsistencyenforcement_.delegate().v_policy((v_writerTypeConsistencyEnforcementPolicy&)(q->writer_typeconsistencyenforcement)); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT writerbatching_.delegate().v_policy((v_writerbatchingPolicy&)(q->writer_batching) ); + psmxinstances_.delegate().v_policy((v_psmxinstancesPolicy&)(q->psmxinstances) ); #endif } @@ -366,6 +379,7 @@ DataWriterQosDelegate::operator ==(const DataWriterQosDelegate& other) const && other.typeconsistencyenforcement_ == typeconsistencyenforcement_ #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT && other.writerbatching_ == writerbatching_ + && other.psmxinstances_ == psmxinstances_ ; } @@ -539,6 +553,13 @@ DataWriterQosDelegate::policy() return writerbatching_; } +template<> dds::core::policy::PSMXInstances& +DataWriterQosDelegate::policy() +{ + present_ |= DDSI_QP_PSMX; + return psmxinstances_; +} + } } } diff --git a/src/ddscxx/src/org/eclipse/cyclonedds/sub/AnyDataReaderDelegate.cpp b/src/ddscxx/src/org/eclipse/cyclonedds/sub/AnyDataReaderDelegate.cpp index 372c89a2..75ff955a 100644 --- a/src/ddscxx/src/org/eclipse/cyclonedds/sub/AnyDataReaderDelegate.cpp +++ b/src/ddscxx/src/org/eclipse/cyclonedds/sub/AnyDataReaderDelegate.cpp @@ -23,7 +23,6 @@ #include #include "dds/dds.h" -#include "dds/ddsc/dds_loan_api.h" #include "dds/ddsc/dds_internal_api.h" #define NORMALIZE_LENGTH(maxs) maxs == static_cast(dds::core::LENGTH_UNLIMITED) ? static_cast(INT32_MAX) : maxs @@ -149,7 +148,9 @@ AnyDataReaderDelegate::collector_callback_fn ( bool AnyDataReaderDelegate::is_loan_supported(const dds_entity_t reader) const { + DDSRT_WARNING_DEPRECATED_OFF return dds_is_loan_available(reader); + DDSRT_WARNING_DEPRECATED_ON } void diff --git a/src/ddscxx/src/org/eclipse/cyclonedds/sub/qos/DataReaderQosDelegate.cpp b/src/ddscxx/src/org/eclipse/cyclonedds/sub/qos/DataReaderQosDelegate.cpp index e0a8833b..50545084 100644 --- a/src/ddscxx/src/org/eclipse/cyclonedds/sub/qos/DataReaderQosDelegate.cpp +++ b/src/ddscxx/src/org/eclipse/cyclonedds/sub/qos/DataReaderQosDelegate.cpp @@ -157,6 +157,14 @@ DataReaderQosDelegate::policy(const dds::core::policy::TypeConsistencyEnforcemen } #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT +void +DataReaderQosDelegate::policy(const dds::core::policy::PSMXInstances& psmxinstances) +{ + psmxinstances.delegate().check(); + present_ |= DDSI_QP_PSMX; + psmxinstances_ = psmxinstances; +} + dds_qos_t* DataReaderQosDelegate::ddsc_qos() const { @@ -194,6 +202,8 @@ DataReaderQosDelegate::ddsc_qos() const if (present_ & DDSI_QP_TYPE_CONSISTENCY_ENFORCEMENT) typeconsistencyenforcement_.delegate().set_c_policy(qos); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + if (present_ & DDSI_QP_PSMX) + psmxinstances_.delegate().set_c_policy(qos); return qos; } @@ -232,6 +242,8 @@ DataReaderQosDelegate::ddsc_qos(const dds_qos_t* qos) if (present_ & DDSI_QP_TYPE_CONSISTENCY_ENFORCEMENT) typeconsistencyenforcement_.delegate().set_iso_policy(qos); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + if (present_ & DDSI_QP_PSMX) + psmxinstances_.delegate().set_iso_policy(qos); } void @@ -260,6 +272,7 @@ DataReaderQosDelegate::named_qos(const struct _DDS_NamedDataReaderQos &qos) datarepresentation_.delegate().v_policy((v_dataRepresentationPolicy&)(q->datarepresentation)); typeconsistencyenforcement_.delegate().v_policy((v_typeConsistencyEnforcementPolicy&)(q->typeconsistencyenforcement)); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + psmxinstances_.delegate().v_policy((v_psmxinstancesPolicy&)(q->psmxinstances) ); #endif } @@ -292,6 +305,7 @@ DataReaderQosDelegate::operator==(const DataReaderQosDelegate& other) const && other.datarepresentation_ == datarepresentation_ && other.typeconsistencyenforcement_ == typeconsistencyenforcement_ #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + && other.psmxinstances_ == psmxinstances_ ; } @@ -437,6 +451,13 @@ DataReaderQosDelegate::policy() } #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT +template<> dds::core::policy::PSMXInstances& +DataReaderQosDelegate::policy() +{ + present_ |= DDSI_QP_PSMX; + return psmxinstances_; +} + } } } diff --git a/src/ddscxx/tests/CMakeLists.txt b/src/ddscxx/tests/CMakeLists.txt index 48332ea1..de37ca3e 100644 --- a/src/ddscxx/tests/CMakeLists.txt +++ b/src/ddscxx/tests/CMakeLists.txt @@ -13,6 +13,7 @@ find_package(GTest REQUIRED) idlcxx_generate(TARGET ddscxx_test_types FILES data/Space.idl + data/KeylessSpace.idl data/HelloWorldData.idl data/Serialization.idl data/CdrDataModels.idl @@ -30,8 +31,8 @@ idlcxx_generate(TARGET ddscxx_test_types FILES configure_file( config_simple.xml.in config_simple.xml @ONLY) -if(ENABLE_SHM) - # Packages required packages for SHM tests +if(ENABLE_ICEORYX) + # Packages required packages for Iceoryx tests find_package(iceoryx_posh REQUIRED) find_package(iceoryx_posh_testing REQUIRED) endif() @@ -78,9 +79,8 @@ if (ENABLE_TYPELIB AND ENABLE_TOPIC_DISCOVERY) TopicTypeDiscovery.cpp) endif() -if(ENABLE_SHM) - # Add shared memory tests - list(APPEND sources SharedMemory.cpp) +if(ENABLE_ICEORYX) + list(APPEND sources Iceoryx.cpp) endif() add_executable(ddscxx_tests ${sources}) @@ -101,7 +101,7 @@ target_link_libraries( GTest::Main ddscxx_test_types) -if(ENABLE_SHM) +if(ENABLE_ICEORYX) target_link_libraries( ddscxx_tests PRIVATE iceoryx_posh::iceoryx_posh_roudi @@ -131,7 +131,7 @@ endif() get_target_property(cyclonedds_lib CycloneDDS::ddsc LOCATION) get_target_property(gtest_lib GTest::GTest IMPORTED_LOCATION) get_target_property(gtest_main_lib GTest::Main IMPORTED_LOCATION) -if(ENABLE_SHM) +if(ENABLE_ICEORYX) get_target_property(gmock_lib GTest::GMock IMPORTED_LOCATION) get_target_property(gmock_main_lib GTest::GMockMain IMPORTED_LOCATION) endif() diff --git a/src/ddscxx/tests/DataWriter.cpp b/src/ddscxx/tests/DataWriter.cpp index c97113fe..90cd26b4 100644 --- a/src/ddscxx/tests/DataWriter.cpp +++ b/src/ddscxx/tests/DataWriter.cpp @@ -571,6 +571,26 @@ TEST_F(DataWriter, write_iter_with_timestamp) ReadAndCheckSampleType1(samplesC[1], viewedState, true); } +TEST_F(DataWriter, write_cdr) +{ + Space::Type1 testData(0,1,2); + this->SetupCommunication(false); + + /* Write one sample (1st 0x00,0x00: CDR_BE, 2nd 0x00,0x00: no options, padding). */ + const std::array encoding{0x00, 0x00, 0x00, 0x00}; + const std::vector payloadcdr{0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x02}; + org::eclipse::cyclonedds::topic::CDRBlob cdrblob{ + encoding, org::eclipse::cyclonedds::topic::BlobKind::Data, payloadcdr}; + + this->writer->write_cdr(cdrblob); + + /* Check result. */ + dds::sub::status::DataState notReadState(dds::sub::status::SampleState::not_read(), + dds::sub::status::ViewState::new_view(), + dds::sub::status::InstanceState::alive()); + ReadAndCheckSampleType1(testData, notReadState, true); +} + TEST_F(DataWriter, writedispose) { Space::Type1 testData0(0,0,0); diff --git a/src/ddscxx/tests/SharedMemory.cpp b/src/ddscxx/tests/Iceoryx.cpp similarity index 73% rename from src/ddscxx/tests/SharedMemory.cpp rename to src/ddscxx/tests/Iceoryx.cpp index 9a1fb3d4..4c6cc903 100644 --- a/src/ddscxx/tests/SharedMemory.cpp +++ b/src/ddscxx/tests/Iceoryx.cpp @@ -13,10 +13,9 @@ #include "dds/dds.hpp" #include "dds/ddsrt/environ.h" -#include "dds/ddsi/ddsi_shm_transport.h" #include "iceoryx_posh/testing/roudi_gtest.hpp" #include "HelloWorldData.hpp" -#include "Space.hpp" +#include "KeylessSpace.hpp" #include "Serialization.hpp" #include "iceoryx_posh/popo/subscriber.hpp" #include "iceoryx_posh/popo/sample.hpp" @@ -35,13 +34,11 @@ namespace { -using IceoryxHeader = iceoryx_header; - template void make_sample_(T & sample, const int32_t cnt); template<> -void make_sample_(Space::Type1 & sample, const int32_t cnt) +void make_sample_(KeylessSpace::Type1 & sample, const int32_t cnt) { sample.long_1(cnt); sample.long_2(cnt + 1); @@ -49,7 +46,7 @@ void make_sample_(Space::Type1 & sample, const int32_t cnt) } template<> -void make_sample_(Space::Type2 & sample, const int32_t cnt) +void make_sample_(KeylessSpace::Type2 & sample, const int32_t cnt) { sample.long_1(cnt); sample.long_2(cnt + 1); @@ -115,7 +112,7 @@ constexpr bool DO_NOT_USE_ICEORYX = false; * Fixture for the shared memory tests with RouDi */ template -class SharedMemoryTest : public RouDi_GTest +class IceoryxTest : public RouDi_GTest { public: using TopicType = T; @@ -135,11 +132,11 @@ class SharedMemoryTest : public RouDi_GTest // read condition for the reader of content filtered topic dds::sub::cond::ReadCondition flt_rc; dds::core::cond::WaitSet waitset; - iox::cxx::optional> iceoryx_subscriber; + iox::cxx::optional> iceoryx_subscriber; static constexpr char TOPIC_NAME[] = "datareader_test_topic"; - SharedMemoryTest() + IceoryxTest() : participant(dds::core::null), subscriber(dds::core::null), flt_subscriber(dds::core::null), @@ -162,15 +159,23 @@ class SharedMemoryTest : public RouDi_GTest { if (this->participant == dds::core::null) { // configuration to enable shared memory communication - static const std::string shm_config { - "trueverbose"}; + static const std::string cdds_config { + "" + "" + " " + " " + " " + "" + "" + }; this->participant = dds::domain::DomainParticipant( 0, dds::domain::DomainParticipant::default_participant_qos(), nullptr, dds::core::status::StatusMask::none(), - shm_config); + cdds_config); ASSERT_NE(this->participant, dds::core::null); } } @@ -220,8 +225,8 @@ class SharedMemoryTest : public RouDi_GTest ASSERT_NE(this->reader, dds::core::null); this->iceoryx_subscriber.emplace( - iox::capro::ServiceDescription{"DDS_CYCLONE", - iox::capro::IdString_t(iox::cxx::TruncateToCapacity, org::eclipse::cyclonedds::topic::TopicTraits::getTypeName()), + iox::capro::ServiceDescription{"CYCLONEDDS", + iox::capro::IdString_t(iox::cxx::TruncateToCapacity, org::eclipse::cyclonedds::topic::TopicTraits::getTypeName()), iox::capro::IdString_t(iox::cxx::TruncateToCapacity, std::string(".") + std::string(TOPIC_NAME)) /* default partition . topic name */ }); } @@ -335,19 +340,39 @@ class SharedMemoryTest : public RouDi_GTest auto iceoryx_data = iox_sample.get(); // if the data in the chunk is of the serialized type - if (user_header.shm_data_state == IOX_CHUNK_CONTAINS_SERIALIZED_DATA) { + if (user_header.sample_state == DDS_LOANED_SAMPLE_STATE_SERIALIZED_DATA) { // Since the data in iceoryx chunk is in the serialized form, take the // sample and deserialize the data and then compare with the sent data auto buf_ptr = reinterpret_cast(const_cast(iceoryx_data)); T msg; - deserialize_sample_from_buffer(buf_ptr, SIZE_MAX, msg); + endianness end; + encoding_version ver; + unsigned char hdr[DDSI_RTPS_HEADER_SIZE]; + memcpy (hdr, &user_header.cdr_identifier, 2); + memcpy (hdr + 2, &user_header.cdr_options, 2); + read_header(hdr, ver, end); + + switch (ver) { + case encoding_version::basic_cdr: + deserialize_sample_from_buffer_impl(buf_ptr, user_header.sample_size, msg, SDK_DATA, end); + break; + case encoding_version::xcdr_v1: + deserialize_sample_from_buffer_impl(buf_ptr, user_header.sample_size, msg, SDK_DATA, end); + break; + case encoding_version::xcdr_v2: + deserialize_sample_from_buffer_impl(buf_ptr, user_header.sample_size, msg, SDK_DATA, end); + break; + default: + abort(); + } + ASSERT_EQ(msg, test_data); - } else if (user_header.shm_data_state == IOX_CHUNK_CONTAINS_RAW_DATA) { + } else if (user_header.sample_state == DDS_LOANED_SAMPLE_STATE_RAW_DATA) { // the chunk already has deserialized data and can be compared directly ASSERT_EQ(*iceoryx_data, test_data); } else { throw std::runtime_error( - "the data state is not expected " + std::to_string(user_header.shm_data_state)); + "the data state is not expected " + std::to_string(user_header.sample_state)); } } else { ASSERT_FALSE(iceoryx_subscriber->hasData()); @@ -410,14 +435,19 @@ class SharedMemoryTest : public RouDi_GTest EXPECT_EQ(status.current_count(), 0); } - void run_loan_support_api_test(const bool valid_r_shm_qos, const bool valid_w_shm_qos) + void run_loan_support_api_test(const bool valid_r_iox_qos, const bool valid_w_iox_qos) { EXPECT_EQ(this->reader.delegate()->is_loan_supported(), - (org::eclipse::cyclonedds::topic::TopicTraits::isSelfContained() && valid_r_shm_qos)); + (org::eclipse::cyclonedds::topic::TopicTraits::isSelfContained() && valid_r_iox_qos)); EXPECT_EQ(this->flt_reader.delegate()->is_loan_supported(), - (org::eclipse::cyclonedds::topic::TopicTraits::isSelfContained() && valid_r_shm_qos)); + (org::eclipse::cyclonedds::topic::TopicTraits::isSelfContained() && valid_r_iox_qos)); EXPECT_EQ(this->writer.delegate()->is_loan_supported(), - (org::eclipse::cyclonedds::topic::TopicTraits::isSelfContained() && valid_w_shm_qos)); + (org::eclipse::cyclonedds::topic::TopicTraits::isSelfContained() && valid_w_iox_qos)); + } + + bool is_keyless() + { + return org::eclipse::cyclonedds::topic::TopicTraits::isKeyless(); } void TearDown() @@ -435,133 +465,173 @@ class SharedMemoryTest : public RouDi_GTest * Tests */ -using TestTypes = ::testing::Types; + +TEST_F(IceoryxTestType1, writer_reader_default_qos_write_cdr) +{ + // default Qos (is valid IOX qos) + dds::sub::qos::DataReaderQos r_qos{}; + dds::pub::qos::DataWriterQos w_qos{}; + constexpr bool valid_iox_qos = true; + + KeylessSpace::Type1 testData(0,1,2); + + // Serialized data via PSMX is always in native endianness +#if DDSRT_ENDIAN == DDSRT_BIG_ENDIAN + /* Write one sample (1st 0x00,0x00: CDR_BE, 2nd 0x00,0x00: no options, padding). */ + const std::array encoding{0x00, 0x00, 0x00, 0x00}; + const std::vector payloadcdr{0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x02}; +#else + /* Write one sample (1st 0x00,0x10: CDR_LE, 2nd 0x00,0x00: no options, padding). */ + const std::array encoding{0x00, 0x01, 0x00, 0x00}; + const std::vector payloadcdr{0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00, 0x02,0x00,0x00,0x00}; +#endif + org::eclipse::cyclonedds::topic::CDRBlob cdrblob{ + encoding, org::eclipse::cyclonedds::topic::BlobKind::Data, payloadcdr}; + + this->SetupCommunication(r_qos, w_qos); + this->writer->write_cdr(cdrblob); + this->WaitForData(); + auto sample = this->reader.take(); + this->CheckData(valid_iox_qos, sample, testData); +} + +using TestTypes = ::testing::Types; -TYPED_TEST_SUITE(SharedMemoryTest, TestTypes, ); +TYPED_TEST_SUITE(IceoryxTest, TestTypes, ); -TYPED_TEST(SharedMemoryTest, writer_reader_valid_shm_qos) +TYPED_TEST(IceoryxTest, writer_reader_valid_iox_qos) { - // valid SHM QoS + // valid iox QoS dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::BestEffort(); r_qos << dds::core::policy::Durability::Volatile(); r_qos << dds::core::policy::History::KeepLast(10U); - constexpr bool valid_r_shm_qos = true; + constexpr bool valid_r_iox_qos = true; - // valid SHM QoS + // valid iox QoS dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::Reliable(); w_qos << dds::core::policy::Durability::Volatile(); w_qos << dds::core::policy::History::KeepLast(10U); - constexpr bool valid_w_shm_qos = true; + constexpr bool valid_w_iox_qos = true; EXPECT_NO_THROW(this->run_communication_test(MUST_USE_ICEORYX, r_qos, w_qos, 10)); - EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_shm_qos, valid_w_shm_qos)); + EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_iox_qos, valid_w_iox_qos)); } -TYPED_TEST(SharedMemoryTest, writer_reader_default_qos) +TYPED_TEST(IceoryxTest, writer_reader_default_qos) { - // default Qos (is valid SHM qos) + // default Qos (is valid IOX qos) dds::sub::qos::DataReaderQos r_qos{}; dds::pub::qos::DataWriterQos w_qos{}; - constexpr bool valid_shm_qos = true; + constexpr bool valid_iox_qos = true; EXPECT_NO_THROW(this->run_communication_test(MUST_USE_ICEORYX, r_qos, w_qos, 1)); - EXPECT_NO_THROW(this->run_loan_support_api_test(valid_shm_qos, valid_shm_qos)); + EXPECT_NO_THROW(this->run_loan_support_api_test(valid_iox_qos, valid_iox_qos)); } -TYPED_TEST(SharedMemoryTest, writer_valid_shm_qos) +TYPED_TEST(IceoryxTest, writer_valid_iox_qos) { - // valid reader shm qos + // valid reader iox qos dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::Reliable(); - // to not enable SHM for the reader, we should use transient local, but volatile writer and + // to not enable IOX for the reader, we should use transient local, but volatile writer and // transient local reader is not a valid QoS r_qos << dds::core::policy::Durability::Volatile(); r_qos << dds::core::policy::History::KeepLast(10U); - constexpr bool valid_r_shm_qos = true; + constexpr bool valid_r_iox_qos = true; - // valid writer shm qos + // valid writer iox qos dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::Reliable(); w_qos << dds::core::policy::Durability::Volatile(); w_qos << dds::core::policy::History::KeepLast(10U); - constexpr bool valid_w_shm_qos = true; + constexpr bool valid_w_iox_qos = true; EXPECT_NO_THROW(this->run_communication_test(MUST_USE_ICEORYX, r_qos, w_qos, 10)); - EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_shm_qos, valid_w_shm_qos)); + EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_iox_qos, valid_w_iox_qos)); } -TYPED_TEST(SharedMemoryTest, reader_valid_shm_qos) +TYPED_TEST(IceoryxTest, reader_valid_iox_qos) { - // valid reader shm qos + // valid reader iox qos dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::Reliable(); r_qos << dds::core::policy::Durability::Volatile(); r_qos << dds::core::policy::History::KeepLast(10); - constexpr bool valid_r_shm_qos = true; + constexpr bool valid_r_iox_qos = true; - // invalid writer shm qos + // valid writer iox qos dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::Reliable(); w_qos << dds::core::policy::Durability::TransientLocal(); w_qos << dds::core::policy::History::KeepLast(10); - constexpr bool valid_w_shm_qos = true; - EXPECT_NO_THROW(this->run_communication_test(MUST_USE_ICEORYX, r_qos, w_qos, 10)); - EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_shm_qos, valid_w_shm_qos)); + bool valid_w_iox_qos; + bool use_iox; + if (this->is_keyless()) { + valid_w_iox_qos = true; + use_iox = MUST_USE_ICEORYX; + } else { + valid_w_iox_qos = false; + use_iox = DO_NOT_USE_ICEORYX; + } + + EXPECT_NO_THROW(this->run_communication_test(use_iox, r_qos, w_qos, 10)); + EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_iox_qos, valid_w_iox_qos)); } -TYPED_TEST(SharedMemoryTest, invalid_shm_qos) +TYPED_TEST(IceoryxTest, invalid_iox_qos) { - // invalid reader shm QoS + // invalid reader iox QoS dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::Reliable(); r_qos << dds::core::policy::Durability::Transient(); r_qos << dds::core::policy::History::KeepLast(10); - constexpr bool valid_r_shm_qos = false; + constexpr bool valid_r_iox_qos = false; - // invalid writer SHM QoS + // invalid writer iox QoS dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::Reliable(); w_qos << dds::core::policy::Durability::Transient(); w_qos << dds::core::policy::History::KeepLast(10); - constexpr bool valid_w_shm_qos = false; + constexpr bool valid_w_iox_qos = false; EXPECT_NO_THROW(this->run_communication_test(DO_NOT_USE_ICEORYX, r_qos, w_qos, 10)); - EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_shm_qos, valid_w_shm_qos)); + EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_iox_qos, valid_w_iox_qos)); } -TYPED_TEST(SharedMemoryTest, writer_invalid_shm_qos) +TYPED_TEST(IceoryxTest, writer_invalid_iox_qos) { - // valid reader shm QoS + // valid reader iox QoS dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::Reliable(); r_qos << dds::core::policy::Durability::TransientLocal(); r_qos << dds::core::policy::History::KeepLast(10); - constexpr bool valid_r_shm_qos = true; + constexpr bool valid_r_iox_qos = true; - // invalid writer SHM QoS + // invalid writer iox QoS dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::Reliable(); w_qos << dds::core::policy::Durability::Transient(); w_qos << dds::core::policy::History::KeepLast(10); - constexpr bool valid_w_shm_qos = false; + constexpr bool valid_w_iox_qos = false; EXPECT_NO_THROW(this->run_communication_test(DO_NOT_USE_ICEORYX, r_qos, w_qos, 10)); - EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_shm_qos, valid_w_shm_qos)); + EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_iox_qos, valid_w_iox_qos)); } -TYPED_TEST(SharedMemoryTest, reader_invalid_shm_qos) +TYPED_TEST(IceoryxTest, reader_invalid_iox_qos) { - // invalid reader shm QoS + // invalid reader iox QoS dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::BestEffort(); r_qos << dds::core::policy::Durability::Transient(); r_qos << dds::core::policy::History::KeepLast(10); - // valid writer SHM QoS + // valid writer iox QoS dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::BestEffort(); w_qos << dds::core::policy::Durability::TransientLocal(); @@ -570,15 +640,15 @@ TYPED_TEST(SharedMemoryTest, reader_invalid_shm_qos) EXPECT_NO_THROW(this->expect_no_communication(r_qos, w_qos)); } -TYPED_TEST(SharedMemoryTest, reliable_reader_does_not_match_best_effort_writer) +TYPED_TEST(IceoryxTest, reliable_reader_does_not_match_best_effort_writer) { - // valid reader shm QoS + // valid reader iox QoS dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::Reliable(); r_qos << dds::core::policy::Durability::TransientLocal(); r_qos << dds::core::policy::History::KeepLast(10); - // valid writer SHM QoS + // valid writer iox QoS dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::BestEffort(); w_qos << dds::core::policy::Durability::TransientLocal(); @@ -587,75 +657,75 @@ TYPED_TEST(SharedMemoryTest, reliable_reader_does_not_match_best_effort_writer) this->expect_no_communication(r_qos, w_qos); } -TYPED_TEST(SharedMemoryTest, best_effort_reader_receives_data_from_reliable_writer_via_shm) +TYPED_TEST(IceoryxTest, best_effort_reader_receives_data_from_reliable_writer_via_iox) { dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::BestEffort(); - r_qos << dds::core::policy::Durability::TransientLocal(); + r_qos << dds::core::policy::Durability::Volatile(); r_qos << dds::core::policy::History::KeepLast(10); - constexpr bool valid_r_shm_qos = true; + constexpr bool valid_r_iox_qos = true; dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::Reliable(); - w_qos << dds::core::policy::Durability::TransientLocal(); + w_qos << dds::core::policy::Durability::Volatile(); w_qos << dds::core::policy::History::KeepLast(10); - constexpr bool valid_w_shm_qos = true; + constexpr bool valid_w_iox_qos = true; this->SetDurabilityServiceHistory(10); EXPECT_NO_THROW(this->run_communication_test(MUST_USE_ICEORYX, r_qos, w_qos, 10)); - EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_shm_qos, valid_w_shm_qos)); + EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_iox_qos, valid_w_iox_qos)); } -TYPED_TEST(SharedMemoryTest, tl_reader_with_lower_history_depth_receives_data_via_shm) +TYPED_TEST(IceoryxTest, tl_reader_with_lower_history_depth_receives_data_via_iox) { dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::Reliable(); - r_qos << dds::core::policy::Durability::TransientLocal(); + r_qos << dds::core::policy::Durability::Volatile(); r_qos << dds::core::policy::History::KeepLast(10U); - constexpr bool valid_r_shm_qos = true; + constexpr bool valid_r_iox_qos = true; dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::Reliable(); - w_qos << dds::core::policy::Durability::TransientLocal(); + w_qos << dds::core::policy::Durability::Volatile(); w_qos << dds::core::policy::History::KeepLast(11); - constexpr bool valid_w_shm_qos = true; + constexpr bool valid_w_iox_qos = true; this->SetDurabilityServiceHistory(11); EXPECT_NO_THROW(this->run_communication_test(MUST_USE_ICEORYX, r_qos, w_qos, 10)); - EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_shm_qos, valid_w_shm_qos)); + EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_iox_qos, valid_w_iox_qos)); } -TYPED_TEST(SharedMemoryTest, tl_reader_with_larger_history_depth_receives_data_via_shm) +TYPED_TEST(IceoryxTest, tl_reader_with_larger_history_depth_receives_data_via_iox) { dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::Reliable(); - r_qos << dds::core::policy::Durability::TransientLocal(); + r_qos << dds::core::policy::Durability::Volatile(); r_qos << dds::core::policy::History::KeepLast(10); - constexpr bool valid_r_shm_qos = true; + constexpr bool valid_r_iox_qos = true; dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::Reliable(); - w_qos << dds::core::policy::Durability::TransientLocal(); + w_qos << dds::core::policy::Durability::Volatile(); w_qos << dds::core::policy::History::KeepLast(9); - constexpr bool valid_w_shm_qos = true; + constexpr bool valid_w_iox_qos = true; this->SetDurabilityServiceHistory(9); EXPECT_NO_THROW(this->run_communication_test(MUST_USE_ICEORYX, r_qos, w_qos, 10)); - EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_shm_qos, valid_w_shm_qos)); + EXPECT_NO_THROW(this->run_loan_support_api_test(valid_r_iox_qos, valid_w_iox_qos)); } -TYPED_TEST(SharedMemoryTest, tl_reader_does_not_match_volatile_writer) +TYPED_TEST(IceoryxTest, tl_reader_does_not_match_volatile_writer) { - // valid reader shm QoS + // valid reader iox QoS dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::Reliable(); r_qos << dds::core::policy::Durability::TransientLocal(); r_qos << dds::core::policy::History::KeepLast(10); - // valid writer SHM QoS + // valid writer iox QoS dds::pub::qos::DataWriterQos w_qos; w_qos << dds::core::policy::Reliability::Reliable(); w_qos << dds::core::policy::Durability::Volatile(); @@ -664,7 +734,7 @@ TYPED_TEST(SharedMemoryTest, tl_reader_does_not_match_volatile_writer) this->expect_no_communication(r_qos, w_qos); } -TYPED_TEST(SharedMemoryTest, loan_sample) +TYPED_TEST(IceoryxTest, loan_sample) { dds::sub::qos::DataReaderQos r_qos; r_qos << dds::core::policy::Reliability::Reliable(); @@ -677,26 +747,15 @@ TYPED_TEST(SharedMemoryTest, loan_sample) w_qos << dds::core::policy::History::KeepLast(10); this->SetupCommunication(r_qos, w_qos); - using DDSType = typename TestFixture::TopicType; - // request loan (supported only for fixed-size self-contained types) - if (org::eclipse::cyclonedds::topic::TopicTraits::isSelfContained()) { - try { - auto & loaned_sample = this->writer.delegate()->loan_sample(); - - // return the loan back without publishing - this->writer.delegate()->return_loan(loaned_sample); - } catch (...) { - // should never execute this - EXPECT_TRUE(false); - } - } else { // when loaning is not supported - EXPECT_THROW_EXCEPTION(this->writer.delegate()->loan_sample(), - "Error Unsupported - sample loan failed."); - - // illegal loan - DDSType sample; - EXPECT_THROW_EXCEPTION( - this->writer.delegate()->return_loan(sample), - "Error Unsupported - return of sample loan failed."); + + // request loan (psmx loan for memcpy-safe data types, otherwise a heap loan) + try { + auto & loaned_sample = this->writer.delegate()->loan_sample(); + + // return the loan back without publishing + this->writer.delegate()->return_loan(loaned_sample); + } catch (...) { + // should never execute this + EXPECT_TRUE(false); } } diff --git a/src/ddscxx/tests/Qos.cpp b/src/ddscxx/tests/Qos.cpp index 627cd62e..5475788b 100644 --- a/src/ddscxx/tests/Qos.cpp +++ b/src/ddscxx/tests/Qos.cpp @@ -71,6 +71,7 @@ DataRepresentation nonDefaultRepresentation({dds::core::policy::DataRepresen TypeConsistencyEnforcement nonDefaultTypeConsistencyEnforcement(dds::core::policy::TypeConsistencyKind::ALLOW_TYPE_COERCION, true, true, true, true, true); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT WriterBatching nonDefaultWriterBatching(true); +PSMXInstances nonDefaultPSMXInstances({"some_psmx_name"}); @@ -108,6 +109,7 @@ DataRepresentation tmpRepresentation; TypeConsistencyEnforcement tmpEnforcement; #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT WriterBatching tmpWriterBatching; +PSMXInstances tmpPSMXInstances; TEST(Qos, DomainParticipant) { @@ -359,6 +361,7 @@ TEST(Qos, DataWriter) << nonDefaultTypeConsistencyEnforcement #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT << nonDefaultWriterBatching + << nonDefaultPSMXInstances ; DataWriterQos dwQosWConstructed(dwQosShifted); DataWriterQos dwQosWAssigned1 = dwQosShifted; /* Actually calls copy constructor. */ @@ -407,6 +410,7 @@ TEST(Qos, DataWriter) dwQosShifted >> tmpEnforcement; #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT dwQosShifted >> tmpWriterBatching; + dwQosShifted >> tmpPSMXInstances; ASSERT_EQ(nonDefaultUserData, tmpUserData); ASSERT_EQ(nonDefaultDurability, tmpDurability); #ifdef OMG_DDS_PERSISTENCE_SUPPORT @@ -428,6 +432,7 @@ TEST(Qos, DataWriter) ASSERT_EQ(nonDefaultTypeConsistencyEnforcement, tmpEnforcement); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT ASSERT_EQ(nonDefaultWriterBatching, tmpWriterBatching); + ASSERT_EQ(nonDefaultPSMXInstances, tmpPSMXInstances); ASSERT_EQ(nonDefaultUserData, dwQosWConstructed.policy()); ASSERT_EQ(nonDefaultDurability, dwQosWConstructed.policy()); @@ -450,6 +455,7 @@ TEST(Qos, DataWriter) ASSERT_EQ(nonDefaultTypeConsistencyEnforcement, dwQosWConstructed.policy()); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT ASSERT_EQ(nonDefaultWriterBatching, dwQosWConstructed.policy()); + ASSERT_EQ(nonDefaultPSMXInstances, dwQosWConstructed.policy()); #ifdef OMG_DDS_OWNERSHIP_SUPPORT dwQosShifted >> tmpStrength; @@ -502,6 +508,7 @@ TEST(Qos, DataReader) << nonDefaultRepresentation << nonDefaultTypeConsistencyEnforcement #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + << nonDefaultPSMXInstances ; DataReaderQos drQosRConstructed(drQosShifted); DataReaderQos drQosRAssigned1 = drQosShifted; /* Actually calls copy constructor. */ @@ -542,6 +549,7 @@ TEST(Qos, DataReader) drQosShifted >> tmpRepresentation; drQosShifted >> tmpEnforcement; #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + drQosShifted >> tmpPSMXInstances; ASSERT_EQ(nonDefaultUserData, tmpUserData); ASSERT_EQ(nonDefaultDurability, tmpDurability); ASSERT_EQ(nonDefaultDeadline, tmpDeadline); @@ -558,6 +566,7 @@ TEST(Qos, DataReader) ASSERT_EQ(nonDefaultRepresentation, tmpRepresentation); ASSERT_EQ(nonDefaultTypeConsistencyEnforcement, tmpEnforcement); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + ASSERT_EQ(nonDefaultPSMXInstances, tmpPSMXInstances); ASSERT_EQ(nonDefaultUserData, drQosRConstructed.policy()); ASSERT_EQ(nonDefaultDurability, drQosRConstructed.policy()); @@ -575,12 +584,14 @@ TEST(Qos, DataReader) ASSERT_EQ(nonDefaultRepresentation, drQosRConstructed.policy()); ASSERT_EQ(nonDefaultTypeConsistencyEnforcement, drQosRConstructed.policy()); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT + ASSERT_EQ(nonDefaultPSMXInstances, drQosRConstructed.policy()); } TEST(Qos, invalid_values) { History invalidHistory; ResourceLimits invalidResources; + PSMXInstances invalidPSMXInstances; ASSERT_THROW({ invalidHistory = History(dds::core::policy::HistoryKind::KEEP_LAST, @@ -592,6 +603,10 @@ TEST(Qos, invalid_values) 0, /* max_instances */ 0 /* max_samples_per_instance */); }, dds::core::InvalidArgumentError); + + ASSERT_THROW({ + invalidPSMXInstances = PSMXInstances({"instance_1", "instance_2"}); + }, dds::core::InvalidArgumentError); } TEST(Qos, invalid_policies) @@ -667,4 +682,5 @@ TEST(Qos, policy_name) ASSERT_EQ(dds::core::policy::policy_name::name(), "TypeConsistencyEnforcement"); #endif // OMG_DDS_EXTENSIBLE_AND_DYNAMIC_TOPIC_TYPE_SUPPORT ASSERT_EQ(dds::core::policy::policy_name::name(), "WriterBatching"); + ASSERT_EQ(dds::core::policy::policy_name::name(), "PSMXInstances"); } diff --git a/src/ddscxx/tests/Serdata.cpp b/src/ddscxx/tests/Serdata.cpp index 8ae0e50e..d4a6271a 100644 --- a/src/ddscxx/tests/Serdata.cpp +++ b/src/ddscxx/tests/Serdata.cpp @@ -37,7 +37,7 @@ class Serdata : public ::testing::Test sd->resize(12); ptr = static_cast(sd->data()); - + memset(ptr, 0, DDSI_RTPS_HEADER_SIZE); ptr[4] = 0x10; ptr[5] = 0x19; ptr[6] = 0x24; diff --git a/src/ddscxx/tests/data/KeylessSpace.idl b/src/ddscxx/tests/data/KeylessSpace.idl new file mode 100644 index 00000000..d50943fb --- /dev/null +++ b/src/ddscxx/tests/data/KeylessSpace.idl @@ -0,0 +1,22 @@ + +module KeylessSpace { + enum Enumeration + { + VALUE1, + VALUE2 + }; + + struct Type1 { + long long_1; + long long_2; + long long_3; + }; + + struct Type2 { + long long_1; + long long_2; + long long_3; + Enumeration enum_1; + }; +}; + diff --git a/src/idlcxx/src/traits.c b/src/idlcxx/src/traits.c index 3d318a99..4eb41990 100644 --- a/src/idlcxx/src/traits.c +++ b/src/idlcxx/src/traits.c @@ -132,13 +132,13 @@ emit_traits( "template<> constexpr unsigned int TopicTraits<%1$s>::type_map_blob_sz() { return %2$u; }\n" "template<> constexpr unsigned int TopicTraits<%1$s>::type_info_blob_sz() { return %3$u; }\n" "template<> inline const uint8_t * TopicTraits<%1$s>::type_map_blob() {\n" - " static const uint8_t blob[] = {\n"; + " alignas(4) static const uint8_t blob[] = {\n"; static const char *type_info_decl2 = "};\n" " return blob;\n" "}\n" "template<> inline const uint8_t * TopicTraits<%1$s>::type_info_blob() {\n" - " static const uint8_t blob[] = {\n"; + " alignas(4) static const uint8_t blob[] = {\n"; static const char *type_info_decl3 = "};\n" " return blob;\n"