Multithread and shared memory (#216)

* Initial


Update


Revert "Initial"

This reverts commit bbef97f3599786be2febc15f8e8b474a4006234d.

Initial


Update


Update


Initial


Update


Revert example


Uncrustify fix


Add include


Fix header


Fix headers


Fix


Uncrus


Update to const char


Update


Update


Revert "Update"

This reverts commit 3a05e402e5.

Update


Multithread initial


Interprocess initial


Matching initial


Fix interprocess indexing


Update multithread public API


Initial DLL


Double linked list for ucdrBuffers


renaming


Update


Update


Indent


Deinit


Add shared memory tests (#221)

* Initial

* Update

* Update

* Update

* Update

* Fix leak
Update on request reply shared mem

Initial changes req/res


Update


Initial simple API


Working


Renaming


Fix example pthread header

Create shared memory profile folder


Fix warning


Fix warnings


Fix warnings


Multithread test


Update


Add tests


Style


Uncrustify


Uncrustify examples


Fix


Update


Fix


Add test multithread request reply

Update SharedMemory.cpp

Fix build warning
Include requester info on reply SampleIdentity info

Uncrustify

Fix warnings

Add request reply fragmentation test

Update


Update shared memory engine to bin


Update


Uncrustify


Fix

* Remove examples

* Fix naming

* Uncrus
This commit is contained in:
Pablo Garrido 2021-04-30 12:03:19 +02:00 committed by GitHub
parent 206e7bf1b3
commit 527b4dd2f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 2430 additions and 19 deletions

View File

@ -62,6 +62,12 @@ set(UCLIENT_SERIAL_TRANSPORT_MTU 512 CACHE STRING "Set the Serial transport MTU.
option(UCLIENT_PROFILE_CUSTOM_TRANSPORT "Enable Custom transport." ON)
set(UCLIENT_CUSTOM_TRANSPORT_MTU 512 CACHE STRING "Set the Custom transport MTU.")
option(UCLIENT_PROFILE_MULTITHREAD "Enable multithread support." OFF)
option(UCLIENT_PROFILE_SHARED_MEMORY "Enable shared memory transport support." OFF)
option(UCLIENT_PROFILE_MATCHING "Enable QoS matching support." OFF)
set(UCLIENT_SHARED_MEMORY_MAX_ENTITIES 4 CACHE STRING "Max number of entities involved in shared memory.")
set(UCLIENT_SHARED_MEMORY_STATIC_MEM_SIZE 10 CACHE STRING "Max number data buffers stored in shared memory")
###############################################################################
# Dependencies
###############################################################################
@ -215,6 +221,14 @@ if(UCLIENT_PROFILE_CUSTOM_TRANSPORT)
list(APPEND _transport_src src/c/profile/transport/custom/custom_transport.c)
endif()
if(UCLIENT_PROFILE_MULTITHREAD)
set(UCLIENT_PROFILE_SHARED_MEMORY ON)
endif()
if(UCLIENT_PROFILE_SHARED_MEMORY)
set(UCLIENT_PROFILE_MATCHING ON)
endif()
# Other sources
set(SRCS
src/c/core/session/stream/input_best_effort_stream.c
@ -239,6 +253,9 @@ set(SRCS
src/c/core/session/create_entities_bin.c
src/c/core/session/read_access.c
src/c/core/session/write_access.c
$<$<BOOL:${UCLIENT_PROFILE_MULTITHREAD}>:src/c/profile/multithread/multithread.c>
$<$<BOOL:${UCLIENT_PROFILE_SHARED_MEMORY}>:src/c/profile/shared_memory/shared_memory.c>
$<$<BOOL:${UCLIENT_PROFILE_MATCHING}>:src/c/profile/matching/matching.c>
$<$<BOOL:${UCLIENT_PROFILE_STREAM_FRAMING}>:src/c/profile/transport/stream_framing/stream_framing_protocol.c>
$<$<OR:$<BOOL:${UCLIENT_VERBOSE_MESSAGE}>,$<BOOL:${UCLIENT_VERBOSE_SERIALIZATION}>>:src/c/core/log/log.c>
${_transport_src}
@ -308,12 +325,17 @@ if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND (UCLIENT_TARGET_TYPE STREQUAL "SHA
)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_package(Threads REQUIRED)
endif()
target_link_libraries(${PROJECT_NAME}
PUBLIC
microcdr
$<$<BOOL:$<PLATFORM_ID:Windows>>:ws2_32>
PRIVATE
$<$<BOOL:$<PLATFORM_ID:Linux>>:rt>
$<$<BOOL:$<PLATFORM_ID:Linux>>:${CMAKE_THREAD_LIBS_INIT}>
)
target_include_directories(${PROJECT_NAME}
PUBLIC
@ -367,6 +389,7 @@ if(UCLIENT_BUILD_EXAMPLES)
add_subdirectory(examples/ContinuousFragment)
add_subdirectory(examples/PublishHelloWorldBestEffort)
add_subdirectory(examples/SubscribeHelloWorldBestEffort)
if(UCLIENT_PLATFORM_LINUX)
add_subdirectory(examples/CustomTransports)
endif()
@ -392,6 +415,7 @@ if(UCLIENT_BUILD_TESTS)
if(UCLIENT_PLATFORM_LINUX)
add_subdirectory(test/transport/custom_comm)
add_subdirectory(test/transport/serial_comm)
add_subdirectory(test/shared_memory)
endif()
endif()

View File

@ -29,5 +29,6 @@
#include <uxr/client/core/session/create_entities_bin.h>
#include <uxr/client/transport.h>
#include <uxr/client/profile/multithread/multithread.h>
#endif // _UXR_CLIENT_CLIENT_H_

View File

@ -26,6 +26,8 @@
#cmakedefine UCLIENT_PROFILE_TCP
#cmakedefine UCLIENT_PROFILE_SERIAL
#cmakedefine UCLIENT_PROFILE_CUSTOM_TRANSPORT
#cmakedefine UCLIENT_PROFILE_MULTITHREAD
#cmakedefine UCLIENT_PROFILE_SHARED_MEMORY
#cmakedefine UCLIENT_PLATFORM_POSIX
#cmakedefine UCLIENT_PLATFORM_POSIX_NOPOLL
@ -56,7 +58,12 @@
#define UXR_CONFIG_SERIAL_TRANSPORT_MTU @UCLIENT_SERIAL_TRANSPORT_MTU@
#endif
#ifdef UCLIENT_PROFILE_CUSTOM_TRANSPORT
#define UXR_CONFIG_CUSTOM_TRANSPORT_MTU @UCLIENT_CUSTOM_TRANSPORT_MTU@
#define UXR_CONFIG_CUSTOM_TRANSPORT_MTU @UCLIENT_CUSTOM_TRANSPORT_MTU@
#endif
#ifdef UCLIENT_PROFILE_SHARED_MEMORY
#define UXR_CONFIG_SHARED_MEMORY_MAX_ENTITIES @UCLIENT_SHARED_MEMORY_MAX_ENTITIES@
#define UXR_CONFIG_SHARED_MEMORY_STATIC_MEM_SIZE @UCLIENT_SHARED_MEMORY_STATIC_MEM_SIZE@
#endif
#endif // _UXR_CLIENT_CONFIG_H_

View File

@ -80,9 +80,6 @@ UXRDLLAPI uint16_t uxr_buffer_create_topic_bin(
* As a result of the reception of this submessage, the Agent will create an XRCE Publisher according to
* the binary provided in the CREATE submessage.
* @param session A uxrSession structure previously initialized.
* @param stream_id The output stream identifier where the CREATE submessage will be buffered.
* @param object_id The identifier of the XRCE Publisher.
* @param participant_id The identifier of the associated XRCE Participant.
* @param mode The set of flags that determines the entity creation mode.
* The Creation Mode Table describes the entities creation behaviour according to the
* `UXR_REUSE` and `UXR_REPLACE` flags.

View File

@ -24,10 +24,15 @@ extern "C"
{
#endif // ifdef __cplusplus
#include <uxr/client/config.h>
#include <uxr/client/core/session/session_info.h>
#include <uxr/client/core/session/stream/stream_storage.h>
#include <uxr/client/core/type/xrce_types.h>
#ifdef UCLIENT_PROFILE_MULTITHREAD
#include <uxr/client/profile/multithread/multithread.h>
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
#define UXR_TIMEOUT_INF -1
struct uxrSession;
@ -188,6 +193,10 @@ typedef struct uxrSession
bool on_data_flag;
uxrContinuousArgs continuous_args;
#ifdef UCLIENT_PROFILE_MULTITHREAD
uxrMutex mutex;
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
#ifdef PERFORMANCE_TESTING
uxrOnPerformanceFunc on_performance;
void* on_performance_args;

View File

@ -20,8 +20,13 @@ extern "C"
{
#endif // ifdef __cplusplus
#include <uxr/client/config.h>
#include <uxr/client/core/session/stream/seq_num.h>
#ifdef UCLIENT_PROFILE_MULTITHREAD
#include <uxr/client/profile/multithread/multithread.h>
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
#include <stdint.h>
#include <stdbool.h>
@ -29,6 +34,10 @@ typedef struct uxrInputBestEffortStream
{
uxrSeqNum last_handled;
#ifdef UCLIENT_PROFILE_MULTITHREAD
uxrMutex mutex;
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
} uxrInputBestEffortStream;
#ifdef __cplusplus

View File

@ -20,9 +20,14 @@ extern "C"
{
#endif // ifdef __cplusplus
#include <uxr/client/config.h>
#include <uxr/client/core/session/stream/reliable_stream.h>
#include <uxr/client/core/session/stream/seq_num.h>
#ifdef UCLIENT_PROFILE_MULTITHREAD
#include <uxr/client/profile/multithread/multithread.h>
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
#include <stdbool.h>
struct ucdrBuffer;
@ -49,6 +54,10 @@ typedef struct uxrInputReliableStream
bool cleanup_flag;
#ifdef UCLIENT_PROFILE_MULTITHREAD
uxrMutex mutex;
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
} uxrInputReliableStream;
#ifdef __cplusplus

View File

@ -20,8 +20,13 @@ extern "C"
{
#endif // ifdef __cplusplus
#include <uxr/client/config.h>
#include <uxr/client/core/session/stream/seq_num.h>
#ifdef UCLIENT_PROFILE_MULTITHREAD
#include <uxr/client/profile/multithread/multithread.h>
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
#include <stddef.h>
#include <stdbool.h>
@ -35,6 +40,10 @@ typedef struct uxrOutputBestEffortStream
uxrSeqNum last_send;
#ifdef UCLIENT_PROFILE_MULTITHREAD
uxrMutex mutex;
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
} uxrOutputBestEffortStream;
#ifdef __cplusplus

View File

@ -20,9 +20,14 @@ extern "C"
{
#endif // ifdef __cplusplus
#include <uxr/client/config.h>
#include <uxr/client/core/session/stream/reliable_stream.h>
#include <uxr/client/core/session/stream/seq_num.h>
#ifdef UCLIENT_PROFILE_MULTITHREAD
#include <uxr/client/profile/multithread/multithread.h>
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
#include <stdbool.h>
struct ucdrBuffer;
@ -45,6 +50,10 @@ typedef struct uxrOutputReliableStream
uint8_t next_heartbeat_tries;
bool send_lost;
#ifdef UCLIENT_PROFILE_MULTITHREAD
uxrMutex mutex;
#endif // ifdef UCLIENT_PROFILE_MULTITHREAD
} uxrOutputReliableStream;
#ifdef __cplusplus

View File

@ -53,7 +53,9 @@ typedef enum uxrStreamType
/** Identifies a best-effort stream. */
UXR_BEST_EFFORT_STREAM,
/** Identifies a reliable stream. */
UXR_RELIABLE_STREAM
UXR_RELIABLE_STREAM,
/** Identifies a shared memory stream. */
UXR_SHARED_MEMORY_STREAM
} uxrStreamType;

View File

@ -97,9 +97,9 @@ uint16_t uxr_buffer_topic(
* As a result of the reception of this submessage, the Agent will write a topic into the DDS Global-Data-Space.
* @param session A uxrSession structure previously initialized.
* @param stream_id The output stream identifier where the WRITE_DATA submessage will be buffered.
* @param entity_id The identifier of the XRCE DataWriter that will write the topic into the DDS GDS.
* @param ub_topic The ucdrBuffer structure used for serializing the topic.
* @param topic_size The size of the topic in bytes.
* @param entity_id The identifier of the XRCE DataWriter that will write the topic into the DDS GDS.
* @param ub The ucdrBuffer structure used for serializing the topic.
* @param len The size of the topic in bytes.
* @return A `request_id` that identifies the XRCE request made by the Entity.
* This could be used in the `uxr_run_session_until_one_status` or `uxr_run_session_until_all_status` functions.
* */
@ -107,8 +107,8 @@ UXRDLLAPI uint16_t uxr_prepare_output_stream(
uxrSession* session,
uxrStreamId stream_id,
uxrObjectId entity_id,
struct ucdrBuffer* ub_topic,
uint32_t topic_size);
struct ucdrBuffer* ub,
uint32_t len);
/**
@ -120,7 +120,7 @@ UXRDLLAPI uint16_t uxr_prepare_output_stream(
* @param stream_id The output stream identifier where the WRITE_DATA submessage will be buffered.
* @param datawriter_id The identifier of the XRCE DataWriter that will write the topic into the DDS GDS.
* @param ub The ucdrBuffer structure used for serializing the topic.
* @param topic_size The size of the topic in bytes.
* @param data_size The size of the topic in bytes.
* @param flush_callback Callback that is call by the library when user should flush output buffers.
* @return A `request_id` that identifies the XRCE request made by the Entity.
* This could be used in the `uxr_run_session_until_one_status` or `uxr_run_session_until_all_status` functions.
@ -131,7 +131,7 @@ UXRDLLAPI uint16_t uxr_prepare_output_stream_fragmented(
uxrStreamId stream_id,
uxrObjectId datawriter_id,
ucdrBuffer* ub,
size_t topic_size,
size_t data_size,
uxrOnBuffersFull flush_callback);
/** @}*/

View File

@ -0,0 +1,135 @@
// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef UXR_CLIENT_PROFILE_MULTITHREAD_H_
#define UXR_CLIENT_PROFILE_MULTITHREAD_H_
#ifdef __cplusplus
extern "C"
{
#endif // ifdef __cplusplus
#include <uxr/client/config.h>
#include <uxr/client/visibility.h>
#include <uxr/client/core/session/stream/stream_id.h>
struct uxrSession;
#ifdef UCLIENT_PROFILE_MULTITHREAD
#ifdef WIN32
#elif defined(PLATFORM_NAME_FREERTOS)
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#elif defined(UCLIENT_PLATFORM_ZEPHYR)
#elif defined(UCLIENT_PLATFORM_POSIX)
#include <pthread.h>
#endif // ifdef WIN32
// Micro XRCE-DDS Client mutex implementation
typedef struct uxrMutex
{
#ifdef WIN32
#elif defined(PLATFORM_NAME_FREERTOS)
SemaphoreHandle_t impl;
StaticSemaphore_t xMutexBuffer;
#elif defined(UCLIENT_PLATFORM_ZEPHYR)
struct k_mutex impl;
#elif defined(UCLIENT_PLATFORM_POSIX)
pthread_mutex_t impl;
#endif // ifdef WIN32
} uxrMutex;
/**
* @brief
* TODO
*/
UXRDLLAPI uxrMutex* uxr_get_stream_mutex_from_id(
struct uxrSession* session,
uxrStreamId stream_id);
/**
* @brief
* TODO
*/
UXRDLLAPI void uxr_init_lock(
uxrMutex* mutex);
/**
* @brief
* TODO
*/
UXRDLLAPI void uxr_lock(
uxrMutex* mutex);
/**
* @brief
* TODO
*/
UXRDLLAPI void uxr_unlock(
uxrMutex* mutex);
// Conditional defines
#define UXR_INIT_LOCK(X) uxr_init_lock(X)
#define UXR_LOCK(X) uxr_lock(X)
#define UXR_UNLOCK(X) uxr_unlock(X)
#define UXR_INIT_LOCK_SESSION uxr_init_lock(&session->mutex)
#define UXR_LOCK_SESSION(session) uxr_lock(&session->mutex)
#define UXR_UNLOCK_SESSION(session) uxr_unlock(&session->mutex)
#define UXR_LOCK_STREAM_ID(session, stream_id) uxr_lock(uxr_get_stream_mutex_from_id(session, stream_id))
#define UXR_UNLOCK_STREAM_ID(session, stream_id) uxr_unlock(uxr_get_stream_mutex_from_id(session, stream_id))
#define UXR_LOCK_ALL_INPUT_STREAMS(session) \
for (uint8_t i = 0; i < session->streams.input_best_effort_size; \
++i){ uxr_lock(&session->streams.input_best_effort[i].mutex); } \
for (uint8_t i = 0; i < session->streams.input_reliable_size; ++i){ uxr_lock( \
&session->streams.input_reliable[i].mutex); \
}
#define UXR_UNLOCK_ALL_INPUT_STREAMS(session) \
for (uint8_t i = 0; i < session->streams.input_best_effort_size; ++i){ uxr_unlock( \
&session->streams.input_best_effort[i].mutex); \
} \
for (uint8_t i = 0; i < session->streams.input_reliable_size; ++i){ uxr_unlock( \
&session->streams.input_reliable[i].mutex); \
}
#else // UCLIENT_PROFILE_MULTITHREAD
#define UXR_INIT_LOCK(X)
#define UXR_LOCK(X)
#define UXR_UNLOCK(X)
#define UXR_INIT_LOCK_SESSION
#define UXR_LOCK_SESSION(session)
#define UXR_UNLOCK_SESSION(session)
#define UXR_LOCK_STREAM_ID(session, stream_id)
#define UXR_UNLOCK_STREAM_ID(session, stream_id)
#define UXR_LOCK_ALL_INPUT_STREAMS(session)
#define UXR_UNLOCK_ALL_INPUT_STREAMS(session)
#endif // UCLIENT_PROFILE_MULTITHREAD
#ifdef __cplusplus
}
#endif // ifdef __cplusplus
#endif // UXR_CLIENT_PROFILE_MULTITHREAD_H_

View File

@ -4,6 +4,7 @@
#include "session_internal.h"
#include "session_info_internal.h"
#include "submessage_internal.h"
#include <uxr/client/profile/multithread/multithread.h>
//==================================================================
// PUBLIC
@ -22,12 +23,17 @@ uint16_t uxr_buffer_delete_entity(
payload_length = (uint16_t)(payload_length + 4); // delete payload (request id + object_id), no padding.
ucdrBuffer ub;
UXR_LOCK_STREAM_ID(session, stream_id);
if (uxr_prepare_stream_to_write_submessage(session, stream_id, payload_length, &ub, SUBMESSAGE_ID_DELETE, 0))
{
request_id = uxr_init_base_object_request(&session->info, object_id, &payload.base);
(void) uxr_serialize_DELETE_Payload(&ub, &payload);
}
UXR_UNLOCK_STREAM_ID(session, stream_id);
return request_id;
}
@ -55,11 +61,16 @@ uint16_t uxr_common_create_entity(
payload_length = (uint16_t)(payload_length + 2); //object id ref
ucdrBuffer ub;
UXR_LOCK_STREAM_ID(session, stream_id);
if (uxr_prepare_stream_to_write_submessage(session, stream_id, payload_length, &ub, SUBMESSAGE_ID_CREATE, mode))
{
request_id = uxr_init_base_object_request(&session->info, object_id, &payload->base);
(void) uxr_serialize_CREATE_Payload(&ub, payload);
}
UXR_UNLOCK_STREAM_ID(session, stream_id);
return request_id;
}

View File

@ -1,6 +1,7 @@
#include <uxr/client/core/type/xrce_types.h>
#include "common_create_entities_internal.h"
#include "../../profile/shared_memory/shared_memory_internal.h"
#include <string.h>
@ -58,6 +59,8 @@ uint16_t uxr_buffer_create_topic_bin(
uxr_serialize_OBJK_Topic_Binary(&ub, &topic);
payload.object_representation._.topic.base.representation._.binary_representation.size = (uint32_t) ub.offset;
UXR_ADD_SHARED_MEMORY_ENTITY_BIN(session, object_id, &topic);
return uxr_common_create_entity(session, stream_id, object_id, (uint16_t) ub.offset, mode, &payload);
}
@ -150,6 +153,8 @@ uint16_t uxr_buffer_create_datawriter_bin(
datawriter.qos.base.qos_flags |= is_durability_transient_local;
}
UXR_ADD_SHARED_MEMORY_ENTITY_BIN(session, object_id, &datawriter);
ucdrBuffer ub;
ucdr_init_buffer(&ub, payload.object_representation._.data_writer.base.representation._.binary_representation.data,
UXR_BINARY_SEQUENCE_MAX);
@ -199,6 +204,8 @@ uint16_t uxr_buffer_create_datareader_bin(
datareader.qos.base.qos_flags |= is_durability_transient_local;
}
UXR_ADD_SHARED_MEMORY_ENTITY_BIN(session, object_id, &datareader);
ucdrBuffer ub;
ucdr_init_buffer(&ub, payload.object_representation._.data_reader.base.representation._.binary_representation.data,
UXR_BINARY_SEQUENCE_MAX);
@ -234,6 +241,8 @@ uint16_t uxr_buffer_create_requester_bin(
requester.optional_request_topic_name = true;
requester.request_topic_name = (char*) request_topic_name;
UXR_ADD_SHARED_MEMORY_ENTITY_BIN(session, object_id, &requester);
ucdrBuffer ub;
ucdr_init_buffer(&ub, payload.object_representation._.requester.base.representation._.binary_representation.data,
UXR_BINARY_SEQUENCE_MAX);
@ -269,6 +278,8 @@ uint16_t uxr_buffer_create_replier_bin(
replier.optional_request_topic_name = true;
replier.request_topic_name = (char*) request_topic_name;
UXR_ADD_SHARED_MEMORY_ENTITY_BIN(session, object_id, &replier);
ucdrBuffer ub;
ucdr_init_buffer(&ub, payload.object_representation._.replier.base.representation._.binary_representation.data,
UXR_BINARY_SEQUENCE_MAX);

View File

@ -2,6 +2,7 @@
#include <uxr/client/core/type/xrce_types.h>
#include "common_create_entities_internal.h"
#include "../../profile/shared_memory/shared_memory_internal.h"
#include <string.h>
@ -94,6 +95,8 @@ uint16_t uxr_buffer_create_datawriter_xml(
{
//assert with the object_id type
UXR_ADD_SHARED_MEMORY_ENTITY_XML(session, object_id, xml);
CREATE_Payload payload;
payload.object_representation.kind = DDS_XRCE_OBJK_DATAWRITER;
uxr_object_id_to_raw(publisher_id, payload.object_representation._.data_writer.publisher_id.data);
@ -111,6 +114,8 @@ uint16_t uxr_buffer_create_datareader_xml(
{
//assert with the object_id type
UXR_ADD_SHARED_MEMORY_ENTITY_XML(session, object_id, xml);
CREATE_Payload payload;
payload.object_representation.kind = DDS_XRCE_OBJK_DATAREADER;
uxr_object_id_to_raw(subscriber_id, payload.object_representation._.data_reader.subscriber_id.data);
@ -126,6 +131,8 @@ uint16_t uxr_buffer_create_requester_xml(
const char* xml,
uint8_t mode)
{
UXR_ADD_SHARED_MEMORY_ENTITY_XML(session, object_id, xml);
CREATE_Payload payload;
payload.object_representation.kind = DDS_XRCE_OBJK_REQUESTER;
uxr_object_id_to_raw(participant_id, payload.object_representation._.requester.participant_id.data);
@ -141,6 +148,8 @@ uint16_t uxr_buffer_create_replier_xml(
const char* xml,
uint8_t mode)
{
UXR_ADD_SHARED_MEMORY_ENTITY_XML(session, object_id, xml);
CREATE_Payload payload;
payload.object_representation.kind = DDS_XRCE_OBJK_REPLIER;
uxr_object_id_to_raw(participant_id, payload.object_representation._.replier.participant_id.data);

View File

@ -4,6 +4,7 @@
#include "session_internal.h"
#include "session_info_internal.h"
#include "submessage_internal.h"
#include <uxr/client/profile/multithread/multithread.h>
extern void read_submessage_format(
uxrSession* session,
@ -87,12 +88,17 @@ uint16_t uxr_buffer_request_data(
payload_length += (control != NULL) ? 8 : 0; // delivery control
ucdrBuffer ub;
UXR_LOCK_STREAM_ID(session, stream_id);
if (uxr_prepare_stream_to_write_submessage(session, stream_id, payload_length, &ub, SUBMESSAGE_ID_READ_DATA, 0))
{
request_id = uxr_init_base_object_request(&session->info, datareader_id, &payload.base);
(void) uxr_serialize_READ_DATA_Payload(&ub, &payload);
}
UXR_UNLOCK_STREAM_ID(session, stream_id);
return request_id;
}

View File

@ -16,8 +16,17 @@
#include "stream/seq_num_internal.h"
#include "../log/log_internal.h"
#include "../../util/time_internal.h"
#include <uxr/client/profile/multithread/multithread.h>
#include "../../profile/shared_memory/shared_memory_internal.h"
#ifdef UCLIENT_PROFILE_SHARED_MEMORY
#define CREATE_SESSION_PROPERTIES_MAX_SIZE 21
#define CREATE_SESSION_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + CREATE_CLIENT_PAYLOAD_SIZE + \
CREATE_SESSION_PROPERTIES_MAX_SIZE)
#else
#define CREATE_SESSION_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + CREATE_CLIENT_PAYLOAD_SIZE)
#endif /* ifdef UCLIENT_PROFILE_SHARED_MEMORY */
#define DELETE_SESSION_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + DELETE_CLIENT_PAYLOAD_SIZE)
#define HEARTBEAT_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + HEARTBEAT_PAYLOAD_SIZE)
#define ACKNACK_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + ACKNACK_PAYLOAD_SIZE)
@ -124,6 +133,8 @@ void uxr_init_session(
uxrCommunication* comm,
uint32_t key)
{
UXR_INIT_LOCK(&session->mutex);
session->comm = comm;
session->request_list = NULL;
@ -230,6 +241,8 @@ bool uxr_delete_session_retries(
uxrSession* session,
size_t retries)
{
UXR_CLEAN_SHARED_MEMORY();
uint8_t delete_session_buffer[DELETE_SESSION_MAX_MSG_SIZE];
ucdrBuffer ub;
ucdr_init_buffer_origin_offset(&ub, delete_session_buffer, DELETE_SESSION_MAX_MSG_SIZE, 0u, uxr_session_header_offset(
@ -286,6 +299,8 @@ bool uxr_run_session_time(
uxrSession* session,
int timeout_ms)
{
UXR_LOCK_SESSION(session);
uxr_flash_output_streams(session);
bool timeout = false;
@ -294,13 +309,18 @@ bool uxr_run_session_time(
timeout = !listen_message_reliably(session, timeout_ms);
}
return uxr_output_streams_confirmed(&session->streams);
bool ret = uxr_output_streams_confirmed(&session->streams);
UXR_UNLOCK_SESSION(session);
return ret;
}
bool uxr_run_session_timeout(
uxrSession* session,
int timeout_ms)
{
UXR_LOCK_SESSION(session);
int64_t start_timestamp = uxr_millis();
int remaining_time = timeout_ms;
@ -312,13 +332,19 @@ bool uxr_run_session_timeout(
remaining_time = timeout_ms - (int)(uxr_millis() - start_timestamp);
}
while (remaining_time > 0);
return uxr_output_streams_confirmed(&session->streams);
bool ret = uxr_output_streams_confirmed(&session->streams);
UXR_UNLOCK_SESSION(session);
return ret;
}
bool uxr_run_session_until_data(
uxrSession* session,
int timeout_ms)
{
UXR_LOCK_SESSION(session);
int64_t start_timestamp = uxr_millis();
int remaining_time = timeout_ms;
@ -335,6 +361,9 @@ bool uxr_run_session_until_data(
remaining_time = timeout_ms - (int)(uxr_millis() - start_timestamp);
}
while (remaining_time > 0);
UXR_UNLOCK_SESSION(session);
return session->on_data_flag;
}
@ -342,15 +371,22 @@ bool uxr_run_session_until_timeout(
uxrSession* session,
int timeout_ms)
{
UXR_LOCK_SESSION(session);
uxr_flash_output_streams(session);
return listen_message_reliably(session, timeout_ms);
bool ret = listen_message_reliably(session, timeout_ms);
UXR_UNLOCK_SESSION(session);
return ret;
}
bool uxr_run_session_until_confirm_delivery(
uxrSession* session,
int timeout_ms)
{
UXR_LOCK_SESSION(session);
uxr_flash_output_streams(session);
bool timeout = false;
@ -359,7 +395,10 @@ bool uxr_run_session_until_confirm_delivery(
timeout = !listen_message_reliably(session, timeout_ms);
}
return uxr_output_streams_confirmed(&session->streams);
bool ret = uxr_output_streams_confirmed(&session->streams);
UXR_UNLOCK_SESSION(session);
return ret;
}
bool uxr_run_session_until_all_status(
@ -369,6 +408,8 @@ bool uxr_run_session_until_all_status(
uint8_t* status_list,
size_t list_size)
{
UXR_LOCK_SESSION(session);
uxr_flash_output_streams(session);
for (unsigned i = 0; i < list_size; ++i)
@ -376,6 +417,7 @@ bool uxr_run_session_until_all_status(
status_list[i] = UXR_STATUS_NONE;
}
session->request_list = request_list;
session->status_list = status_list;
session->request_status_list_size = list_size;
@ -403,6 +445,8 @@ bool uxr_run_session_until_all_status(
status_ok = status_list[i] == UXR_STATUS_OK || status_list[i] == UXR_STATUS_OK_MATCHED;
}
UXR_UNLOCK_SESSION(session);
return status_ok;
}
@ -413,6 +457,8 @@ bool uxr_run_session_until_one_status(
uint8_t* status_list,
size_t list_size)
{
UXR_LOCK_SESSION(session);
uxr_flash_output_streams(session);
for (unsigned i = 0; i < list_size; ++i)
@ -438,6 +484,7 @@ bool uxr_run_session_until_one_status(
while (!timeout && !status_confirmed);
session->request_status_list_size = 0;
UXR_UNLOCK_SESSION(session);
return status_confirmed;
}
@ -446,6 +493,8 @@ bool uxr_sync_session(
uxrSession* session,
int time)
{
UXR_LOCK_SESSION(session);
uint8_t timestamp_buffer[TIMESTAMP_MAX_MSG_SIZE];
ucdrBuffer ub;
ucdr_init_buffer_origin_offset(&ub, timestamp_buffer, sizeof(timestamp_buffer), 0u,
@ -460,7 +509,10 @@ bool uxr_sync_session(
uxr_stamp_session_header(&session->info, 0, 0, ub.init);
send_message(session, timestamp_buffer, ucdr_buffer_length(&ub));
return run_session_until_sync(session, time);
bool ret = run_session_until_sync(session, time);
UXR_UNLOCK_SESSION(session);
return ret;
}
int64_t uxr_epoch_millis(
@ -510,17 +562,24 @@ bool uxr_buffer_performance(
void uxr_flash_output_streams(
uxrSession* session)
{
UXR_HANDLE_SHARED_MEMORY();
for (uint8_t i = 0; i < session->streams.output_best_effort_size; ++i)
{
uxrOutputBestEffortStream* stream = &session->streams.output_best_effort[i];
uxrStreamId id = uxr_stream_id(i, UXR_BEST_EFFORT_STREAM, UXR_OUTPUT_STREAM);
uint8_t* buffer; size_t length; uxrSeqNum seq_num;
UXR_LOCK_STREAM_ID(session, id);
if (uxr_prepare_best_effort_buffer_to_send(stream, &buffer, &length, &seq_num))
{
uxr_stamp_session_header(&session->info, id.raw, seq_num, buffer);
send_message(session, buffer, length);
}
UXR_UNLOCK_STREAM_ID(session, id);
}
for (uint8_t i = 0; i < session->streams.output_reliable_size; ++i)
@ -529,11 +588,16 @@ void uxr_flash_output_streams(
uxrStreamId id = uxr_stream_id(i, UXR_RELIABLE_STREAM, UXR_OUTPUT_STREAM);
uint8_t* buffer; size_t length; uxrSeqNum seq_num;
UXR_LOCK_STREAM_ID(session, id);
while (uxr_prepare_next_reliable_buffer_to_send(stream, &buffer, &length, &seq_num))
{
uxr_stamp_session_header(&session->info, id.raw, seq_num, buffer);
send_message(session, buffer, length);
}
UXR_UNLOCK_STREAM_ID(session, id);
}
}
@ -545,6 +609,8 @@ bool listen_message(
int poll_ms)
{
uint8_t* data; size_t length;
UXR_LOCK_ALL_INPUT_STREAMS(session);
bool must_be_read = recv_message(session, &data, &length, poll_ms);
if (must_be_read)
{
@ -552,6 +618,7 @@ bool listen_message(
ucdr_init_buffer(&ub, data, (uint32_t)length);
read_message(session, &ub);
}
UXR_UNLOCK_ALL_INPUT_STREAMS(session);
return must_be_read;
}
@ -571,6 +638,7 @@ bool listen_message_reliably(
uxrOutputReliableStream* stream = &session->streams.output_reliable[i];
uxrStreamId id = uxr_stream_id(i, UXR_RELIABLE_STREAM, UXR_OUTPUT_STREAM);
UXR_LOCK_STREAM_ID(session, id);
if (uxr_update_output_stream_heartbeat_timestamp(stream, timestamp))
{
write_submessage_heartbeat(session, id);
@ -580,6 +648,7 @@ bool listen_message_reliably(
{
next_heartbeat_timestamp = stream->next_heartbeat_timestamp;
}
UXR_UNLOCK_STREAM_ID(session, id);
}
int32_t poll_to_next_heartbeat =
@ -893,6 +962,8 @@ void read_submessage_acknack(
uxrOutputReliableStream* stream = uxr_get_output_reliable_stream(&session->streams, id.index);
if (stream)
{
UXR_LOCK_STREAM_ID(session, id);
uint16_t nack_bitmap = (uint16_t)(((uint16_t)acknack.nack_bitmap[0] << 8) + acknack.nack_bitmap[1]);
uxr_process_acknack(stream, nack_bitmap, acknack.first_unacked_seq_num);
@ -902,6 +973,8 @@ void read_submessage_acknack(
{
send_message(session, buffer, length);
}
UXR_UNLOCK_STREAM_ID(session, id);
}
}

View File

@ -1,6 +1,7 @@
#include <uxr/client/defines.h>
#include <uxr/client/core/session/object_id.h>
#include <uxr/client/core/type/xrce_types.h>
#include <uxr/client/config.h>
#include "session_info_internal.h"
#include "submessage_internal.h"
@ -53,6 +54,12 @@ void uxr_buffer_create_session(
payload.client_representation.client_key.data[3] = info->key[3];
payload.client_representation.session_id = info->id;
payload.client_representation.optional_properties = false;
#ifdef UCLIENT_PROFILE_SHARED_MEMORY
payload.client_representation.optional_properties = true;
payload.client_representation.properties.size = 1;
payload.client_representation.properties.data[0].name = "uxr_sm";
payload.client_representation.properties.data[0].value = "1";
#endif /* ifdef UCLIENT_PROFILE_SHARED_MEMORY */
payload.client_representation.mtu = mtu;
info->last_request_id = UXR_REQUEST_LOGIN;

View File

@ -1,5 +1,6 @@
#include "input_best_effort_stream_internal.h"
#include "seq_num_internal.h"
#include <uxr/client/profile/multithread/multithread.h>
//==================================================================
// PUBLIC
@ -8,6 +9,8 @@ void uxr_init_input_best_effort_stream(
uxrInputBestEffortStream* stream)
{
stream->last_handled = SEQ_NUM_MAX;
UXR_INIT_LOCK(&stream->mutex);
}
void uxr_reset_input_best_effort_stream(

View File

@ -4,6 +4,7 @@
#include "./input_reliable_stream_internal.h"
#include "./common_reliable_stream_internal.h"
#include "../submessage_internal.h"
#include <uxr/client/profile/multithread/multithread.h>
#include <string.h>
@ -33,6 +34,8 @@ void uxr_init_input_reliable_stream(
stream->on_get_fragmentation_info = on_get_fragmentation_info;
stream->cleanup_flag = false;
UXR_INIT_LOCK(&stream->mutex);
uxr_reset_input_reliable_stream(stream);
}

View File

@ -2,6 +2,7 @@
#include "../submessage_internal.h"
#include "seq_num_internal.h"
#include <uxr/client/profile/multithread/multithread.h>
#include <ucdr/microcdr.h>
@ -18,6 +19,8 @@ void uxr_init_output_best_effort_stream(
stream->offset = offset;
stream->size = size;
UXR_INIT_LOCK(&stream->mutex);
uxr_reset_output_best_effort_stream(stream);
}

View File

@ -8,6 +8,7 @@
#include "./output_reliable_stream_internal.h"
#include "./common_reliable_stream_internal.h"
#include "../submessage_internal.h"
#include <uxr/client/profile/multithread/multithread.h>
#define MIN_HEARTBEAT_TIME_INTERVAL ((int64_t) UXR_CONFIG_MIN_HEARTBEAT_TIME_INTERVAL) // ms
#define MAX_HEARTBEAT_TRIES (sizeof(int64_t) * 8 - 1)
@ -29,6 +30,8 @@ void uxr_init_output_reliable_stream(
stream->base.history = history;
stream->offset = header_offset;
UXR_INIT_LOCK(&stream->mutex);
uxr_reset_output_reliable_stream(stream);
}

View File

@ -29,6 +29,8 @@ uxrStreamId uxr_stream_id(
case UXR_RELIABLE_STREAM:
stream_id.raw = (uint8_t)(index + RELIABLE_STREAM_THRESHOLD);
break;
default:
break;
}
return stream_id;

View File

@ -3,6 +3,7 @@
#include "input_reliable_stream_internal.h"
#include "output_best_effort_stream_internal.h"
#include "output_reliable_stream_internal.h"
#include <uxr/client/profile/multithread/multithread.h>
//==================================================================
// PUBLIC
@ -141,7 +142,9 @@ bool uxr_output_streams_confirmed(
bool up_to_date = true;
for (unsigned i = 0; i < storage->output_reliable_size && up_to_date; ++i)
{
UXR_LOCK((uxrMutex*) &storage->output_reliable[i].mutex);
up_to_date = uxr_is_output_up_to_date(&storage->output_reliable[i]);
UXR_UNLOCK((uxrMutex*) &storage->output_reliable[i].mutex);
}
return up_to_date;
}

View File

@ -8,6 +8,8 @@
#include "./stream/common_reliable_stream_internal.h"
#include "./stream/stream_storage_internal.h"
#include "./stream/seq_num_internal.h"
#include <uxr/client/profile/multithread/multithread.h>
#include "../../profile/shared_memory/shared_memory_internal.h"
#define WRITE_DATA_PAYLOAD_SIZE 4
#define SAMPLE_IDENTITY_SIZE 24
@ -26,6 +28,8 @@ uint16_t uxr_buffer_request(
ucdrBuffer ub;
size_t payload_size = WRITE_DATA_PAYLOAD_SIZE + len;
UXR_LOCK_STREAM_ID(session, stream_id);
ub.error = !uxr_prepare_stream_to_write_submessage(session, stream_id, payload_size, &ub, SUBMESSAGE_ID_WRITE_DATA,
FORMAT_DATA);
if (!ub.error)
@ -33,9 +37,12 @@ uint16_t uxr_buffer_request(
WRITE_DATA_Payload_Data payload;
rv = uxr_init_base_object_request(&session->info, requester_id, &payload.base);
uxr_serialize_WRITE_DATA_Payload_Data(&ub, &payload);
UXR_PREPARE_SHARED_MEMORY(session, requester_id, &ub, (uint16_t) len, rv);
ucdr_serialize_array_uint8_t(&ub, buffer, len);
}
UXR_UNLOCK_STREAM_ID(session, stream_id);
return rv;
}
@ -51,6 +58,8 @@ uint16_t uxr_buffer_reply(
ucdrBuffer ub;
size_t payload_size = WRITE_DATA_PAYLOAD_SIZE + SAMPLE_IDENTITY_SIZE + len;
UXR_LOCK_STREAM_ID(session, stream_id);
ub.error = !uxr_prepare_stream_to_write_submessage(session, stream_id, payload_size, &ub, SUBMESSAGE_ID_WRITE_DATA,
FORMAT_DATA);
if (!ub.error)
@ -58,10 +67,13 @@ uint16_t uxr_buffer_reply(
WRITE_DATA_Payload_Data payload;
rv = uxr_init_base_object_request(&session->info, replier_id, &payload.base);
uxr_serialize_WRITE_DATA_Payload_Data(&ub, &payload);
UXR_PREPARE_SHARED_MEMORY(session, replier_id, &ub, (uint16_t) (SAMPLE_IDENTITY_SIZE + len), rv);
uxr_serialize_SampleIdentity(&ub, sample_id);
ucdr_serialize_array_uint8_t(&ub, buffer, len);
}
UXR_UNLOCK_STREAM_ID(session, stream_id);
return rv;
}
@ -76,6 +88,8 @@ uint16_t uxr_buffer_topic(
ucdrBuffer ub;
size_t payload_size = WRITE_DATA_PAYLOAD_SIZE + len;
UXR_LOCK_STREAM_ID(session, stream_id);
ub.error = !uxr_prepare_stream_to_write_submessage(session, stream_id, payload_size, &ub, SUBMESSAGE_ID_WRITE_DATA,
FORMAT_DATA);
if (!ub.error)
@ -83,9 +97,12 @@ uint16_t uxr_buffer_topic(
WRITE_DATA_Payload_Data payload;
rv = uxr_init_base_object_request(&session->info, datawriter_id, &payload.base);
uxr_serialize_WRITE_DATA_Payload_Data(&ub, &payload);
UXR_PREPARE_SHARED_MEMORY(session, datawriter_id, &ub, (uint16_t) len, rv);
ucdr_serialize_array_uint8_t(&ub, buffer, len);
}
UXR_UNLOCK_STREAM_ID(session, stream_id);
return rv;
}
@ -94,11 +111,14 @@ uint16_t uxr_prepare_output_stream(
uxrStreamId stream_id,
uxrObjectId entity_id,
ucdrBuffer* ub,
uint32_t data_size)
uint32_t len)
{
uint16_t rv = UXR_INVALID_REQUEST_ID;
size_t payload_size = WRITE_DATA_PAYLOAD_SIZE + data_size;
UXR_LOCK_STREAM_ID(session, stream_id);
size_t payload_size = WRITE_DATA_PAYLOAD_SIZE + len;
ub->error = !uxr_prepare_stream_to_write_submessage(session, stream_id, payload_size, ub, SUBMESSAGE_ID_WRITE_DATA,
FORMAT_DATA);
if (!ub->error)
@ -111,6 +131,8 @@ uint16_t uxr_prepare_output_stream(
void* args = ub->args;
ucdr_init_buffer(ub, ub->iterator, (size_t)(ub->final - ub->iterator));
ucdr_set_on_full_buffer_callback(ub, on_full_buffer, args);
UXR_PREPARE_SHARED_MEMORY(session, entity_id, ub, (uint16_t) len, rv);
}
return rv;
@ -174,6 +196,10 @@ uint16_t uxr_prepare_output_stream_fragmented(
{
uint16_t rv = UXR_INVALID_REQUEST_ID;
#ifdef UCLIENT_PROFILE_MULTITHREAD
return rv;
#endif /* ifdef UCLIENT_PROFILE_MULTITHREAD */
size_t user_required_space = data_size + SUBHEADER_SIZE + WRITE_DATA_PAYLOAD_SIZE;
uxrOutputReliableStream* stream = uxr_get_output_reliable_stream(&session->streams, stream_id.index);

View File

@ -0,0 +1,256 @@
#include "matching_internal.h"
#include <uxr/client/core/type/xrce_types.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>
//==================================================================
// PRIVATE
//==================================================================
// djb2 by Dan Bernstein: http://www.cse.yorku.ca/~oz/hash.html
void hash_string(
unsigned char* str,
char* hash,
bool initial)
{
hash_int_t int_hash = 5381;
if (initial)
{
int_hash = *((hash_int_t*) hash);
}
int c;
do {
c = *str++;
int_hash = ((int_hash << 5) + int_hash) + (hash_int_t)c; /* hash * 33 + c */
} while (c);
for (size_t i = 0; i < UXR_MATCHING_HASH_SIZE; i++)
{
hash[i] = ((char*)&int_hash)[i];
}
}
// Find first occurrence of tag in XML
bool find_tag_xml(
const char* xml,
size_t len,
char* tag,
const char** content,
size_t* content_len)
{
size_t tag_len = strlen(tag);
bool found_begin = false;
bool found_end = false;
for (size_t i = 1; i < len; i++)
{
if (!found_begin && 0 == memcmp(&xml[i], tag, tag_len) && xml[i - 1] == '<')
{
size_t tag_opener_len = 0;
while (xml[i + tag_opener_len] != '>')
{
tag_opener_len++;
}
*content = &xml[i + tag_opener_len + 1];
found_begin = true;
}
else if (found_begin && 0 == memcmp(&xml[i], tag, tag_len) && xml[i - 1] == '/')
{
*content_len = (size_t)(&xml[i - 2] - *content);
found_end = true;
break;
}
}
return found_begin && found_end;
}
// Find property in first occurrence of tag in XML
bool find_tag_property(
const char* xml,
size_t len,
const char* tag,
char* property,
const char** content,
size_t* content_len)
{
size_t tag_len = strlen(tag);
size_t property_len = strlen(property);
bool found_tag = false;
bool found_property = false;
for (size_t i = 1; i < len; i++)
{
if (!found_tag && 0 == memcmp(&xml[i], tag, tag_len) && xml[i - 1] == '<')
{
found_tag = true;
}
else if (found_tag && 0 == memcmp(&xml[i], property, property_len))
{
*content = &xml[i + property_len + 2];
i += property_len + 2;
*content_len = 0;
while (xml[i + (*content_len)] != '"')
{
*content_len += 1;
}
found_property = true;
break;
}
}
return found_tag && found_property;
}
bool uxr_generate_hash_from_xml(
const char* xml,
uxrObjectId id,
char* hash)
{
bool found = true;
char name_type_buffer[100];
switch (id.type)
{
case UXR_DATAREADER_ID:
case UXR_DATAWRITER_ID:
{
const char* data_reader_or_writer = (id.type == UXR_DATAREADER_ID) ? "data_reader\0" : "data_writer\0";
char xml_strings[3][12] =
{
"dds",
"",
"topic"
};
memmove(xml_strings[1], data_reader_or_writer, 12);
const char* content_in = xml;
char* content_out;
size_t content_len_in = strlen(content_in);
size_t content_len_out;
for (size_t i = 0; i < 3; i++)
{
if (find_tag_xml(content_in, content_len_in, xml_strings[i], (const char**)&content_out,
&content_len_out))
{
content_in = content_out;
content_len_in = content_len_out;
}
else
{
return false;
}
}
size_t topic_name_len;
size_t type_name_len;
found &= find_tag_xml(content_in, content_len_in, "name", (const char**)&content_out, &topic_name_len);
memcpy(name_type_buffer, content_out, topic_name_len);
found &= find_tag_xml(content_in, content_len_in, "dataType", (const char**)&content_out, &type_name_len);
memcpy(&name_type_buffer[topic_name_len], content_out, type_name_len);
name_type_buffer[topic_name_len + type_name_len] = '\0';
hash_string((unsigned char*) name_type_buffer, hash, false);
break;
}
case UXR_REQUESTER_ID:
case UXR_REPLIER_ID:
{
char* content_out;
size_t service_name_len;
size_t request_type_name_len;
size_t reply_type_name_len;
found &= find_tag_property(xml,
strlen(xml),
(id.type == UXR_REQUESTER_ID) ? "requester" : "replier",
"service_name",
(const char**)&content_out,
&service_name_len);
if (found)
{
memcpy(name_type_buffer, content_out, service_name_len);
}
found &= find_tag_property(xml,
strlen(xml),
(id.type == UXR_REQUESTER_ID) ? "requester" : "replier",
"request_type",
(const char**)&content_out,
&request_type_name_len);
if (found)
{
memcpy(&name_type_buffer[service_name_len], content_out, request_type_name_len);
}
found &= find_tag_property(xml,
strlen(xml),
(id.type == UXR_REQUESTER_ID) ? "requester" : "replier",
"reply_type",
(const char**)&content_out,
&reply_type_name_len);
if (found)
{
memcpy(&name_type_buffer[service_name_len + request_type_name_len], content_out, reply_type_name_len);
name_type_buffer[service_name_len + request_type_name_len + reply_type_name_len] = '\0';
}
if (found)
{
hash_string((unsigned char*) name_type_buffer, hash, false);
}
break;
}
}
return found;
}
bool uxr_generate_hash_from_ref(
const char* ref,
char* hash)
{
hash_string((unsigned char*) ref, hash, false);
return true;
}
bool uxr_generate_hash_from_strings(
char* hash,
size_t number_strings,
...)
{
va_list args;
va_start(args, number_strings);
char* s = va_arg(args, char*);
hash_string((unsigned char*) s, hash, false);
for (size_t i = 1; i < number_strings; i++)
{
s = va_arg(args, char*);
hash_string((unsigned char*) s, hash, true);
}
va_end(args);
return true;
}
bool uxr_match_endpoint_qosbinary(
const OBJK_Endpoint_QosBinary* entity_1,
const OBJK_Endpoint_QosBinary* entity_2)
{
bool matched = true;
matched &= entity_1->qos_flags == entity_2->qos_flags;
return matched;
}

View File

@ -0,0 +1,58 @@
// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef UXR_CLIENT_PROFILE_MATCHING_INTERNAL_H_
#define UXR_CLIENT_PROFILE_MATCHING_INTERNAL_H_
#ifdef __cplusplus
extern "C"
{
#endif // ifdef __cplusplus
#include <uxr/client/config.h>
#include <uxr/client/visibility.h>
#include <uxr/client/core/session/object_id.h>
#include <uxr/client/core/type/xrce_types.h>
#include <stdbool.h>
typedef uint32_t hash_int_t;
#define UXR_MATCHING_HASH_SIZE sizeof(hash_int_t)
bool uxr_generate_hash_from_xml(
const char* xml,
uxrObjectId id,
char* hash);
bool uxr_generate_hash_from_ref(
const char* ref,
char* hash);
bool uxr_generate_hash_from_strings(
char* hash,
size_t number_strings,
...);
bool uxr_match_endpoint_qosbinary(
const OBJK_Endpoint_QosBinary* entity_1,
const OBJK_Endpoint_QosBinary* entity_2);
#ifdef __cplusplus
}
#endif // ifdef __cplusplus
#endif // UXR_CLIENT_PROFILE_MATCHING_INTERNAL_H_

View File

@ -0,0 +1,83 @@
#include <uxr/client/profile/multithread/multithread.h>
#include <uxr/client/core/session/session.h>
#include "../../core/session/stream/stream_storage_internal.h"
//==================================================================
// PRIVATE
//==================================================================
void uxr_init_lock(
uxrMutex* mutex)
{
#if defined(PLATFORM_NAME_FREERTOS)
mutex->impl = xSemaphoreCreateRecursiveMutexStatic( &mutex->xMutexBuffer );
#elif defined(UCLIENT_PLATFORM_ZEPHYR)
k_mutex_init(&mutex->impl);
#elif defined(UCLIENT_PLATFORM_POSIX)
pthread_mutexattr_t mat;
pthread_mutexattr_init(&mat);
pthread_mutexattr_settype(&mat, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex->impl, &mat);
#else
#error XRCE multithreading not supported for this platform.
#endif /* if defined(PLATFORM_NAME_FREERTOS) */
}
void uxr_lock(
uxrMutex* mutex)
{
#if defined(PLATFORM_NAME_FREERTOS)
xSemaphoreTakeRecursive(mutex->impl, portMAX_DELAY);
#elif defined(UCLIENT_PLATFORM_ZEPHYR)
k_mutex_lock(&mutex->impl, K_FOREVER);
#elif defined(UCLIENT_PLATFORM_POSIX)
pthread_mutex_lock(&mutex->impl);
#else
#error XRCE multithreading not supported for this platform.
#endif /* if defined(PLATFORM_NAME_FREERTOS) */
}
void uxr_unlock(
uxrMutex* mutex)
{
#if defined(PLATFORM_NAME_FREERTOS)
xSemaphoreGiveRecursive(mutex->impl);
#elif defined(UCLIENT_PLATFORM_ZEPHYR)
k_mutex_unlock(&mutex->impl);
#elif defined(UCLIENT_PLATFORM_POSIX)
pthread_mutex_unlock(&mutex->impl);
#else
#error XRCE multithreading not supported for this platform.
#endif /* if defined(PLATFORM_NAME_FREERTOS) */
}
uxrMutex* uxr_get_stream_mutex_from_id(
struct uxrSession* session,
uxrStreamId stream_id)
{
uxrMutex* mutex = NULL;
if (stream_id.type == UXR_BEST_EFFORT_STREAM && stream_id.direction == UXR_OUTPUT_STREAM)
{
uxrOutputBestEffortStream* stream = uxr_get_output_best_effort_stream(&session->streams, stream_id.index);
mutex = (stream == NULL) ? NULL : &stream->mutex;
}
else if (stream_id.type == UXR_BEST_EFFORT_STREAM && stream_id.direction == UXR_INPUT_STREAM)
{
uxrInputBestEffortStream* stream = uxr_get_input_best_effort_stream(&session->streams, stream_id.index);
mutex = (stream == NULL) ? NULL : &stream->mutex;
}
else if (stream_id.type == UXR_RELIABLE_STREAM && stream_id.direction == UXR_OUTPUT_STREAM)
{
uxrOutputReliableStream* stream = uxr_get_output_reliable_stream(&session->streams, stream_id.index);
mutex = (stream == NULL) ? NULL : &stream->mutex;
}
else if (stream_id.type == UXR_RELIABLE_STREAM && stream_id.direction == UXR_INPUT_STREAM)
{
uxrInputReliableStream* stream = uxr_get_input_reliable_stream(&session->streams, stream_id.index);
mutex = (stream == NULL) ? NULL : &stream->mutex;
}
return mutex;
}

View File

@ -0,0 +1,482 @@
#include <uxr/client/config.h>
#include <uxr/client/core/session/session.h>
#include <uxr/client/core/type/xrce_types.h>
#include <uxr/client/profile/multithread/multithread.h>
#include <uxr/client/core/type/xrce_types.h>
#include "../../core/session/stream/stream_storage_internal.h"
#include "../matching/matching_internal.h"
#include <string.h>
#if defined(WIN32)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#else
#include <sys/types.h>
#endif /* if defined(WIN32) */
//==================================================================
// PRIVATE
//==================================================================
typedef struct uxr_shared_memory_buffer_item_t
{
struct uxr_shared_memory_buffer_item_t* next;
ucdrBuffer data;
uint16_t data_size;
uint16_t request_id;
} uxr_shared_memory_buffer_item_t;
typedef enum entity_descriptor_type_t
{
UXR_SHARED_MEMORY_HASH_ENTITY,
UXR_SHARED_MEMORY_BIN_ENTITY
} entity_descriptor_type_t;
typedef struct uxr_shared_memory_entity_t
{
uxrObjectId object_id;
uxrSession* session;
entity_descriptor_type_t type;
union
{
char hash[UXR_MATCHING_HASH_SIZE];
OBJK_DataWriter_Binary datawriter;
OBJK_DataReader_Binary datareader;
} data;
struct uxr_shared_memory_entity_t* related_topic;
} uxr_shared_memory_entity_t;
typedef struct uxr_shared_memory_matrix_block_t
{
bool matched;
struct uxr_shared_memory_buffer_item_t* list;
} uxr_shared_memory_matrix_block_t;
typedef struct uxr_shared_memory_map_t
{
uxr_shared_memory_entity_t entities[UXR_CONFIG_SHARED_MEMORY_MAX_ENTITIES];
size_t entities_len;
uxr_shared_memory_matrix_block_t matrix[UXR_CONFIG_SHARED_MEMORY_MAX_ENTITIES][UXR_CONFIG_SHARED_MEMORY_MAX_ENTITIES
];
uxr_shared_memory_buffer_item_t mem_pool[UXR_CONFIG_SHARED_MEMORY_STATIC_MEM_SIZE];
uxr_shared_memory_buffer_item_t* mempool_freeitems;
bool init;
#ifdef UCLIENT_PROFILE_MULTITHREAD
uxrMutex lock;
#endif /* ifdef UCLIENT_PROFILE_MULTITHREAD */
} uxr_shared_memory_map_t;
static uxr_shared_memory_map_t uxr_sm_map = {
0
};
// Double linked pool for ucdrBuffers
void uxr_prepend_to_list(
uxr_shared_memory_buffer_item_t* member,
uxr_shared_memory_buffer_item_t** list)
{
member->next = *list;
*list = member;
}
uxr_shared_memory_buffer_item_t* uxr_pop_head_from_list(
uxr_shared_memory_buffer_item_t** list)
{
uxr_shared_memory_buffer_item_t* member = *list;
*list = (*list == NULL ) ? NULL : (*list)->next;
return member;
}
#define UXR_SHARED_MEMORY_INIT() if (!uxr_sm_map.init){uxr_init_shared_memory();}
void uxr_init_shared_memory()
{
uxr_sm_map.init = true;
UXR_INIT_LOCK(&uxr_sm_map.lock);
for (size_t i = 0; i < UXR_CONFIG_SHARED_MEMORY_STATIC_MEM_SIZE; i++)
{
uxr_prepend_to_list(&uxr_sm_map.mem_pool[i], &uxr_sm_map.mempool_freeitems);
}
}
void uxr_clean_shared_memory()
{
memset(&uxr_sm_map, 0, sizeof(uxr_sm_map));
}
// API
bool uxr_shared_memory_entity_compare(
uxr_shared_memory_entity_t* e1,
uxr_shared_memory_entity_t* e2)
{
bool ret = true;
for (uint8_t i = 0; i < sizeof(e1->session->info.key); i++)
{
ret &= e1->session->info.key[i] == e2->session->info.key[i];
}
ret &= e1->object_id.id == e2->object_id.id;
ret &= e1->object_id.type == e2->object_id.type;
return ret;
}
ssize_t uxr_shared_memory_get_entity_index(
uxrSession* session,
uxrObjectId* entity_id)
{
uxr_shared_memory_entity_t aux;
aux.session = session;
aux.object_id = *entity_id;
for (size_t i = 0; i < uxr_sm_map.entities_len; i++)
{
if (uxr_shared_memory_entity_compare(&aux, &uxr_sm_map.entities[i]))
{
return (ssize_t)i;
}
}
return -1;
}
uxr_shared_memory_entity_t* uxr_shared_memory_get_entity(
uxrSession* session,
uxrObjectId* entity_id)
{
uxr_shared_memory_entity_t aux;
aux.session = session;
aux.object_id = *entity_id;
for (size_t i = 0; i < uxr_sm_map.entities_len; i++)
{
if (uxr_shared_memory_entity_compare(&aux, &uxr_sm_map.entities[i]))
{
return &uxr_sm_map.entities[i];
}
}
return NULL;
}
void uxr_prepare_shared_memory(
uxrSession* session,
uxrObjectId entity_id,
ucdrBuffer* ub,
uint16_t data_size,
uint16_t request_id)
{
UXR_SHARED_MEMORY_INIT();
UXR_LOCK(&uxr_sm_map.lock);
ssize_t entity_index = uxr_shared_memory_get_entity_index(session, &entity_id);
if (-1 == entity_index)
{
return;
}
for (size_t i = 0; i < uxr_sm_map.entities_len; i++)
{
if (uxr_sm_map.matrix[entity_index][i].matched)
{
uxr_shared_memory_buffer_item_t* item = uxr_pop_head_from_list(&uxr_sm_map.mempool_freeitems);
if (item != NULL)
{
item->data = *ub;
item->data_size = data_size;
item->request_id = request_id;
uxr_prepend_to_list(item, &uxr_sm_map.matrix[entity_index][i].list);
}
}
}
UXR_UNLOCK(&uxr_sm_map.lock);
}
void uxr_handle_shared_memory()
{
UXR_SHARED_MEMORY_INIT();
UXR_LOCK(&uxr_sm_map.lock);
for (size_t i = 0; i < uxr_sm_map.entities_len; i++)
{
if (uxr_sm_map.entities[i].object_id.type != UXR_DATAWRITER_ID
&& uxr_sm_map.entities[i].object_id.type != UXR_REPLIER_ID
&& uxr_sm_map.entities[i].object_id.type != UXR_REQUESTER_ID
)
{
continue;
}
for (size_t j = 0; j < uxr_sm_map.entities_len; j++)
{
while (uxr_sm_map.matrix[i][j].list != NULL)
{
uxrStreamId stream_id = {
.type = UXR_SHARED_MEMORY_STREAM
};
uxr_shared_memory_buffer_item_t* item = uxr_pop_head_from_list(&uxr_sm_map.matrix[i][j].list);
switch (uxr_sm_map.entities[j].object_id.type)
{
case UXR_DATAREADER_ID:
{
if (NULL != uxr_sm_map.entities[j].session->on_topic)
{
uxr_sm_map.entities[j].session->on_topic(
uxr_sm_map.entities[j].session,
uxr_sm_map.entities[j].object_id,
0, // Req ID = 0 means shared memory?
stream_id,
&item->data,
item->data_size,
uxr_sm_map.entities[j].session->on_topic_args
);
}
break;
}
case UXR_REPLIER_ID:
{
if (NULL != uxr_sm_map.entities[j].session->on_request)
{
SampleIdentity sample_identity;
sample_identity.sequence_number.low = item->request_id;
// Save session key
memcpy(sample_identity.writer_guid.guidPrefix.data,
uxr_sm_map.entities[i].session->info.key,
sizeof(uxr_sm_map.entities[i].session->info.key));
// Save source uxrObjectId info
sample_identity.writer_guid.entityId.entityKey[1] =
(uint8_t) (uxr_sm_map.entities[i].object_id.id >> 8) & 0xFF;
sample_identity.writer_guid.entityId.entityKey[0] =
(uint8_t) uxr_sm_map.entities[i].object_id.id &
0xFF;
sample_identity.writer_guid.entityId.entityKind = uxr_sm_map.entities[i].object_id.type;
uxr_sm_map.entities[j].session->on_request(
uxr_sm_map.entities[j].session,
uxr_sm_map.entities[j].object_id,
0, // Req ID = 0 means shared memory?
&sample_identity,
&item->data,
item->data_size,
uxr_sm_map.entities[j].session->on_topic_args);
}
break;
}
case UXR_REQUESTER_ID:
{
if (NULL != uxr_sm_map.entities[j].session->on_reply)
{
SampleIdentity sample_identity;
size_t offset = item->data.offset;
uxr_deserialize_SampleIdentity(&item->data, &sample_identity);
// Check destination session key and uxrObjectId info
if (!memcmp(uxr_sm_map.entities[j].session->info.key,
sample_identity.writer_guid.guidPrefix.data,
sizeof(uxr_sm_map.entities[j].session->info.key))
&& uxr_sm_map.entities[j].object_id.id ==
(sample_identity.writer_guid.entityId.entityKey[1] >> 8) +
sample_identity.writer_guid.entityId.entityKey[0]
&& sample_identity.writer_guid.entityId.entityKind ==
uxr_sm_map.entities[j].object_id.type)
{
// TODO: Check this size calculation taking alignment
item->data_size = (uint16_t)(item->data_size - (item->data.offset - offset));
uxr_sm_map.entities[j].session->on_reply(
uxr_sm_map.entities[j].session,
uxr_sm_map.entities[j].object_id,
0, // Req ID = 0 means shared memory?
(uint16_t)sample_identity.sequence_number.low,
&item->data,
(size_t)item->data_size,
uxr_sm_map.entities[j].session->on_topic_args);
}
}
break;
}
default:
break;
}
uxr_prepend_to_list(item, &uxr_sm_map.mempool_freeitems);
}
}
}
UXR_UNLOCK(&uxr_sm_map.lock);
}
bool uxr_match_binary_entities(
uxr_shared_memory_entity_t* entity_1,
uxr_shared_memory_entity_t* entity_2)
{
if (!(entity_1->object_id.type == UXR_DATAREADER_ID && entity_2->object_id.type == UXR_DATAWRITER_ID) &&
!(entity_1->object_id.type == UXR_DATAWRITER_ID && entity_2->object_id.type == UXR_DATAREADER_ID) &&
!(entity_1->object_id.type == UXR_REQUESTER_ID && entity_2->object_id.type == UXR_REPLIER_ID) &&
!(entity_1->object_id.type == UXR_REPLIER_ID && entity_2->object_id.type == UXR_REQUESTER_ID))
{
return false;
}
bool matched = true;
switch (entity_1->object_id.type)
{
case UXR_DATAREADER_ID:
{
OBJK_DataReader_Binary* dr = (OBJK_DataReader_Binary*) &entity_1->data.datareader;
OBJK_DataWriter_Binary* dw = (OBJK_DataWriter_Binary*) &entity_2->data.datawriter;
matched &= uxr_match_endpoint_qosbinary(&dr->qos.base, &dw->qos.base);
matched &= 0 == strcmp(entity_1->related_topic->data.hash, entity_2->related_topic->data.hash);
break;
}
case UXR_DATAWRITER_ID:
{
OBJK_DataWriter_Binary* dw = (OBJK_DataWriter_Binary*) &entity_1->data.datawriter;
OBJK_DataReader_Binary* dr = (OBJK_DataReader_Binary*) &entity_2->data.datareader;
matched &= uxr_match_endpoint_qosbinary(&dr->qos.base, &dw->qos.base);
matched &= 0 == strcmp(entity_1->related_topic->data.hash, entity_2->related_topic->data.hash);
break;
}
case UXR_REQUESTER_ID:
case UXR_REPLIER_ID:
default:
matched = false;
break;
}
return matched;
}
void uxr_update_shared_memory_matching()
{
UXR_LOCK(&uxr_sm_map.lock);
for (size_t i = 0; i < uxr_sm_map.entities_len; i++)
{
for (size_t j = 0; j < uxr_sm_map.entities_len; j++)
{
if (i != j &&
uxr_sm_map.entities[i].type == uxr_sm_map.entities[j].type &&
uxr_sm_map.entities[i].object_id.type != uxr_sm_map.entities[j].object_id.type &&
uxr_sm_map.entities[i].object_id.type != UXR_TOPIC_ID &&
uxr_sm_map.entities[j].object_id.type != UXR_TOPIC_ID)
{
switch (uxr_sm_map.entities[i].type)
{
case UXR_SHARED_MEMORY_HASH_ENTITY:
uxr_sm_map.matrix[i][j].matched =
0 == memcmp(uxr_sm_map.entities[i].data.hash, uxr_sm_map.entities[j].data.hash,
UXR_MATCHING_HASH_SIZE);
break;
case UXR_SHARED_MEMORY_BIN_ENTITY:
uxr_sm_map.matrix[i][j].matched = uxr_match_binary_entities(&uxr_sm_map.entities[i],
&uxr_sm_map.entities[j]);
break;
default:
uxr_sm_map.matrix[i][j].matched = 0;
}
}
}
}
UXR_UNLOCK(&uxr_sm_map.lock);
}
void uxr_add_shared_memory_entity_xml(
uxrSession* session,
uxrObjectId entity_id,
const char* xml)
{
UXR_SHARED_MEMORY_INIT();
UXR_LOCK(&uxr_sm_map.lock);
if (uxr_sm_map.entities_len <= UXR_CONFIG_SHARED_MEMORY_MAX_ENTITIES - 1)
{
uxr_sm_map.entities[uxr_sm_map.entities_len].object_id = entity_id;
uxr_sm_map.entities[uxr_sm_map.entities_len].session = session;
uxr_sm_map.entities[uxr_sm_map.entities_len].type = UXR_SHARED_MEMORY_HASH_ENTITY;
uxr_generate_hash_from_xml(xml, entity_id, uxr_sm_map.entities[uxr_sm_map.entities_len].data.hash);
uxr_sm_map.entities_len++;
uxr_update_shared_memory_matching();
}
UXR_UNLOCK(&uxr_sm_map.lock);
}
void uxr_add_shared_memory_entity_bin(
uxrSession* session,
uxrObjectId entity_id,
const void* entity)
{
UXR_SHARED_MEMORY_INIT();
UXR_LOCK(&uxr_sm_map.lock);
if (uxr_sm_map.entities_len <= UXR_CONFIG_SHARED_MEMORY_MAX_ENTITIES - 1)
{
uxr_sm_map.entities[uxr_sm_map.entities_len].object_id = entity_id;
uxr_sm_map.entities[uxr_sm_map.entities_len].session = session;
uxr_sm_map.entities[uxr_sm_map.entities_len].type = UXR_SHARED_MEMORY_BIN_ENTITY;
uxrObjectId related_object_id;
switch (entity_id.type)
{
case UXR_DATAWRITER_ID:
related_object_id = uxr_object_id_from_raw(((OBJK_DataWriter_Binary*) entity)->topic_id.data);
uxr_sm_map.entities[uxr_sm_map.entities_len].data.datawriter = *((OBJK_DataWriter_Binary*) entity);
uxr_sm_map.entities[uxr_sm_map.entities_len].related_topic = uxr_shared_memory_get_entity(session,
&related_object_id);
break;
case UXR_DATAREADER_ID:
related_object_id = uxr_object_id_from_raw(((OBJK_DataReader_Binary*) entity)->topic_id.data);
uxr_sm_map.entities[uxr_sm_map.entities_len].data.datareader = *((OBJK_DataReader_Binary*) entity);
uxr_sm_map.entities[uxr_sm_map.entities_len].related_topic = uxr_shared_memory_get_entity(session,
&related_object_id);
break;
case UXR_REQUESTER_ID:
uxr_sm_map.entities[uxr_sm_map.entities_len].type = UXR_SHARED_MEMORY_HASH_ENTITY;
uxr_generate_hash_from_strings(
uxr_sm_map.entities[uxr_sm_map.entities_len].data.hash, 5,
((OBJK_Requester_Binary*) entity)->service_name,
((OBJK_Requester_Binary*) entity)->request_type,
((OBJK_Requester_Binary*) entity)->reply_type,
((OBJK_Requester_Binary*) entity)->request_topic_name,
((OBJK_Requester_Binary*) entity)->reply_topic_name);
uxr_sm_map.entities[uxr_sm_map.entities_len].related_topic = NULL;
break;
case UXR_REPLIER_ID:
uxr_sm_map.entities[uxr_sm_map.entities_len].type = UXR_SHARED_MEMORY_HASH_ENTITY;
uxr_generate_hash_from_strings(
uxr_sm_map.entities[uxr_sm_map.entities_len].data.hash, 5,
((OBJK_Replier_Binary*) entity)->service_name,
((OBJK_Replier_Binary*) entity)->request_type,
((OBJK_Replier_Binary*) entity)->reply_type,
((OBJK_Replier_Binary*) entity)->request_topic_name,
((OBJK_Replier_Binary*) entity)->reply_topic_name);
uxr_sm_map.entities[uxr_sm_map.entities_len].related_topic = NULL;
break;
case UXR_TOPIC_ID:
uxr_sm_map.entities[uxr_sm_map.entities_len].type = UXR_SHARED_MEMORY_HASH_ENTITY;
uxr_generate_hash_from_strings(
uxr_sm_map.entities[uxr_sm_map.entities_len].data.hash, 2,
((OBJK_Topic_Binary*) entity)->topic_name,
((OBJK_Topic_Binary*) entity)->type_name);
uxr_sm_map.entities[uxr_sm_map.entities_len].related_topic = NULL;
default:
break;
}
uxr_sm_map.entities_len++;
uxr_update_shared_memory_matching();
}
UXR_UNLOCK(&uxr_sm_map.lock);
}

View File

@ -0,0 +1,72 @@
// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef UXR_CLIENT_PROFILE_SHARED_MEMORY_INTERNAL_H_
#define UXR_CLIENT_PROFILE_SHARED_MEMORY_INTERNAL_H_
#ifdef __cplusplus
extern "C"
{
#endif // ifdef __cplusplus
#include <uxr/client/config.h>
#include <uxr/client/visibility.h>
#include <uxr/client/core/session/session.h>
#include <uxr/client/profile/multithread/multithread.h>
#ifdef UCLIENT_PROFILE_SHARED_MEMORY
#define UXR_PREPARE_SHARED_MEMORY(a, b, c, d, e) uxr_prepare_shared_memory(a, b, c, d, e)
#define UXR_HANDLE_SHARED_MEMORY() uxr_handle_shared_memory()
#define UXR_ADD_SHARED_MEMORY_ENTITY_XML(a, b, c) uxr_add_shared_memory_entity_xml(a, b, c)
#define UXR_ADD_SHARED_MEMORY_ENTITY_BIN(a, b, c) uxr_add_shared_memory_entity_bin(a, b, (void*) c)
#define UXR_CLEAN_SHARED_MEMORY() uxr_clean_shared_memory()
#else // UCLIENT_PROFILE_SHARED_MEMORY
#define UXR_PREPARE_SHARED_MEMORY(a, b, c, d, e)
#define UXR_HANDLE_SHARED_MEMORY()
#define UXR_ADD_SHARED_MEMORY_ENTITY_XML(a, b, c)
#define UXR_ADD_SHARED_MEMORY_ENTITY_BIN(a, b, c)
#define UXR_CLEAN_SHARED_MEMORY()
#endif // UCLIENT_PROFILE_SHARED_MEMORY
void uxr_prepare_shared_memory(
uxrSession* session,
uxrObjectId entity_id,
ucdrBuffer* ub,
uint16_t data_size,
uint16_t request_id);
void uxr_handle_shared_memory();
void uxr_add_shared_memory_entity_xml(
uxrSession* session,
uxrObjectId entity_id,
const char* xml);
void uxr_add_shared_memory_entity_bin(
uxrSession* session,
uxrObjectId entity_id,
const void* entity);
void uxr_clean_shared_memory();
#ifdef __cplusplus
}
#endif // ifdef __cplusplus
#endif // UXR_CLIENT_PROFILE_SHARED_MEMORY_INTERNAL_H_

View File

@ -0,0 +1,80 @@
# Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
project(uxr_sharedmem_unitary_tests LANGUAGES C CXX)
include(ExternalProject)
ExternalProject_Add(uxr_sharedmem_project
SOURCE_DIR
${CMAKE_CURRENT_SOURCE_DIR}/../../
BINARY_DIR
${PROJECT_BINARY_DIR}/microxrcedds_client_sharedmem
INSTALL_DIR
${PROJECT_BINARY_DIR}/temp_install/sharedmem
CMAKE_CACHE_ARGS
-DUCLIENT_PROFILE_SHARED_MEMORY:BOOL=ON
-DUCLIENT_PROFILE_MULTITHREAD:BOOL=ON
-DUCLIENT_PROFILE_MATCHING:BOOL=ON
-DUCLIENT_SHARED_MEMORY_MAX_ENTITIES:STRING=30
-DUCLIENT_SHARED_MEMORY_STATIC_MEM_SIZE:STRING=30
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
BUILD_BYPRODUCTS ${PROJECT_BINARY_DIR}/temp_install/lib/sharedmem/libmicroxrcedds_client.a
BUILD_BYPRODUCTS ${PROJECT_BINARY_DIR}/temp_install/lib/sharedmem/libmicrocdr.a
)
ExternalProject_Get_Property(uxr_sharedmem_project INSTALL_DIR)
add_library(ucdr_sharedmem STATIC IMPORTED GLOBAL)
add_dependencies(ucdr_sharedmem uxr_sharedmem_project)
set_property(TARGET ucdr_sharedmem PROPERTY IMPORTED_LOCATION ${PROJECT_BINARY_DIR}/temp_install/sharedmem/lib/libmicrocdr.a)
add_library(uxr_sharedmem STATIC IMPORTED GLOBAL)
add_dependencies(uxr_sharedmem uxr_sharedmem_project)
target_link_libraries(uxr_sharedmem INTERFACE ucdr_sharedmem)
set_property(TARGET uxr_sharedmem PROPERTY IMPORTED_LOCATION ${PROJECT_BINARY_DIR}/temp_install/sharedmem/lib/libmicroxrcedds_client.a)
add_executable(sharedmem_test SharedMemory.cpp)
set_common_compile_options(sharedmem_test)
if(MSVC OR MSVC_IDE)
target_compile_options(sharedmem_test PRIVATE /wd4996)
endif()
add_gtest(sharedmem_test SOURCES SharedMemory.cpp)
target_link_libraries(sharedmem_test
PUBLIC
ucdr_sharedmem
uxr_sharedmem
PRIVATE
${GTEST_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
target_include_directories(sharedmem_test
PUBLIC
${PROJECT_BINARY_DIR}/temp_install/sharedmem/include
PRIVATE
${GTEST_INCLUDE_DIRS}
)
set_target_properties(sharedmem_test PROPERTIES
CXX_STANDARD
11
CXX_STANDARD_REQUIRED
YES
)

File diff suppressed because it is too large Load Diff