From d66880d68cde1b538307a2e8d39aab8a9b1132b3 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Tue, 6 Nov 2018 17:38:54 -0600 Subject: [PATCH 1/4] refactor init to allow options to be passed and to not be global Signed-off-by: William Woodall --- rmw/CMakeLists.txt | 1 + rmw/include/rmw/init.h | 134 ++++++++++++++++++++++++++++++++++++++++ rmw/include/rmw/rmw.h | 93 +++++++++++++++++++++++++--- rmw/include/rmw/types.h | 7 ++- rmw/src/init.c | 33 ++++++++++ 5 files changed, 260 insertions(+), 8 deletions(-) create mode 100644 rmw/include/rmw/init.h create mode 100644 rmw/src/init.c diff --git a/rmw/CMakeLists.txt b/rmw/CMakeLists.txt index 50d35ac0..4d64da44 100644 --- a/rmw/CMakeLists.txt +++ b/rmw/CMakeLists.txt @@ -27,6 +27,7 @@ include_directories(include) set(rmw_sources "src/allocators.c" "src/convert_rcutils_ret_to_rmw_ret.c" + "src/init.c" "src/names_and_types.c" "src/sanity_checks.c" "src/node_security_options.c" diff --git a/rmw/include/rmw/init.h b/rmw/include/rmw/init.h new file mode 100644 index 00000000..fc59b2a2 --- /dev/null +++ b/rmw/include/rmw/init.h @@ -0,0 +1,134 @@ +// Copyright 2014-2018 Open Source Robotics Foundation, Inc. +// +// 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 RMW__RMW_H_ +#define RMW__RMW_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#include "rmw/macros.h" +#include "rmw/types.h" +#include "rmw/visibility_control.h" + +/// Implementation defined options structure used during rmw_init(). +/** + * This should be defined by the rmw implementation. + */ +typedef struct rmw_init_options_impl_t rmw_init_options_impl_t; + +/// Options structure used during rmw_init(). +typedef struct RMW_PUBLIC_TYPE rmw_init_options_t { + /// Locally (process local) unique ID that represents this init/shutdown cycle. + /** + * This should be set by the caller of `rmw_init()` to a number that is + * unique within this process. + * It is designed to be used with `rcl_init()` and `rcl_get_instance_id()`. + */ + uint64_t instance_id; + /// Implementation defined init options. + rmw_init_options_impl_t * impl; +} rmw_init_options_t; + +/// Return the default init options. +/** + * This should be defined by the rmw implementation. + */ +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_init_options_t +rmw_get_default_init_options(void); + +/// Implementation defined context structure returned by rmw_init(). +/** + * This should be defined by the rmw implementation. + */ +typedef struct rmw_init_context_impl_t rmw_init_context_impl_t; + +/// Initialization context structure which is used to store init specific information. +typedef struct RMW_PUBLIC_TYPE rmw_init_context_t { + /// Locally (process local) unique ID that represents this init/shutdown cycle. + uint64_t instance_id; + /// Implementation defined init context information. + rmw_init_context_impl_t * impl; +} rmw_init_context_t; + +/// Return a zero initialized init context structure. +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_init_context_t +rmw_get_zero_initialized_init_context(void); + +/// Initialize the middleware with the given options, and yielding an init context. +/** + * The given init context must be zero initialized, and is filled with + * middleware specific data upon success of this function. + * The init context is used when initializing some entities like nodes and + * guard conditions, and is also required to properly call rmw_shutdown(). + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * This should be defined by the rmw implementation. + * + * \param[in] options initialization options to be used during initialization + * \param[out] context resulting context struct + * \return `RMW_RET_OK` if successful, or + * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are null or invalid, or + * \return `RMW_RET_ERROR` if an unexpected error occurs. + */ +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_ret_t +rmw_init(const rmw_init_options_t * options, rmw_init_context_t * context); + +/// Shutdown the middleware for a given init context. +/** + * The given init context must be a valid context which has been initialized + * with rmw_init(). + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * This should be defined by the rmw implementation. + * + * \param[in] context resulting context struct + * \return `RMW_RET_OK` if successful, or + * \return `RMW_RET_INVALID_ARGUMENT` if the argument is null or invalid, or + * \return `RMW_RET_ERROR` if an unexpected error occurs. + */ +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_ret_t +rmw_shutdown(rmw_init_context_t * context); + +#ifdef __cplusplus +} +#endif + +#endif // RMW__RMW_H_ diff --git a/rmw/include/rmw/rmw.h b/rmw/include/rmw/rmw.h index afb509c3..968994fc 100644 --- a/rmw/include/rmw/rmw.h +++ b/rmw/include/rmw/rmw.h @@ -17,6 +17,8 @@ * `rmw` defines an interface of middleware primitives that are used by the higher level ROS API's. * It consists of these main components: * + * - Initialization and Shutdown: + * - rmw/init.h * - Nodes * - rmw/rmw.h * - Publisher @@ -90,6 +92,7 @@ extern "C" #include "rosidl_generator_c/message_type_support_struct.h" #include "rosidl_generator_c/service_type_support_struct.h" +#include "rmw/init.h" #include "rmw/macros.h" #include "rmw/qos_profiles.h" #include "rmw/types.h" @@ -117,20 +120,63 @@ RMW_WARN_UNUSED const char * rmw_get_serialization_format(void); -RMW_PUBLIC -RMW_WARN_UNUSED -rmw_ret_t -rmw_init(void); - +// TODO(wjwwood): refactor this API to return a return code when updated to use an allocator +/// Create a node and return a handle to that node. +/** + * This function can fail, and therefore return `NULL`, if: + * - init_context, name, namespace_, or security_options is `NULL` + * - init_context, security_options is invalid + * - memory allocation fails during node creation + * - an unspecified error occurs + * + * The init_context must be non-null and valid, i.e. it has been initialized + * by `rmw_init()` and has not been finalized by `rmw_shutdown()`. + * + * The name and namespace_ should be valid node name and namespace, + * and this should be asserted by the caller (e.g. `rcl`). + * + * The domain ID should be used to physically separate nodes at the + * communication graph level by the middleware. + * For RTPS/DDS this maps naturally to their concept of domain id. + * + * The security options should always be non-null and encapsulate the + * essential security configurations for the node and its entities. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No [1] + * Lock-Free | No [1] + * [1] rmw implementation defined, check the implementation documentation + * + * This should be defined by the rmw implementation. + * + * \param[in] init_context init context that this node should be associated with + * \param[in] name the node name + * \param[in] namespace_ the node namespace + * \param[in] domain_id the id of the domain that the node should join + * \param[in] security_options the security configurations for the node + * \return rmw node handle or `NULL` if there was an error + */ RMW_PUBLIC RMW_WARN_UNUSED rmw_node_t * rmw_create_node( + rmw_init_context_t * init_context, const char * name, const char * namespace_, size_t domain_id, const rmw_node_security_options_t * security_options); +/// Finalize a given node handle, reclaim the resources, and deallocate the node handle. +/** + * \param node the node handle to be destroyed + * \return `RMW_RET_OK` if successful, or + * \return `RMW_RET_INVALID_ARGUMENT` if node is null, or + * \return `RMW_RET_ERROR` if an unexpected error occurs. + */ RMW_PUBLIC RMW_WARN_UNUSED rmw_ret_t @@ -162,7 +208,6 @@ rmw_destroy_node(rmw_node_t * node); * * \param[in] node pointer to the rmw node * \return rmw guard condition handle if successful, otherwise `NULL` - * */ RMW_PUBLIC RMW_WARN_UNUSED @@ -425,11 +470,45 @@ rmw_send_response( rmw_request_id_t * request_header, void * ros_response); +// TODO(wjwwood): refactor this API to return a return code when updated to use an allocator +/// Create a guard condition and return a handle to that guard condition. +/** + * This function can fail, and therefore return `NULL`, if: + * - init_context is `NULL` + * - init_context is invalid + * - memory allocation fails during guard condition creation + * - an unspecified error occurs + * + * The init_context must be non-null and valid, i.e. it has been initialized + * by `rmw_init()` and has not been finalized by `rmw_shutdown()`. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No [1] + * Lock-Free | No [1] + * [1] rmw implementation defined, check the implementation documentation + * + * This should be defined by the rmw implementation. + * + * \param[in] init_context init context that this node should be associated with + * \return rmw guard condition handle or `NULL` if there was an error + */ RMW_PUBLIC RMW_WARN_UNUSED rmw_guard_condition_t * -rmw_create_guard_condition(void); +rmw_create_guard_condition(rmw_init_context_t * init_context); + +/// Finalize a given guard condition handle, reclaim the resources, and deallocate the handle. +/** + * \param guard_condition the guard condition handle to be destroyed + * \return `RMW_RET_OK` if successful, or + * \return `RMW_RET_INVALID_ARGUMENT` if guard_condition is null, or + * \return `RMW_RET_ERROR` if an unexpected error occurs. + */ RMW_PUBLIC RMW_WARN_UNUSED rmw_ret_t diff --git a/rmw/include/rmw/types.h b/rmw/include/rmw/types.h index b484147c..0a74df98 100644 --- a/rmw/include/rmw/types.h +++ b/rmw/include/rmw/types.h @@ -44,12 +44,16 @@ typedef int rmw_ret_t; // implementation. It may need to be increased in the future. #define RMW_GID_STORAGE_SIZE 24 +// forward declaration to avoid circular dependency +typedef struct rmw_init_context_t rmw_init_context_t; + typedef struct RMW_PUBLIC_TYPE rmw_node_t { const char * implementation_identifier; void * data; const char * name; const char * namespace_; + rmw_init_context_t * init_context; } rmw_node_t; typedef struct RMW_PUBLIC_TYPE rmw_publisher_t @@ -84,9 +88,10 @@ typedef struct RMW_PUBLIC_TYPE rmw_guard_condition_t { const char * implementation_identifier; void * data; + rmw_init_context_t * init_context; } rmw_guard_condition_t; -/// Array of subsciber handles. +/// Array of subscriber handles. /** * An array of void * pointers representing type-erased middleware-specific subscriptions. * The number of non-null entries may be smaller than the allocated size of the array. diff --git a/rmw/src/init.c b/rmw/src/init.c new file mode 100644 index 00000000..b0ffedeb --- /dev/null +++ b/rmw/src/init.c @@ -0,0 +1,33 @@ +// Copyright 2018 Open Source Robotics Foundation, Inc. +// +// 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. + +#include "rmw/init.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +rmw_init_context_t +rmw_get_zero_initialized_init_context(void) +{ + return (const rmw_init_context_t) { + .instance_id = 0, + .impl = NULL + }; +} + +#ifdef __cplusplus +} +#endif From 098a6d1ffb3ad9170207bdef2e87a856cd128fbb Mon Sep 17 00:00:00 2001 From: William Woodall Date: Tue, 6 Nov 2018 21:01:20 -0600 Subject: [PATCH 2/4] use implementation identifier in init and shutdown functions Signed-off-by: William Woodall --- rmw/include/rmw/init.h | 8 ++++++++ rmw/include/rmw/types.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/rmw/include/rmw/init.h b/rmw/include/rmw/init.h index fc59b2a2..4312700f 100644 --- a/rmw/include/rmw/init.h +++ b/rmw/include/rmw/init.h @@ -41,6 +41,8 @@ typedef struct RMW_PUBLIC_TYPE rmw_init_options_t { * It is designed to be used with `rcl_init()` and `rcl_get_instance_id()`. */ uint64_t instance_id; + /// Implementation identifier, used to ensure two different implementations are not being mixed. + const char * implementation_identifier; /// Implementation defined init options. rmw_init_options_impl_t * impl; } rmw_init_options_t; @@ -64,6 +66,8 @@ typedef struct rmw_init_context_impl_t rmw_init_context_impl_t; typedef struct RMW_PUBLIC_TYPE rmw_init_context_t { /// Locally (process local) unique ID that represents this init/shutdown cycle. uint64_t instance_id; + /// Implementation identifier, used to ensure two different implementations are not being mixed. + const char * implementation_identifier; /// Implementation defined init context information. rmw_init_context_impl_t * impl; } rmw_init_context_t; @@ -94,6 +98,8 @@ rmw_get_zero_initialized_init_context(void); * \param[in] options initialization options to be used during initialization * \param[out] context resulting context struct * \return `RMW_RET_OK` if successful, or + * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the implementation + * identifier does not match, or * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are null or invalid, or * \return `RMW_RET_ERROR` if an unexpected error occurs. */ @@ -119,6 +125,8 @@ rmw_init(const rmw_init_options_t * options, rmw_init_context_t * context); * * \param[in] context resulting context struct * \return `RMW_RET_OK` if successful, or + * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the implementation + * identifier does not match, or * \return `RMW_RET_INVALID_ARGUMENT` if the argument is null or invalid, or * \return `RMW_RET_ERROR` if an unexpected error occurs. */ diff --git a/rmw/include/rmw/types.h b/rmw/include/rmw/types.h index 0a74df98..52c008b0 100644 --- a/rmw/include/rmw/types.h +++ b/rmw/include/rmw/types.h @@ -39,6 +39,8 @@ typedef int rmw_ret_t; #define RMW_RET_BAD_ALLOC 10 /// Invalid argument return code. #define RMW_RET_INVALID_ARGUMENT 11 +/// Incorrect rmw implementation. +#define RMW_RET_INCORRECT_RMW_IMPLEMENTATION 12 // 24 bytes is the most memory needed to represent the GID by any current // implementation. It may need to be increased in the future. From 3159283fc4fc6ce4684415dae7c9ad6b44d29335 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Thu, 8 Nov 2018 11:46:05 -0600 Subject: [PATCH 3/4] refactors and renames Signed-off-by: William Woodall --- rmw/include/rmw/init.h | 26 ++++++++++++----------- rmw/include/rmw/ret_types.h | 41 +++++++++++++++++++++++++++++++++++++ rmw/include/rmw/rmw.h | 20 +++++++++--------- rmw/include/rmw/types.h | 21 ++++--------------- rmw/src/init.c | 8 +++++--- 5 files changed, 74 insertions(+), 42 deletions(-) create mode 100644 rmw/include/rmw/ret_types.h diff --git a/rmw/include/rmw/init.h b/rmw/include/rmw/init.h index 4312700f..ce38615f 100644 --- a/rmw/include/rmw/init.h +++ b/rmw/include/rmw/init.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef RMW__RMW_H_ -#define RMW__RMW_H_ +#ifndef RMW__INIT_H_ +#define RMW__INIT_H_ #ifdef __cplusplus extern "C" @@ -23,7 +23,7 @@ extern "C" #include #include "rmw/macros.h" -#include "rmw/types.h" +#include "rmw/ret_types.h" #include "rmw/visibility_control.h" /// Implementation defined options structure used during rmw_init(). @@ -44,6 +44,7 @@ typedef struct RMW_PUBLIC_TYPE rmw_init_options_t { /// Implementation identifier, used to ensure two different implementations are not being mixed. const char * implementation_identifier; /// Implementation defined init options. + /** May be NULL if there are no implementation defined options. */ rmw_init_options_impl_t * impl; } rmw_init_options_t; @@ -60,23 +61,24 @@ rmw_get_default_init_options(void); /** * This should be defined by the rmw implementation. */ -typedef struct rmw_init_context_impl_t rmw_init_context_impl_t; +typedef struct rmw_context_impl_t rmw_context_impl_t; /// Initialization context structure which is used to store init specific information. -typedef struct RMW_PUBLIC_TYPE rmw_init_context_t { +typedef struct RMW_PUBLIC_TYPE rmw_context_t { /// Locally (process local) unique ID that represents this init/shutdown cycle. uint64_t instance_id; /// Implementation identifier, used to ensure two different implementations are not being mixed. const char * implementation_identifier; /// Implementation defined init context information. - rmw_init_context_impl_t * impl; -} rmw_init_context_t; + /** May be NULL if there is no implementation defined context information. */ + rmw_context_impl_t * impl; +} rmw_context_t; /// Return a zero initialized init context structure. RMW_PUBLIC RMW_WARN_UNUSED -rmw_init_context_t -rmw_get_zero_initialized_init_context(void); +rmw_context_t +rmw_get_zero_initialized_context(void); /// Initialize the middleware with the given options, and yielding an init context. /** @@ -106,7 +108,7 @@ rmw_get_zero_initialized_init_context(void); RMW_PUBLIC RMW_WARN_UNUSED rmw_ret_t -rmw_init(const rmw_init_options_t * options, rmw_init_context_t * context); +rmw_init(const rmw_init_options_t * options, rmw_context_t * context); /// Shutdown the middleware for a given init context. /** @@ -133,10 +135,10 @@ rmw_init(const rmw_init_options_t * options, rmw_init_context_t * context); RMW_PUBLIC RMW_WARN_UNUSED rmw_ret_t -rmw_shutdown(rmw_init_context_t * context); +rmw_shutdown(rmw_context_t * context); #ifdef __cplusplus } #endif -#endif // RMW__RMW_H_ +#endif // RMW__INIT_H_ diff --git a/rmw/include/rmw/ret_types.h b/rmw/include/rmw/ret_types.h new file mode 100644 index 00000000..32179c78 --- /dev/null +++ b/rmw/include/rmw/ret_types.h @@ -0,0 +1,41 @@ +// Copyright 2014-2018 Open Source Robotics Foundation, Inc. +// +// 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 RMW__RET_TYPES_H_ +#define RMW__RET_TYPES_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +typedef int32_t rmw_ret_t; +#define RMW_RET_OK 0 +#define RMW_RET_ERROR 1 +#define RMW_RET_TIMEOUT 2 + +/// Failed to allocate memory return code. +#define RMW_RET_BAD_ALLOC 10 +/// Invalid argument return code. +#define RMW_RET_INVALID_ARGUMENT 11 +/// Incorrect rmw implementation. +#define RMW_RET_INCORRECT_RMW_IMPLEMENTATION 12 + +#ifdef __cplusplus +} +#endif + +#endif // RMW__RET_TYPES_H_ diff --git a/rmw/include/rmw/rmw.h b/rmw/include/rmw/rmw.h index 968994fc..a47767d2 100644 --- a/rmw/include/rmw/rmw.h +++ b/rmw/include/rmw/rmw.h @@ -124,12 +124,12 @@ rmw_get_serialization_format(void); /// Create a node and return a handle to that node. /** * This function can fail, and therefore return `NULL`, if: - * - init_context, name, namespace_, or security_options is `NULL` - * - init_context, security_options is invalid + * - context, name, namespace_, or security_options is `NULL` + * - context, security_options is invalid * - memory allocation fails during node creation * - an unspecified error occurs * - * The init_context must be non-null and valid, i.e. it has been initialized + * The context must be non-null and valid, i.e. it has been initialized * by `rmw_init()` and has not been finalized by `rmw_shutdown()`. * * The name and namespace_ should be valid node name and namespace, @@ -153,7 +153,7 @@ rmw_get_serialization_format(void); * * This should be defined by the rmw implementation. * - * \param[in] init_context init context that this node should be associated with + * \param[in] context init context that this node should be associated with * \param[in] name the node name * \param[in] namespace_ the node namespace * \param[in] domain_id the id of the domain that the node should join @@ -164,7 +164,7 @@ RMW_PUBLIC RMW_WARN_UNUSED rmw_node_t * rmw_create_node( - rmw_init_context_t * init_context, + rmw_context_t * context, const char * name, const char * namespace_, size_t domain_id, @@ -474,12 +474,12 @@ rmw_send_response( /// Create a guard condition and return a handle to that guard condition. /** * This function can fail, and therefore return `NULL`, if: - * - init_context is `NULL` - * - init_context is invalid + * - context is `NULL` + * - context is invalid * - memory allocation fails during guard condition creation * - an unspecified error occurs * - * The init_context must be non-null and valid, i.e. it has been initialized + * The context must be non-null and valid, i.e. it has been initialized * by `rmw_init()` and has not been finalized by `rmw_shutdown()`. * *
@@ -493,13 +493,13 @@ rmw_send_response( * * This should be defined by the rmw implementation. * - * \param[in] init_context init context that this node should be associated with + * \param[in] context init context that this node should be associated with * \return rmw guard condition handle or `NULL` if there was an error */ RMW_PUBLIC RMW_WARN_UNUSED rmw_guard_condition_t * -rmw_create_guard_condition(rmw_init_context_t * init_context); +rmw_create_guard_condition(rmw_context_t * context); /// Finalize a given guard condition handle, reclaim the resources, and deallocate the handle. diff --git a/rmw/include/rmw/types.h b/rmw/include/rmw/types.h index 52c008b0..577205b5 100644 --- a/rmw/include/rmw/types.h +++ b/rmw/include/rmw/types.h @@ -27,35 +27,22 @@ extern "C" // map rcutils specific log levels to rmw speicfic type #include +#include "rmw/init.h" +#include "rmw/ret_types.h" #include "rmw/serialized_message.h" #include "rmw/visibility_control.h" -typedef int rmw_ret_t; -#define RMW_RET_OK 0 -#define RMW_RET_ERROR 1 -#define RMW_RET_TIMEOUT 2 - -/// Failed to allocate memory return code. -#define RMW_RET_BAD_ALLOC 10 -/// Invalid argument return code. -#define RMW_RET_INVALID_ARGUMENT 11 -/// Incorrect rmw implementation. -#define RMW_RET_INCORRECT_RMW_IMPLEMENTATION 12 - // 24 bytes is the most memory needed to represent the GID by any current // implementation. It may need to be increased in the future. #define RMW_GID_STORAGE_SIZE 24 -// forward declaration to avoid circular dependency -typedef struct rmw_init_context_t rmw_init_context_t; - typedef struct RMW_PUBLIC_TYPE rmw_node_t { const char * implementation_identifier; void * data; const char * name; const char * namespace_; - rmw_init_context_t * init_context; + rmw_context_t * context; } rmw_node_t; typedef struct RMW_PUBLIC_TYPE rmw_publisher_t @@ -90,7 +77,7 @@ typedef struct RMW_PUBLIC_TYPE rmw_guard_condition_t { const char * implementation_identifier; void * data; - rmw_init_context_t * init_context; + rmw_context_t * context; } rmw_guard_condition_t; /// Array of subscriber handles. diff --git a/rmw/src/init.c b/rmw/src/init.c index b0ffedeb..7c8f0450 100644 --- a/rmw/src/init.c +++ b/rmw/src/init.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "rmw/init.h" #ifdef __cplusplus @@ -19,10 +21,10 @@ extern "C" { #endif -rmw_init_context_t -rmw_get_zero_initialized_init_context(void) +rmw_context_t +rmw_get_zero_initialized_context(void) { - return (const rmw_init_context_t) { + return (const rmw_context_t) { .instance_id = 0, .impl = NULL }; From ff6c94620df3cf513952196df91d1ef172e8fe99 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Mon, 19 Nov 2018 16:49:23 -0600 Subject: [PATCH 4/4] refactor init_options into its own files Signed-off-by: William Woodall --- rmw/CMakeLists.txt | 1 + rmw/include/rmw/init.h | 49 +++------- rmw/include/rmw/init_options.h | 159 +++++++++++++++++++++++++++++++++ rmw/src/init.c | 6 +- rmw/src/init_options.c | 36 ++++++++ 5 files changed, 209 insertions(+), 42 deletions(-) create mode 100644 rmw/include/rmw/init_options.h create mode 100644 rmw/src/init_options.c diff --git a/rmw/CMakeLists.txt b/rmw/CMakeLists.txt index 4d64da44..cf643706 100644 --- a/rmw/CMakeLists.txt +++ b/rmw/CMakeLists.txt @@ -28,6 +28,7 @@ set(rmw_sources "src/allocators.c" "src/convert_rcutils_ret_to_rmw_ret.c" "src/init.c" + "src/init_options.c" "src/names_and_types.c" "src/sanity_checks.c" "src/node_security_options.c" diff --git a/rmw/include/rmw/init.h b/rmw/include/rmw/init.h index ce38615f..5d4426b9 100644 --- a/rmw/include/rmw/init.h +++ b/rmw/include/rmw/init.h @@ -22,41 +22,11 @@ extern "C" #include +#include "rmw/init_options.h" #include "rmw/macros.h" #include "rmw/ret_types.h" #include "rmw/visibility_control.h" -/// Implementation defined options structure used during rmw_init(). -/** - * This should be defined by the rmw implementation. - */ -typedef struct rmw_init_options_impl_t rmw_init_options_impl_t; - -/// Options structure used during rmw_init(). -typedef struct RMW_PUBLIC_TYPE rmw_init_options_t { - /// Locally (process local) unique ID that represents this init/shutdown cycle. - /** - * This should be set by the caller of `rmw_init()` to a number that is - * unique within this process. - * It is designed to be used with `rcl_init()` and `rcl_get_instance_id()`. - */ - uint64_t instance_id; - /// Implementation identifier, used to ensure two different implementations are not being mixed. - const char * implementation_identifier; - /// Implementation defined init options. - /** May be NULL if there are no implementation defined options. */ - rmw_init_options_impl_t * impl; -} rmw_init_options_t; - -/// Return the default init options. -/** - * This should be defined by the rmw implementation. - */ -RMW_PUBLIC -RMW_WARN_UNUSED -rmw_init_options_t -rmw_get_default_init_options(void); - /// Implementation defined context structure returned by rmw_init(). /** * This should be defined by the rmw implementation. @@ -64,27 +34,28 @@ rmw_get_default_init_options(void); typedef struct rmw_context_impl_t rmw_context_impl_t; /// Initialization context structure which is used to store init specific information. -typedef struct RMW_PUBLIC_TYPE rmw_context_t { +typedef struct RMW_PUBLIC_TYPE rmw_context_t +{ /// Locally (process local) unique ID that represents this init/shutdown cycle. uint64_t instance_id; /// Implementation identifier, used to ensure two different implementations are not being mixed. const char * implementation_identifier; - /// Implementation defined init context information. + /// Implementation defined context information. /** May be NULL if there is no implementation defined context information. */ rmw_context_impl_t * impl; } rmw_context_t; -/// Return a zero initialized init context structure. +/// Return a zero initialized context structure. RMW_PUBLIC RMW_WARN_UNUSED rmw_context_t rmw_get_zero_initialized_context(void); -/// Initialize the middleware with the given options, and yielding an init context. +/// Initialize the middleware with the given options, and yielding an context. /** - * The given init context must be zero initialized, and is filled with + * The given context must be zero initialized, and is filled with * middleware specific data upon success of this function. - * The init context is used when initializing some entities like nodes and + * The context is used when initializing some entities like nodes and * guard conditions, and is also required to properly call rmw_shutdown(). * *
@@ -110,9 +81,9 @@ RMW_WARN_UNUSED rmw_ret_t rmw_init(const rmw_init_options_t * options, rmw_context_t * context); -/// Shutdown the middleware for a given init context. +/// Shutdown the middleware for a given context. /** - * The given init context must be a valid context which has been initialized + * The given context must be a valid context which has been initialized * with rmw_init(). * *
diff --git a/rmw/include/rmw/init_options.h b/rmw/include/rmw/init_options.h new file mode 100644 index 00000000..8d8a64cc --- /dev/null +++ b/rmw/include/rmw/init_options.h @@ -0,0 +1,159 @@ +// Copyright 2014-2018 Open Source Robotics Foundation, Inc. +// +// 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 RMW__INIT_OPTIONS_H_ +#define RMW__INIT_OPTIONS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#include "rcutils/allocator.h" +#include "rmw/macros.h" +#include "rmw/ret_types.h" +#include "rmw/visibility_control.h" + +/// Implementation defined options structure used during rmw_init(). +/** + * This should be defined by the rmw implementation. + */ +typedef struct rmw_init_options_impl_t rmw_init_options_impl_t; + +/// Options structure used during rmw_init(). +typedef struct RMW_PUBLIC_TYPE rmw_init_options_t +{ + /// Locally (process local) unique ID that represents this init/shutdown cycle. + /** + * This should be set by the caller of `rmw_init()` to a number that is + * unique within this process. + * It is designed to be used with `rcl_init()` and `rcl_get_instance_id()`. + */ + uint64_t instance_id; + /// Implementation identifier, used to ensure two different implementations are not being mixed. + const char * implementation_identifier; + // TODO(wjwwood): replace with rmw_allocator_t when that refactor happens + /// Allocator used during internal allocation of init options, if needed. + rcutils_allocator_t allocator; + /// Implementation defined init options. + /** May be NULL if there are no implementation defined options. */ + rmw_init_options_impl_t * impl; +} rmw_init_options_t; + +/// Return a zero initialized init options structure. +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_init_options_t +rmw_get_zero_initialized_init_options(void); + +/// Initialize given init_options with the default values and implementation specific values. +/** + * The given allocator is used, if required, during setup of the init options, + * but is also used during initialization. + * + * In either case the given allocator is stored in the returned init options. + * + * The `impl` pointer should not be changed manually. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | Yes + * Lock-Free | Yes + * + * This should be defined by the rmw implementation. + * + * \param[inout] init_options object to be setup + * \param[in] allocator to be used during setup and during initialization + * \return `RMW_RET_OK` if setup is successful, or + * \return `RMW_RET_INVALID_ARGUMENT` if init_options has already be initialized, or + * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or + * \return `RMW_RET_BAD_ALLOC` if allocating memory failed, or + * \return `RMW_RET_ERROR` if an unspecified error occurs. + */ +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_ret_t +rmw_init_options_init(rmw_init_options_t * init_options, rcutils_allocator_t allocator); + +/// Copy the given source init options to the destination init options. +/** + * The allocator from the source is used for any allocations and stored in the + * destination. + * + * The destination should either be zero initialized with + * `rmw_get_zero_initialized_init_options()` or should have had + * `rmw_init_options_fini()` called on it. + * Giving an already initialized init options for the destination will result + * in a failure with return code `RMW_RET_INVALID_ARGUMENT`. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | Yes + * Lock-Free | Yes + * + * This should be defined by the rmw implementation. + * + * \param[in] src rcl_init_options_t object to be copied from + * \param[out] dst rcl_init_options_t object to be copied into + * \return `RMW_RET_OK` if the copy is successful, or + * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the implementation + * identifier for src does not match the implementation of this function, or + * \return `RMW_RET_INVALID_ARGUMENT` if the dst has already be initialized, or + * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or + * \return `RMW_RET_BAD_ALLOC` if allocating memory failed, or + * \return `RMW_RET_ERROR` if an unspecified error occurs. + */ +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_ret_t +rmw_init_options_copy(const rmw_init_options_t * src, rmw_init_options_t * dst); + +/// Finalize the given init_options. +/** + * The given init_options must be non-`NULL` and valid, i.e. had + * `rmw_init_options_init()` called on it but not this function yet. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | Yes + * Lock-Free | Yes + * + * This should be defined by the rmw implementation. + * + * \param[inout] init_options object to be setup + * \return `RMW_RET_OK` if setup is successful, or + * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or + * \return `RMW_RET_ERROR` if an unspecified error occurs. + */ +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_ret_t +rmw_init_options_fini(rmw_init_options_t * init_options); + +#ifdef __cplusplus +} +#endif + +#endif // RMW__INIT_OPTIONS_H_ diff --git a/rmw/src/init.c b/rmw/src/init.c index 7c8f0450..7e0136a9 100644 --- a/rmw/src/init.c +++ b/rmw/src/init.c @@ -25,9 +25,9 @@ rmw_context_t rmw_get_zero_initialized_context(void) { return (const rmw_context_t) { - .instance_id = 0, - .impl = NULL - }; + .instance_id = 0, + .impl = NULL + }; // NOLINT(readability/braces): false positive } #ifdef __cplusplus diff --git a/rmw/src/init_options.c b/rmw/src/init_options.c new file mode 100644 index 00000000..de7701c2 --- /dev/null +++ b/rmw/src/init_options.c @@ -0,0 +1,36 @@ +// Copyright 2018 Open Source Robotics Foundation, Inc. +// +// 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. + +#include + +#include "rmw/init_options.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +rmw_init_options_t +rmw_get_zero_initialized_init_options(void) +{ + return (const rmw_init_options_t) { + .instance_id = 0, + .implementation_identifier = NULL, + .impl = NULL, + }; // NOLINT(readability/braces): false positive +} + +#ifdef __cplusplus +} +#endif