diff --git a/rcl/include/rcl/context.h b/rcl/include/rcl/context.h index ec5c89ff2..f07b291e0 100644 --- a/rcl/include/rcl/context.h +++ b/rcl/include/rcl/context.h @@ -240,6 +240,32 @@ RCL_WARN_UNUSED rcl_context_instance_id_t rcl_context_get_instance_id(rcl_context_t * context); +/// Returns the context domain id. +/** + * \pre If context is uninitialized, then it is undefined behavior. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes [1] + * Uses Atomics | No + * Lock-Free | No + * + * [1] Calling the function asynchronously with `rcl_init` or `rcl_shutdown` can result + * in the function sometimes succeeding and sometimes returning `RCL_RET_INVALID_ARGUMENT`. + * + * \param[in] context from which the domain id should be retrieved. + * \param[out] domain_id output variable where the domain id will be returned. + * \return RCL_RET_INVALID_ARGUMENT if `context` is invalid \ref `rcl_context_is_valid`, or + * \return RCL_RET_INVALID_ARGUMENT if `domain_id` is `NULL`, or + * \return RCL_RET_OK if the domain id was correctly retrieved. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_context_get_domain_id(rcl_context_t * context, size_t * domain_id); + /// Return `true` if the given context is currently valid, otherwise `false`. /** * If context is `NULL`, then `false` is returned. diff --git a/rcl/src/rcl/context.c b/rcl/src/rcl/context.c index 6ffde3613..3a8c6eec4 100644 --- a/rcl/src/rcl/context.c +++ b/rcl/src/rcl/context.c @@ -77,6 +77,17 @@ rcl_context_get_instance_id(rcl_context_t * context) return rcutils_atomic_load_uint64_t((atomic_uint_least64_t *)(&context->instance_id_storage)); } +rcl_ret_t +rcl_context_get_domain_id(rcl_context_t * context, size_t * domain_id) +{ + if (!rcl_context_is_valid(context)) { + return RCL_RET_INVALID_ARGUMENT; + } + RCL_CHECK_ARGUMENT_FOR_NULL(domain_id, RCL_RET_INVALID_ARGUMENT); + *domain_id = context->impl->rmw_context.actual_domain_id; + return RCL_RET_OK; +} + bool rcl_context_is_valid(rcl_context_t * context) { diff --git a/rcl/src/rcl/node.c b/rcl/src/rcl/node.c index 18347fcb1..fe8a947fb 100644 --- a/rcl/src/rcl/node.c +++ b/rcl/src/rcl/node.c @@ -56,7 +56,6 @@ extern "C" typedef struct rcl_node_impl_t { rcl_node_options_t options; - size_t actual_domain_id; rmw_node_t * rmw_node_handle; rcl_guard_condition_t * graph_guard_condition; const char * logger_name; @@ -120,7 +119,6 @@ rcl_node_init( rcl_context_t * context, const rcl_node_options_t * options) { - size_t domain_id = 0; const rmw_guard_condition_t * rmw_graph_guard_condition = NULL; rcl_guard_condition_options_t graph_guard_condition_options = rcl_guard_condition_get_default_options(); @@ -253,12 +251,8 @@ rcl_node_init( RCL_CHECK_FOR_NULL_WITH_MSG( node->impl->logger_name, "creating logger name failed", goto fail); - ret = rcl_init_options_get_domain_id(rcl_context_get_init_options(context), &domain_id); - if (RCL_RET_OK != ret) { - goto fail; - } - RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Using domain ID of '%zu'", domain_id); - node->impl->actual_domain_id = domain_id; + RCUTILS_LOG_DEBUG_NAMED( + ROS_PACKAGE_NAME, "Using domain ID of '%zu'", context->impl->rmw_context.actual_domain_id); node->impl->rmw_node_handle = rmw_create_node( &(node->context->impl->rmw_context), @@ -474,12 +468,14 @@ rcl_node_get_options(const rcl_node_t * node) rcl_ret_t rcl_node_get_domain_id(const rcl_node_t * node, size_t * domain_id) { - const rcl_node_options_t * node_options = rcl_node_get_options(node); - if (!node_options) { - return RCL_RET_NODE_INVALID; // error already set + if (!rcl_node_is_valid(node)) { + return RCL_RET_NODE_INVALID; } RCL_CHECK_ARGUMENT_FOR_NULL(domain_id, RCL_RET_INVALID_ARGUMENT); - *domain_id = node->impl->actual_domain_id; + rcl_ret_t ret = rcl_context_get_domain_id(node->context, domain_id); + if (RCL_RET_OK != ret) { + return ret; + } return RCL_RET_OK; } diff --git a/rcl/test/rcl/test_context.cpp b/rcl/test/rcl/test_context.cpp index 22cc6ff8b..7489e4b54 100644 --- a/rcl/test/rcl/test_context.cpp +++ b/rcl/test/rcl/test_context.cpp @@ -87,6 +87,28 @@ TEST_F(CLASSNAME(TestContextFixture, RMW_IMPLEMENTATION), nominal) { EXPECT_NE(instance_id, 0UL) << rcl_get_error_string().str; rcl_reset_error(); + // test rcl_context_get_domain_id + size_t domain_id; + + EXPECT_NO_MEMORY_OPERATIONS( + { + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, rcl_context_get_domain_id(&context, nullptr)); + }); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + + EXPECT_NO_MEMORY_OPERATIONS( + { + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, rcl_context_get_domain_id(nullptr, &domain_id)); + }); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + + EXPECT_NO_MEMORY_OPERATIONS( + { + EXPECT_EQ(RCL_RET_OK, rcl_context_get_domain_id(&context, &domain_id)); + }); + // test rcl_context_is_valid bool is_valid; EXPECT_NO_MEMORY_OPERATIONS( diff --git a/rcl/test/rcl/test_node.cpp b/rcl/test/rcl/test_node.cpp index 87817cae1..3ae5193ba 100644 --- a/rcl/test/rcl/test_node.cpp +++ b/rcl/test/rcl/test_node.cpp @@ -262,7 +262,7 @@ TEST_F(CLASSNAME(TestNodeFixture, RMW_IMPLEMENTATION), test_rcl_node_accessors) ASSERT_TRUE(rcl_error_is_set()); rcl_reset_error(); ret = rcl_node_get_domain_id(&invalid_node, &actual_domain_id); - EXPECT_EQ(RCL_RET_OK, ret); + EXPECT_EQ(RCL_RET_NODE_INVALID, ret); rcl_reset_error(); EXPECT_NO_MEMORY_OPERATIONS( { @@ -270,6 +270,14 @@ TEST_F(CLASSNAME(TestNodeFixture, RMW_IMPLEMENTATION), test_rcl_node_accessors) }); EXPECT_EQ(RCL_RET_OK, ret); EXPECT_EQ(42u, actual_domain_id); + actual_domain_id = 0u; + EXPECT_NO_MEMORY_OPERATIONS( + { + ret = rcl_context_get_domain_id(&context, &actual_domain_id); + }); + EXPECT_EQ(RCL_RET_OK, ret); + EXPECT_EQ(42u, actual_domain_id); + // Test rcl_node_get_rmw_handle(). rmw_node_t * node_handle; node_handle = rcl_node_get_rmw_handle(nullptr);