diff --git a/rmw/include/rmw/get_node_info_and_types.h b/rmw/include/rmw/get_node_info_and_types.h
index e0924574..98d85fce 100644
--- a/rmw/include/rmw/get_node_info_and_types.h
+++ b/rmw/include/rmw/get_node_info_and_types.h
@@ -25,28 +25,66 @@ extern "C"
#include "rmw/types.h"
#include "rmw/visibility_control.h"
-/// Return a list of subscribed topic names and their types.
+/// Return all topic names and types for which a given remote node has subscriptions.
/**
- * This function returns a list of subscribed topic names and their types.
- *
- * The node parameter must not be `NULL`, and must point to a valid node.
- *
- * The topic_names_and_types parameter must be allocated and zero initialized.
- * The topic_names_and_types is the output for this function, and contains
- * allocated memory.
- * Therefore, it should be passed to rmw_names_and_types_fini() when
- * it is no longer needed.
- * Failing to do so will result in leaked memory.
- *
- * \param[in] node the handle to the node being used to query the ROS graph
- * \param[in] allocator allocator to be used when allocating space for strings
- * \param[in] node_name the name of the node to get information for
- * \param[in] node_namespace the namespace of the node to get information for
- * \param[in] no_demangle if true, list all topics without any demangling
- * \param[out] topic_names_and_types list of topic names and their types the node_name is subscribed to
+ * This function returns an array of topic names and types for which a given remote
+ * node has subscriptions, as discovered so far by the given local node.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined, check the implementation documentation
+ *
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
+ *
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, when querying subscribed topic names and types:
+ * - Access to the array of names and types is not synchronized.
+ * It is not safe to read or write `topic_names_and_types`
+ * while rmw_get_subscriber_names_and_types_by_node() uses it.
+ * - Access to node name and namespace is read-only but it is not synchronized.
+ * Concurrent `node_name` and `node_namespace` reads are safe, but concurrent reads and
+ * writes are not.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
+ *
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ * \pre Given `topic_names_and_types` must be a zero-initialized array of names and types,
+ * as returned by rmw_get_zero_initialized_names_and_types().
+ *
+ * \param[in] node Local node to query the ROS graph.
+ * \param[in] allocator Allocator to be used when populating the `topic_names_and_types` array.
+ * \param[in] node_name Name of the remote node to get information for.
+ * \param[in] node_namespace Namespace of the remote node to get information for.
+ * \param[in] no_demangle Whether to demangle all topic names following ROS conventions or not.
+ * \param[out] topic_names_and_types Array of topic names and types the remote node has created
+ * a subscription for, populated on success but left unchanged on failure.
+ * If populated, it is up to the caller to finalize this array later on
+ * using rmw_names_and_types_fini().
* \return `RMW_RET_OK` if the query was successful, or
- * \return `RMW_RET_INVALID_ARGUMENT` if the node is invalid, or
- * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `allocator` is not valid,
+ * by rcutils_allocator_is_valid() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_name` is not valid,
+ * by rmw_validate_node_name() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_namespace` is not valid,
+ * by rmw_validate_namespace() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_names_and_types` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_names_and_types` is not a
+ * zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
* \return `RMW_RET_NODE_NAME_NON_EXISTENT` if the node name wasn't found, or
* \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
@@ -60,30 +98,68 @@ rmw_get_subscriber_names_and_types_by_node(
const char * node_name,
const char * node_namespace,
bool no_demangle,
- rmw_names_and_types_t * topics_names_and_types);
+ rmw_names_and_types_t * topic_names_and_types);
-/// Return a list of published topic names and their types.
+/// Return all topic names and types for which a given remote node has publishers.
/**
- * This function returns a list of published topic names and their types.
- *
- * The node parameter must not be `NULL`, and must point to a valid node.
- *
- * The topic_names_and_types parameter must be allocated and zero initialized.
- * The topic_names_and_types is the output for this function, and contains
- * allocated memory.
- * Therefore, it should be passed to rmw_names_and_types_fini() when
- * it is no longer needed.
- * Failing to do so will result in leaked memory.
- *
- * \param[in] node the handle to the node being used to query the ROS graph
- * \param[in] allocator allocator to be used when allocating space for strings
- * \param[in] node_name the name of the node to get information for
- * \param[in] node_namespace the namespace of the node to get information for
- * \param[in] no_demangle if true, list all topics without any demangling
- * \param[out] topic_names_and_types list of topic names and their types the node_name is publishing
+ * This function returns an array of topic names and types for which a given remote
+ * node has created publishers, as discovered so far by the given local node.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined, check the implementation documentation
+ *
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
+ *
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, when querying published topic names and types:
+ * - Access to the array of names and types is not synchronized.
+ * It is not safe to read or write `topic_names_and_types`
+ * while rmw_get_publisher_names_and_types_by_node() uses it.
+ * - Access to node name and namespace is read-only but it is not synchronized.
+ * Concurrent `node_name` and `node_namespace` reads are safe, but concurrent reads and
+ * writes are not.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
+ *
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ * \pre Given `topic_names_and_types` must be a zero-initialized array of names and types,
+ * as returned by rmw_get_zero_initialized_names_and_types().
+ *
+ * \param[in] Local node to query the ROS graph.
+ * \param[in] allocator Allocator to be used when populating the `topic_names_and_types` array.
+ * \param[in] node_name Name of the remote node to get information for.
+ * \param[in] node_namespace Namespace of the remote node to get information for.
+ * \param[in] no_demangle Whether to demangle all topic names following ROS conventions or not.
+ * \param[out] topic_names_and_types Array of topic names and types the remote node has created
+ * a publisher for, populated on success but left unchanged on failure.
+ * If populated, it is up to the caller to finalize this array later on
+ * using rmw_names_and_types_fini().
* \return `RMW_RET_OK` if the query was successful, or
- * \return `RMW_RET_INVALID_ARGUMENT` if the node is invalid, or
- * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `allocator` is not valid,
+ * by rcutils_allocator_is_valid() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_name` is not valid,
+ * by rmw_validate_node_name() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_namespace` is not valid,
+ * by rmw_validate_namespace() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_names_and_types` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_names_and_types` is not a
+ * zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
* \return `RMW_RET_NODE_NAME_NON_EXISTENT` if the node name wasn't found, or
* \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
@@ -99,27 +175,61 @@ rmw_get_publisher_names_and_types_by_node(
bool no_demangle,
rmw_names_and_types_t * topic_names_and_types);
-/// Return a list of service topic names and their types.
+/// Return all service names and types for which a given remote node has servers.
/**
- * This function returns a list of service topic names and their types.
- *
- * The node parameter must not be `NULL`, and must point to a valid node.
- *
- * The topic_names_and_types parameter must be allocated and zero initialized.
- * The topic_names_and_types is the output for this function, and contains
- * allocated memory.
- * Therefore, it should be passed to rmw_names_and_types_fini() when
- * it is no longer needed.
- * Failing to do so will result in leaked memory.
- *
- * \param[in] node the handle to the node being used to query the ROS graph
- * \param[in] allocator allocator to be used when allocating space for strings
- * \param[in] node_name the name of the node to get information for
- * \param[in] node_namespace the namespace of the node to get information for
- * \param[out] topic_names_and_types list of topic names and their types the node_name has created a service for
+ * This function returns an array of service names and types for which a given remote
+ * node has servers, as discovered so far by the given local node.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined, check the implementation documentation
+ *
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
+ *
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, when querying served service names and types:
+ * - Access to the array of names and types is not synchronized.
+ * It is not safe to read or write `service_names_and_types`
+ * while rmw_get_service_names_and_types_by_node() uses it.
+ * - Access to node name and namespace is read-only but it is not synchronized.
+ * Concurrent `node_name` and `node_namespace` reads are safe, but concurrent reads and
+ * writes are not.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
+ *
+ * \param[in] node Local node to query the ROS graph.
+ * \param[in] node_name Name of the remote node to get information for.
+ * \param[in] node_namespace Namespace of the remote node to get information for.
+ * \param[in] no_demangle Whether to demangle all topic names following ROS conventions or not.
+ * \param[out] service_names_and_types Array of service names and types the remote node has
+ * created a service server for, populated on success but left unchanged on failure.
+ * If populated, it is up to the caller to finalize this array later on
+ * using rmw_names_and_types_fini().
* \return `RMW_RET_OK` if the query was successful, or
- * \return `RMW_RET_INVALID_ARGUMENT` if the node is invalid, or
- * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `allocator` is not valid,
+ * by rcutils_allocator_is_valid() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_name` is not valid,
+ * by rmw_validate_node_name() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_namespace` is not valid,
+ * by rmw_validate_namespace() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `service_names_and_types` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `service_names_and_types` is not a
+ * zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
* \return `RMW_RET_NODE_NAME_NON_EXISTENT` if the node name wasn't found, or
* \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
@@ -134,28 +244,61 @@ rmw_get_service_names_and_types_by_node(
const char * node_namespace,
rmw_names_and_types_t * service_names_and_types);
-/// Return a list of service client topic names and their types.
+/// Return all service names and types for which a given remote node has clients.
/**
- * This function returns a list of service client topic names and their types.
- *
- * The node parameter must not be `NULL`, and must point to a valid node.
- *
- * The topic_names_and_types parameter must be allocated and zero initialized.
- * The topic_names_and_types is the output for this function, and contains
- * allocated memory.
- * Therefore, it should be passed to rmw_names_and_types_fini() when
- * it is no longer needed.
- * Failing to do so will result in leaked memory.
- *
- * \param[in] node the handle to the node being used to query the ROS graph
- * \param[in] allocator allocator to be used when allocating space for strings
- * \param[in] node_name the name of the node to get information for
- * \param[in] node_namespace the namespace of the node to get information for
- * \param[out] topic_names_and_types list of topic names and their types the
- * node_name has created a service client for
+ * This function returns an array of service names and types for which a given remote
+ * node has clients, as discovered so far by the given local node.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined, check the implementation documentation
+ *
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
+ *
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, when querying served service names and types:
+ * - Access to the array of names and types is not synchronized.
+ * It is not safe to read or write `service_names_and_types`
+ * while rmw_get_client_names_and_types_by_node() uses it.
+ * - Access to C-style string arguments is read-only but it is not synchronized.
+ * Concurrent `node_name` and `node_namespace` reads are safe, but concurrent reads and
+ * writes are not.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
+ *
+ * \param[in] node Local node to query the ROS graph.
+ * \param[in] node_name Name of the remote node to get information for.
+ * \param[in] node_namespace Namespace of the remote node to get information for.
+ * \param[in] no_demangle Whether to demangle all topic names following ROS conventions or not.
+ * \param[out] service_names_and_types Array of service names and types the remote node has
+ * created a service client for, populated on success but left unchanged on failure.
+ * If populated, it is up to the caller to finalize this array later on
+ * using rmw_names_and_types_fini().
* \return `RMW_RET_OK` if the query was successful, or
- * \return `RMW_RET_INVALID_ARGUMENT` if the node is invalid, or
- * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `allocator` is not valid,
+ * by rcutils_allocator_is_valid() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_name` is not valid,
+ * by rmw_validate_node_name() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_namespace` is not valid,
+ * by rmw_validate_namespace() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `service_names_and_types` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `service_names_and_types` is not a
+ * zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
* \return `RMW_RET_NODE_NAME_NON_EXISTENT` if the node name wasn't found, or
* \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
diff --git a/rmw/include/rmw/get_service_names_and_types.h b/rmw/include/rmw/get_service_names_and_types.h
index 21a85681..5bf72491 100644
--- a/rmw/include/rmw/get_service_names_and_types.h
+++ b/rmw/include/rmw/get_service_names_and_types.h
@@ -25,25 +25,57 @@ extern "C"
#include "rmw/types.h"
#include "rmw/visibility_control.h"
-/// Return a list of service names and their types.
+/// Return all service names and types in the ROS graph.
/**
- * This function returns a list of service names in the ROS graph and their types.
+ * This function returns an array of all service names and types in the ROS graph
+ * i.e. for which a server and/or client exists, as discovered so far by the given
+ * local node.
*
- * The node parameter must not be `NULL`, and must point to a valid node.
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined, check the implementation documentation
*
- * The service_names_and_types parameter must be allocated and zero initialized.
- * The service_names_and_types is the output for this function, and contains
- * allocated memory.
- * Therefore, it should be passed to rmw_names_and_types_fini() when
- * it is no longer needed.
- * Failing to do so will result in leaked memory.
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
*
- * \param[in] node the handle to the node being used to query the ROS graph
- * \param[in] allocator allocator to be used when allocating space for strings
- * \param[out] service_names_and_types list of service names and their types
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, when querying services names and types:
+ * - Access to the array of names and types is not synchronized.
+ * It is not safe to read or write `service_names_and_types`
+ * while rmw_get_service_names_and_types() uses it.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
+ *
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ * \pre Given `services_names_and_types` must be a zero-initialized array of names and types,
+ * as returned by rmw_get_zero_initialized_names_and_types().
+ *
+ * \param[in] node Node to query the ROS graph.
+ * \param[in] allocator Allocator to be used when populating the `service_names_and_types` array.
+ * \param[out] service_names_and_types Array of service names and their types,
+ * populated on success but left unchanged on failure.
+ * If populated, it is up to the caller to finalize this array later
+ * on using rmw_names_and_types_fini().
* \return `RMW_RET_OK` if the query was successful, or
- * \return `RMW_RET_INVALID_ARGUMENT` if the node is invalid, or
- * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `allocator` is not valid,
+ * by rcutils_allocator_is_valid() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `service_names_and_types` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `service_names_and_types` is not a
+ * zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
* \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
*/
diff --git a/rmw/include/rmw/get_topic_endpoint_info.h b/rmw/include/rmw/get_topic_endpoint_info.h
index efb5b42f..b9f6ae67 100644
--- a/rmw/include/rmw/get_topic_endpoint_info.h
+++ b/rmw/include/rmw/get_topic_endpoint_info.h
@@ -23,42 +23,65 @@ extern "C"
#include "rmw/topic_endpoint_info_array.h"
#include "rmw/visibility_control.h"
-/// Retrieve the information for all publishers to a given topic.
+/// Retrieve endpoint information for each known publisher of a given topic.
/**
- * The retrieved information will contain the publisher's node name, node namespace,
- * associated topic type, publisher gid and qos profile.
+ * This function returns an array of endpoint information for each publisher
+ * of a given topic, as discovered so far by the given node.
+ * Endpoint information includes the publisher's node name and namespace,
+ * the associated topic type, the publisher's gid, and the publisher QoS profile.
+ * Names of non-existent topics are allowed, in which case an empty array will be returned.
*
- * The node parameter must not be `NULL` and must point to a valid node.
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined, check the implementation documentation
*
- * The topic_name parameter must not be `NULL` and must follow the topic naming rules
- * mentioned at http://design.ros2.org/articles/topic_and_service_names.html
- * Names of non-existent topics are allowed.
- * In that case, this function will return an empty array.
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
*
- * It is the responsibility of the caller to ensure that `publishers_info` parameter points
- * to a valid struct of type rmw_topic_endpoint_info_array_t.
- * The rmw_topic_endpoint_info_array_t struct must be zero initialized.
- * \see rmw_get_zero_initialized_topic_endpoint_info_array
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, when querying topic names and types:
+ * - Access to the array of topic endpoint information is not synchronized.
+ * It is not safe to read or write `publishers_info`
+ * while rmw_get_publishers_info_by_topic() uses it.
+ * - Access to C-style string arguments is read-only but it is not synchronized.
+ * Concurrent `topic_name` reads are safe, but concurrent reads and writes are not.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
*
- * The `allocator` will be used to allocate memory to the `info_array` member
- * inside of `publishers_info`.
- * Moreover, every `const char *` member inside of
- * rmw_topic_endpoint_info_t will be assigned a copied value on allocated memory.
- * \see rmw_topic_endpoint_info_set_topic_type
- * \see rmw_topic_endpoint_info_set_node_name
- * \see rmw_topic_endpoint_info_set_node_namespace
- * However, it is the responsibility of the caller to
- * reclaim any allocated resources to `publishers_info` to avoid leaking memory.
- * \see rmw_topic_endpoint_info_array_fini
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ * \pre Given `publishers_info` must be a zero-initialized array of endpoints' information,
+ * as returned by rmw_get_zero_initialized_topic_endpoint_info_array().
*
- * \param[in] node the handle to the node being used to query the ROS graph.
- * \param[in] allocator the allocator to be used when allocating space for the array.
- * \param[in] topic_name the name of the topic for which the list of publishers will be retrieved.
- * \param[in] no_mangle if true, the topic name will not be mangled.
- * \param[out] publishers_info an array of rmw_topic_endpoint_info_t.
+ * \param[in] node Node to query the ROS graph.
+ * \param[in] allocator Allocator to be used when populating the `publishers_info` array.
+ * \param[in] topic_name Name of the topic for publisher lookup, often a fully qualified
+ * topic name but not necessarily (see rmw_create_publisher()).
+ * \param[in] no_mangle Whether to mangle the topic name before publisher lookup or not.
+ * \param[out] publishers_info Array of publisher information, populated on success,
+ * left unchanged on failure.
+ * If populated, it is up to the caller to finalize this array later on,
+ * using rmw_topic_endpoint_info_array_fini().
* \return `RMW_RET_OK` if the query was successful, or
- * \return `RMW_RET_INVALID_ARGUMENT` if the node is invalid, or
- * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `allocator` is not valid,
+ * by rcutils_allocator_is_valid() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_name` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `publishers_info` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `publishers_info` is not a
+ * zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
* \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
*/
@@ -72,42 +95,63 @@ rmw_get_publishers_info_by_topic(
bool no_mangle,
rmw_topic_endpoint_info_array_t * publishers_info);
-/// Retrieve the information for all subscriptions to a given topic.
+/// Retrieve endpoint information for each known subscription of a given topic.
/**
- * The retrieved information will contain the subscriptions's node name, node namespace,
- * associated topic type, subscription gid and qos profile.
+ * This function returns an array of endpoint information for each subscription
+ * of a given topic, as discovered so far by the given node.
+ * Endpoint information includes the subscription's node name and namespace,
+ * the associated topic type, the subscription's gid, and the subscription QoS profile.
+ * Names of non-existent topics are allowed, in which case an empty array will be returned.
*
- * The node parameter must not be `NULL` and must point to a valid node.
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined, check the implementation documentation
*
- * The topic_name parameter must not be `NULL` and must follow the topic naming rules
- * mentioned at http://design.ros2.org/articles/topic_and_service_names.html
- * Names of non-existent topics are allowed.
- * They will return an empty array.
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
*
- * It is the responsibility of the caller to ensure that `subscriptions_info` parameter points
- * to a valid struct of type rmw_topic_endpoint_info_array_t.
- * The rmw_topic_endpoint_info_array_t struct must be zero initialized.
- * \see rmw_get_zero_initialized_topic_endpoint_info_array
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, when querying subscriptions' information:
+ * - Access to the array of topic endpoint information is not synchronized.
+ * It is not safe to read or write `subscriptions_info`
+ * while rmw_get_subscriptions_info_by_topic() uses it.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
*
- * The `allocator` will be used to allocate memory to the `info_array` member
- * inside of `publishers_info`.
- * Moreover, every `const char *` member inside of
- * rmw_topic_endpoint_info_t will be assigned a copied value on allocated memory.
- * \see rmw_topic_endpoint_info_set_topic_type
- * \see rmw_topic_endpoint_info_set_node_name
- * \see rmw_topic_endpoint_info_set_node_namespace
- * However, it is the responsibility of the caller to
- * reclaim any allocated resources to `publishers_info` to avoid leaking memory.
- * \see rmw_topic_endpoint_info_array_fini
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ * \pre Given `subscriptions_info` must be a zero-initialized array of endpoints' information,
+ * as returned by rmw_get_zero_initialized_topic_endpoint_info_array().
*
- * \param[in] node the handle to the node being used to query the ROS graph.
- * \param[in] allocator the allocator to be used when allocating space for the array.
- * \param[in] topic_name the name of the topic for which the list of subscriptions will be retrieved.
- * \param[in] no_mangle if true, the topic name will not be mangled.
- * \param[out] subscriptions_info an array of rmw_topic_endpoint_info_t..
+ * \param[in] node Node to query the ROS graph.
+ * \param[in] allocator Allocator to be used when populating the `subscriptions_info` array.
+ * \param[in] topic_name Name of the topic for subscription lookup, often a fully qualified
+ * topic name but not necessarily (see rmw_create_subscription()).
+ * \param[in] no_mangle Whether to mangle the topic name before subscription lookup or not.
+ * \param[out] publishers_info Array of subscription information, populated on success,
+ * left unchanged on failure.
+ * If populated, it is up to the caller to finalize this array later on,
+ * using rmw_topic_endpoint_info_array_fini().
* \return `RMW_RET_OK` if the query was successful, or
- * \return `RMW_RET_INVALID_ARGUMENT` if the node is invalid, or
- * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `allocator` is not valid,
+ * by rcutils_allocator_is_valid() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_name` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `subscriptions_info` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `subscriptions_info` is not a
+ * zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
* \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
*/
diff --git a/rmw/include/rmw/get_topic_names_and_types.h b/rmw/include/rmw/get_topic_names_and_types.h
index b4fbe46b..d070a351 100644
--- a/rmw/include/rmw/get_topic_names_and_types.h
+++ b/rmw/include/rmw/get_topic_names_and_types.h
@@ -25,49 +25,65 @@ extern "C"
#include "rmw/types.h"
#include "rmw/visibility_control.h"
-/// Return a list of topic names and their types.
+/// Return all topic names and types in the ROS graph.
/**
- * This function returns a list of topic names in the ROS graph and their types.
+ * This function returns an array of all topic names and types in the ROS graph
+ * i.e. for which a publisher and/or a subscription exists, as discovered so far
+ * by the given local node.
*
- * The node parameter must not be `NULL`, and must point to a valid node.
+ * Unless `no_demangle` is true, some demangling and filtering may take place when
+ * listing topics as implemented by the middleware.
+ * Whether demangling applies or not, and how it applies, depends on the underlying
+ * implementation.
+ * See http://design.ros2.org/articles/topic_and_service_names.html for an example
+ * on how it is used in DDS and RTPS based implementations.
*
- * The topic_names_and_types parameter must be allocated and zero initialized.
- * The topic_names_and_types is the output for this function, and contains
- * allocated memory.
- * Therefore, it should be passed to rmw_names_and_types_fini() when
- * it is no longer needed.
- * Failing to do so will result in leaked memory.
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined, check the implementation documentation
*
- * There may be some demangling that occurs when listing the topics from the
- * middleware implementation.
- * This is the mechanism by which this function can discriminate between ROS
- * topics, non-ROS topics, and topics which may be used to implement other
- * concepts like ROS Services.
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
*
- * For example, if the underlying implementation is DDS or RTPS, ROS specific
- * prefixes may be prepended to the user namespace, and the namespace may be
- * stripped of leading and trailing slashes, see:
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, when querying topic names and types:
+ * - Access to the array of names and types is not synchronized.
+ * It is not safe to read or write `topic_names_and_types`
+ * while rmw_get_topic_names_and_types() uses it.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
*
- * http://design.ros2.org/articles/topic_and_service_names.html#ros-namespaces-with-dds-partitions
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ * \pre Given `topic_names_and_types` must be a zero-initialized array of names and types,
+ * as returned by rmw_get_zero_initialized_names_and_types().
*
- * As well as:
- *
- * http://design.ros2.org/articles/topic_and_service_names.html#communicating-with-non-ros-topics
- *
- * If the no_demangle argument is true, then the topic names given by the
- * middleware will be returned without any demangling or filtering.
- * For example, the ROS topic `/foo` may be returned as `rt/foo` or the DDS
- * topic (non-ROS topic) with a partition list `['foo', 'bar']` and topic `baz`
- * may be returned as `foo/baz` (note that only the first partition is used but
- * it is still concatenated to the topic).
- *
- * \param[in] node the handle to the node being used to query the ROS graph
- * \param[in] allocator allocator to be used when allocating space for strings
- * \param[in] no_demangle if true, list all topics without any demangling
- * \param[out] topic_names_and_types list of topic names and their types
+ * \param[in] node Node to query the ROS graph.
+ * \param[in] allocator Allocator to be used when populating the `topic_names_and_types` array.
+ * \param[in] no_demangle Whether to demangle all topic names following ROS conventions or not.
+ * \param[out] topic_names_and_types Array of topic names and their types,
+ * populated on success but left unchanged on failure.
+ * If populated, it is up to the caller to finalize this array later on
+ * using rmw_names_and_types_fini().
* \return `RMW_RET_OK` if the query was successful, or
- * \return `RMW_RET_INVALID_ARGUMENT` if the node is invalid, or
- * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `allocator` is not valid, by rcutils_allocator_is_valid()
+ * definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_names_and_types` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_names_and_types` is not a
+ * zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
* \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
*/
diff --git a/rmw/include/rmw/names_and_types.h b/rmw/include/rmw/names_and_types.h
index 050eceb1..a8318660 100644
--- a/rmw/include/rmw/names_and_types.h
+++ b/rmw/include/rmw/names_and_types.h
@@ -31,45 +31,77 @@ extern "C"
/// Associative array of topic or service names and types.
typedef struct RMW_PUBLIC_TYPE rmw_names_and_types_t
{
+ /// Array of names
rcutils_string_array_t names;
- // The length of this array is the same as names.size
+
+ /// Dynamic array of arrays of type names, with the same length as `names`
rcutils_string_array_t * types;
} rmw_names_and_types_t;
-/// Return a rmw_names_and_types_t struct with members initialized to `NULL`.
+/// Return a zero initialized array of names and types.
RMW_PUBLIC
RMW_WARN_UNUSED
rmw_names_and_types_t
rmw_get_zero_initialized_names_and_types(void);
-/// Check that a rmw_topic_names_and_types_t struct is zero initialized.
+/// Check that the given `names_and_types` array is zero initialized.
/**
- * Sets error message if names_and_types is not zero initialized
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | Yes
+ * Uses Atomics | No
+ * Lock-Free | Yes
+ *
+ * \par Thread-safety
+ * Access to the array of names and types is read-only, but it is not synchronized.
+ * Concurrent `names_and_types` reads are safe, but concurrent reads and writes are not.
*
- * \param[in] names_and_types Object to check
- * \return RMW_RET_OK if zero initialized, RMW_RET_INVALID_ARGUMENT otherwise
+ * \param[in] names_and_types Array to be checked.
+ * \return RMW_RET_OK if array is zero initialized, RMW_RET_INVALID_ARGUMENT otherwise.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
rmw_ret_t
rmw_names_and_types_check_zero(rmw_names_and_types_t * names_and_types);
-/// Initialize a rmw_names_and_types_t object.
+/// Initialize an array of names and types.
/**
* This function initializes the string array for the names and allocates space
* for all the string arrays for the types according to the given size, but
* it does not initialize the string array for each setup of types.
* However, the string arrays for each set of types is zero initialized.
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
+ *
+ * \par Thread-safety
+ * Initialization is a reentrant procedure, but:
+ * - Access to arrays of names and types is not synchronized.
+ * It is not safe to read or write `names_and_types` during initialization.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
*
- * \param[inout] names_and_types object to be initialized
- * \param[in] size the number of names and sets of types to be stored
- * \param[in] allocator to be used to allocate and deallocate memory
- * \returns `RMW_RET_OK` on successfully running the check, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if names_and_types is NULL, or
+ * \param[inout] names_and_types Array to be initialized on success,
+ * but left unchanged on failure.
+ * \param[in] size Size of the array.
+ * \param[in] allocator Allocator to be used to populate `names_and_types`.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `names_and_types` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `names_and_types` is not
+ * a zero initialized array, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `allocator` is invalid,
+ * by rcutils_allocator_is_valid() definition, or
* \returns `RMW_BAD_ALLOC` if memory allocation fails, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -79,23 +111,32 @@ rmw_names_and_types_init(
size_t size,
rcutils_allocator_t * allocator);
-/// Finalize a rmw_names_and_types_t object.
+/// Finalize an array of names and types.
/**
- * The names_and_types_t objects are populated by one of the
- * rmw_get_*_names_and_types() functions.
- * During which memory is allocated to store the names and types.
- * This function will reclaim any resources within the object so it is safe
- * to destroy without leaking memory.
+ * This function deallocates the string array of names and the array of string arrays of types,
+ * and zero initializes the given array.
+ * If a logical error, such as `RMW_RET_INVALID_ARGUMENT`, ensues, this function will return
+ * early, leaving the given array unchanged.
+ * Otherwise, it will proceed despite errors.
*
- * The allocator within the rmw_names_and_types_t object is used to deallocate
- * memory.
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ * \par Thread-safety
+ * Finalization is a reentrant procedure, but access to arrays of names and types
+ * is not synchronized.
+ * It is not safe to read or write `names_and_types` during initialization.
*
- * \param[inout] names_and_types object to be finalized
- * \returns `RMW_RET_OK` on successfully running the check, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if names_and_types is NULL, or
+ * \param[inout] names_and_types Array to be finalized.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `names_and_types` is NULL, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
diff --git a/rmw/include/rmw/rmw.h b/rmw/include/rmw/rmw.h
index 36871f0f..ab5c01a2 100644
--- a/rmw/include/rmw/rmw.h
+++ b/rmw/include/rmw/rmw.h
@@ -200,19 +200,38 @@ rmw_node_assert_liveliness(const rmw_node_t * node);
/// Return a guard condition which is triggered when the ROS graph changes.
/**
- * The handle returned is a pointer to an internally held rmw guard condition.
- * This function can fail, and therefore return `NULL`, if:
- * - node is `NULL`
- * - node is invalid
- *
- * The returned handle is made invalid if the node is destroyed or if
- * rmw_shutdown() is called.
- *
- * The guard condition will be triggered anytime a change to the ROS graph
- * occurs.
- * A ROS graph change includes things like (but not limited to) a new publisher
- * advertises, a new subscription is created, a new service becomes available,
- * a subscription is canceled, etc.
+ * The guard condition will be triggered anytime a change to the ROS graph occurs.
+ * A ROS graph change occurs whenever:
+ * - A node joins or leaves the ROS graph.
+ * This change will be reflected in rmw_get_node_names() and
+ * rmw_get_node_names_with_enclaves() outcome.
+ * - A topic subscription joins or leaves the ROS graph.
+ * This change will be reflected in rmw_get_topic_names_and_types(),
+ * rmw_get_subscriber_names_and_types_by_node(), and
+ * rmw_get_subscriptions_info_by_topic() outcome.
+ * - A topic publisher joins or leaves the ROS graph.
+ * This change will be reflected in rmw_get_topic_names_and_types(),
+ * rmw_get_publisher_names_and_types_by_node(), and
+ * rmw_get_publishers_info_by_topic() outcome.
+ * - A topic subscription matches a topic publisher with compatible QoS policies.
+ * This change will be reflected in rmw_subscription_count_matched_publishers() outcome.
+ * - A topic publisher matches a topic subscription with compatible QoS policies.
+ * This change will be reflected in rmw_publisher_count_matched_subscriptions() outcome.
+ * - A service server joins or leaves the ROS graph.
+ * This change will be reflected in rmw_get_service_names_and_types() and
+ * rmw_get_service_names_and_types_by_node() outcome.
+ * - A service client joins or leaves the ROS graph.
+ * This change will be reflected in rmw_get_service_names_and_types() and
+ * rmw_get_client_names_and_types_by_node() outcome.
+ * - A service client matches a service server with compatible QoS policies.
+ * This change will be reflected in rmw_service_server_is_available() outcome.
+ *
+ * \note The state of the ROS graph, and any changes that may take place,
+ * are reported as seen by the associated `node`.
+ *
+ * The guard condition is owned and internally held by the `node`.
+ * It will be invalidated if `node` is finalized using rmw_destroy_node().
+ * It is undefined behavior to use an invalidated guard condition.
*
*
* Attribute | Adherence
@@ -222,8 +241,11 @@ rmw_node_assert_liveliness(const rmw_node_t * node);
* Uses Atomics | No
* Lock-Free | Yes
*
- * \param[in] node pointer to the rmw node
- * \return rmw guard condition handle if successful, otherwise `NULL`
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ *
+ * \param[in] node Node to retrieve the guard condition from.
+ * \return Guard condition if successful, or `NULL` if
+ * `node` is `NULL`, or an unspecified error occurs.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -1996,31 +2018,60 @@ rmw_wait(
rmw_wait_set_t * wait_set,
const rmw_time_t * wait_timeout);
-/// Return a list of node name and namespaces discovered via a node.
+/// Return the name and namespace of all nodes in the ROS graph.
/**
- * This function will return a list of node names and a list of node namespaces
- * that are discovered via the middleware.
- * The two lists represent pairs of namespace and name for each discovered
- * node.
- * The lists will be the same length and the same position will refer to the
- * same node across lists.
- *
- * The node parameter must not be `NULL`, and must point to a valid node.
+ * This function will return an array of node names and an array of node namespaces,
+ * as discovered so far by the given node.
+ * The two arrays represent name and namespace pairs for each discovered node.
+ * Both arrays will be the same length and the same index will refer to the same node.
*
- * The node_names parameter must not be `NULL`, and must point to a valid
- * string array.
- *
- * The node_namespaces parameter must not be `NULL`, and must point to a
- * valid string array.
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | No
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] implementation defined, check the implementation documentation
*
- * This function does manipulate heap memory.
- * This function is not thread-safe.
- * This function is lock-free.
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
*
- * \param[in] node the handle to the node being used to query the ROS graph
- * \param[out] node_names a list of discovered node names
- * \param[out] node_namespaces a list of discovered node namespaces
- * \return `RMW_RET_OK` if node the query was made successfully, or
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, access to string arrays is not synchronized.
+ * It is not safe to read or write `node_names` nor `node_namespaces`
+ * while rmw_get_node_names() uses them.
+ *
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ * \pre Given `node_names` must be a valid string array, zero-initialized
+ * as returned by rcutils_get_zero_initialized_string_array().
+ * \pre Given `node_namespaces` must be a valid string array, zero-initialized
+ * as returned by rcutils_get_zero_initialized_string_array().
+ * \post Given `node_names` and `node_namespaces` will remain valid arrays.
+ * These will be left unchanged if this function fails early due to a logical error,
+ * such as an invalid argument, or in an unknown yet valid state if it fails due to
+ * a runtime error.
+ *
+ * \param[in] node Node to query the ROS graph.
+ * \param[out] node_names Array of discovered node names, populated on success.
+ * It is up to the caller to finalize this array later on, using rcutils_string_array_fini().
+ * \param[out] node_namespaces Array of discovered node namespaces, populated on success.
+ * It is up to the caller to finalize this array later on, using rcutils_string_array_fini().
+ * \return `RMW_RET_OK` if the query was successful, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_names` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_names` is not a zero-initialized array, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_namespaces` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_namespaces` is not a zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
+ * \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
*/
RMW_PUBLIC
@@ -2031,15 +2082,63 @@ rmw_get_node_names(
rcutils_string_array_t * node_names,
rcutils_string_array_t * node_namespaces);
-/// Return a list of node name and namespaces discovered via a node with its enclave.
+/// Return the name, namespae, and enclave name of all nodes in the ROS graph.
/**
- * Similar to \ref rmw_get_node_names, but it also provides the enclave name.
+ * This is similar to rmw_get_node_names(), but it also provides enclave names.
*
- * \param[in] node the handle to the node being used to query the ROS graph
- * \param[out] node_names a list of discovered node names
- * \param[out] node_namespaces a list of discovered node namespaces
- * \param[out] enclaves list of discovered nodes' enclave names
- * \return `RMW_RET_OK` if node the query was made successfully, or
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] implementation defined, check the implementation documentation
+ *
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
+ *
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is safe to query the ROS graph using the same node concurrently.
+ * However, access to string arrays is not synchronized.
+ * It is not safe to read or write `node_names`, `node_namespaces`, nor `enclaves`
+ * while rmw_get_node_names_with_enclaves() uses them.
+ *
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ * \pre Given `node_names` must be a valid string array, zero-initialized
+ * as returned by rcutils_get_zero_initialized_string_array().
+ * \pre Given `node_namespaces` must be a valid string array, zero-initialized
+ * as returned by rcutils_get_zero_initialized_string_array().
+ * \pre Given `enclaves` must be a zero-initialized string array,
+ * as returned by rcutils_get_zero_initialized_string_array().
+ * \post Given `node_names`, `node_namespaces`, and `enclaves` will remain valid arrays.
+ * These will be left unchanged if this function fails early due to a logical error,
+ * such as an invalid argument, or in an unknown yet valid state if it fails due to
+ * a runtime error.
+ *
+ * \param[in] node Node to query the ROS graph.
+ * \param[out] node_names Array of discovered node names, populated on success.
+ * It is up to the caller to finalize this array later on, using rcutils_string_array_fini().
+ * \param[out] node_namespaces Array of discovered node namespaces, populated on success.
+ * It is up to the caller to finalize this array later on, using rcutils_string_array_fini().
+ * \param[out] enclaves Array of discovered node enclave names, populated on success.
+ * It is up to the caller to finalize this array later on, using rcutils_string_array_fini().
+ * \return `RMW_RET_OK` if the query was successful, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_names` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_names` is not a zero-initialized array, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_namespaces` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node_namespaces` is not a zero-initialized array, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `enclaves` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `enclaves` is not a zero-initialized array, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
+ * \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RMW_RET_ERROR` if an unspecified error occurs.
*/
RMW_PUBLIC
@@ -2051,13 +2150,49 @@ rmw_get_node_names_with_enclaves(
rcutils_string_array_t * node_namespaces,
rcutils_string_array_t * enclaves);
-/// Count the number of publishers matching a topic name
+/// Count the number of known publishers matching a topic name.
/**
-* \param[in] node rmw node connected to the ROS graph
-* \param[in] topic_name The name of the topic to match under possible prefixes
-* \param[out] count The number of publishers matching the topic name
-* \return RMW_RET_OK if successful, otherwise an appropriate error code
-*/
+ * This function returns the numbers of publishers of a given topic in the ROS graph,
+ * as discovered so far by the given node.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] implementation defined, check the implementation documentation
+ *
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
+ *
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is to query the ROS graph using the same node concurrently.
+ * However, access to primitive data-type arguments is not synchronized.
+ * It is not safe to read or write `topic_name` or `count` while rmw_count_publishers()
+ * uses them.
+ *
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ *
+ * \param[in] node Handle to node to use to query the ROS graph.
+ * \param[in] topic_name Fully qualified ROS topic name.
+ * \param[out] count Number of publishers matching the given topic name.
+ * \return `RMW_RET_OK` if the query was successful, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_name` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_name` is not a fully qualified topic name,
+ * by rmw_validate_full_topic_name() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `count` is NULL, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
+ * \return `RMW_RET_ERROR` if an unspecified error occurs.
+ */
RMW_PUBLIC
RMW_WARN_UNUSED
rmw_ret_t
@@ -2066,12 +2201,48 @@ rmw_count_publishers(
const char * topic_name,
size_t * count);
-/// Count the number of subscribers matching a topic name
+/// Count the number of known subscribers matching a topic name.
/**
- * \param[in] node rmw node connected to the ROS graph
- * \param[in] topic_name The name of the topic to match under possible prefixes
- * \param[out] count The number of subscribers matching the topic name
- * \return RMW_RET_OK if successful, otherwise an appropriate error code
+ * This function returns the numbers of subscribers of a given topic in the ROS graph,
+ * as discovered so far by the given node.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] implementation defined, check the implementation documentation
+ *
+ * \par Runtime behavior
+ * To query the ROS graph is a synchronous operation.
+ * It is also non-blocking, but it is not guaranteed to be lock-free.
+ * Generally speaking, implementations may synchronize access to internal resources using
+ * locks but are not allowed to wait for events with no guaranteed time bound (barring
+ * the effects of starvation due to OS scheduling).
+ *
+ * \par Thread-safety
+ * Nodes are thread-safe objects, and so are all operations on them except for finalization.
+ * Therefore, it is to query the ROS graph using the same node concurrently.
+ * However, access to primitive data-type arguments is not synchronized.
+ * It is not safe to read or write `topic_name` or `count` while rmw_count_subscribers()
+ * uses them.
+ *
+ * \pre Given `node` must be a valid node handle, as returned by rmw_create_node().
+ *
+ * \param[in] node Handle to node to use to query the ROS graph.
+ * \param[in] topic_name Fully qualified ROS topic name.
+ * \param[out] count Number of subscribers matching the given topic name.
+ * \return `RMW_RET_OK` if the query was successful, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `node` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_name` is NULL, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `topic_name` is not a fully qualified topic name,
+ * by rmw_validate_full_topic_name() definition, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if `count` is NULL, or
+ * \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if the `node` implementation
+ * identifier does not match this implementation, or
+ * \return `RMW_RET_ERROR` if an unspecified error occurs.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
diff --git a/rmw/include/rmw/topic_endpoint_info.h b/rmw/include/rmw/topic_endpoint_info.h
index 1e4ac690..dee89178 100644
--- a/rmw/include/rmw/topic_endpoint_info.h
+++ b/rmw/include/rmw/topic_endpoint_info.h
@@ -24,8 +24,9 @@ extern "C"
#include "rmw/types.h"
#include "rmw/visibility_control.h"
-/// A structure that encapsulates the name, namespace, topic_type, gid and qos_profile
-/// of publishers and subscriptions for a topic.
+/// A data structure that encapsulates the node name, node namespace,
+/// topic_type, gid, and qos_profile of publishers and subscriptions
+/// for a topic.
typedef struct RMW_PUBLIC_TYPE rmw_topic_endpoint_info_t
{
/// Name of the node
@@ -42,26 +43,47 @@ typedef struct RMW_PUBLIC_TYPE rmw_topic_endpoint_info_t
rmw_qos_profile_t qos_profile;
} rmw_topic_endpoint_info_t;
-/// Return a rmw_topic_endpoint_info_t struct with members initialized to `NULL`.
+/// Return zero initialized topic endpoint info data structure.
+/**
+ * Endpoint type will be invalid.
+ * Endpoint QoS profile will be the system default.
+ */
RMW_PUBLIC
RMW_WARN_UNUSED
rmw_topic_endpoint_info_t
rmw_get_zero_initialized_topic_endpoint_info(void);
-/// Finalize a rmw_topic_endpoint_info_t object.
+/// Finalize a topic endpoint info data structure.
/**
- * The rmw_topic_endpoint_info_t struct has members which require memory to be allocated to them before
- * setting values.
- * This function reclaims any allocated resources within the object and zeroes out all other
- * members.
+ * This function deallocates all allocated members of the given data structure,
+ * and then zero initializes it.
+ * If a logical error, such as `RMW_RET_INVALID_ARGUMENT`, ensues, this function
+ * will return early, leaving the given data structure unchanged.
+ * Otherwise, it will proceed despite errors.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ * \par Thread-safety
+ * Finalization is a reentrant procedure, but:
+ * - Access to the topic endpoint info data structure is not synchronized.
+ * It is not safe to read or write `topic_endpoint` during finalization.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
*
- * \param[inout] topic_endpoint_info object to be finalized
- * \param[in] allocator the allocator used to allocate memory to the object
- * \returns `RMW_RET_OK` on successfully reclaiming memory, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if any parameters are NULL, or
+ * \param[inout] topic_endpoint_info Data structure to be finalized.
+ * \param[in] allocator Allocator used to populate the given `topic_endpoint_info`.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `allocator` is invalid,
+ * by rcutils_allocator_is_valid() definition, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -70,20 +92,40 @@ rmw_topic_endpoint_info_fini(
rmw_topic_endpoint_info_t * topic_endpoint_info,
rcutils_allocator_t * allocator);
-/// Set the topic_type in rmw_topic_endpoint_info_t.
+/// Set the topic type in the given topic endpoint info data structure.
/**
- * rmw_topic_endpoint_info_t has a member topic_type of type const char *;
- * this function allocates memory and copies the value of param passed to it.
+ * This functions allocates memory and copies the value of the `topic_type`
+ * argument to set the data structure `topic_type` member.
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * \param[inout] topic_endpoint_info pointer to an initialized instance of rmw_topic_endpoint_info_t
- * \param[in] topic_type the topic_type value to set in rmw_topic_endpoint_info_t
- * \param[in] allocator the allocator that will be used to allocate memory
- * \returns `RMW_RET_OK` on successfully setting the topic_type, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if any parameters are NULL, or
- * \returns `RMW_RET_BAD_ALLOC` if allocation for string duplication fails, or
+ * \par Thread-safety
+ * Setting a member is a reentrant procedure, but:
+ * - Access to the topic endpoint info data structure is not synchronized.
+ * It is not safe to read or write the `topic_type` member of the given `topic_endpoint`
+ * while setting it.
+ * - Access to C-style string arguments is read-only but it is not synchronized.
+ * Concurrent `topic_type` reads are safe, but concurrent reads and writes are not.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
+ *
+ * \pre Given `topic_type` is a valid C-style string i.e. NULL terminated.
+ *
+ * \param[inout] topic_endpoint_info Data structure to be populated.
+ * \param[in] topic_type Type name to be set.
+ * \param[in] allocator Allocator to be used.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_type` is NULL, or
+ * \returns `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -93,20 +135,40 @@ rmw_topic_endpoint_info_set_topic_type(
const char * topic_type,
rcutils_allocator_t * allocator);
-/// Set the node_name in rmw_topic_endpoint_info_t.
+/// Set the node name in the given topic endpoint info data structure.
/**
- * rmw_topic_endpoint_info_t has a member node_name of type const char *;
- * this function allocates memory and copies the value of param passed to it.
+ * This functions allocates memory and copies the value of the `node_name`
+ * argument to set the data structure `node_name` member.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ * \par Thread-safety
+ * Setting a member is a reentrant procedure, but:
+ * - Access to the topic endpoint info data structure is not synchronized.
+ * It is not safe to read or write the `node_name` member of the given `topic_endpoint`
+ * while setting it.
+ * - Access to C-style string arguments is read-only but it is not synchronized.
+ * Concurrent `node_name` reads are safe, but concurrent reads and writes are not.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
*
- * \param[inout] topic_endpoint_info pointer to an initialized instance of rmw_topic_endpoint_info_t
- * \param[in] node_name the node_name value to set in rmw_topic_endpoint_info_t
- * \param[in] allocator the allocator that will be used to allocate memory
- * \returns `RMW_RET_OK` on successfully setting the node_name, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if any parameters are NULL, or
- * \returns `RMW_RET_BAD_ALLOC` if allocation for string duplication fails, or
+ * \pre Given `node_name` is a valid C-style string i.e. NULL terminated.
+ *
+ * \param[inout] topic_endpoint_info Data structure to be populated.
+ * \param[in] node_name Node name to be set.
+ * \param[in] allocator Allocator to be used.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `node_name` is NULL, or
+ * \returns `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -116,20 +178,40 @@ rmw_topic_endpoint_info_set_node_name(
const char * node_name,
rcutils_allocator_t * allocator);
-/// Set the node_namespace in rmw_topic_endpoint_info_t.
+/// Set the node namespace in the given topic endpoint info data structure.
/**
- * rmw_topic_endpoint_info_t has a member node_namespace of type const char *;
- * this function allocates memory and copies the value of param passed to it.
+ * This functions allocates memory and copies the value of the `node_namespace`
+ * argument to set the data structure `node_namespace` member.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
+ *
+ * \par Thread-safety
+ * Setting a member is a reentrant procedure, but:
+ * - Access to the topic endpoint info data structure is not synchronized.
+ * It is not safe to read or write the `node_namespace` member of the given `topic_endpoint`
+ * while setting it.
+ * - Access to C-style string arguments is read-only but it is not synchronized.
+ * Concurrent `node_namespace` reads are safe, but concurrent reads and writes are not.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ * \pre Given `node_namespace` is a valid C-style string i.e. NULL terminated.
*
- * \param[inout] topic_endpoint_info pointer to an initialized instance of rmw_topic_endpoint_info_t
- * \param[in] node_namespace the node_namespace value to set in rmw_topic_endpoint_info_t
- * \param[in] allocator the allocator that will be used to allocate memory
- * \returns `RMW_RET_OK` on successfully setting the node_namespace, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if any parameters are NULL, or
- * \returns `RMW_RET_BAD_ALLOC` if allocation for string duplication fails, or
+ * \param[inout] topic_endpoint_info Data structure to be populated.
+ * \param[in] node_namespace Node namespace to be set.
+ * \param[in] allocator Allocator to be used.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `node_namespace` is NULL, or
+ * \returns `RMW_RET_BAD_ALLOC` if memory allocation fails, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -139,20 +221,31 @@ rmw_topic_endpoint_info_set_node_namespace(
const char * node_namespace,
rcutils_allocator_t * allocator);
-/// Set the gid in rmw_topic_endpoint_info_t.
+/// Set the endpoint type in the given topic endpoint info data structure.
/**
- * Copies the values from gid into the gid member inside topic_endpoint_info.
+ * This functions assigns the value of the `type` argument to the data structure
+ * `endpoint_type` member.
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * \param[inout] topic_endpoint_info pointer to an initialized instance of rmw_topic_endpoint_info_t
- * \param[in] gid the gid value to set in rmw_topic_endpoint_info_t
- * \param[in] size the size of the gid param
- * \returns `RMW_RET_OK` on successfully setting the gid, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if any parameters are NULL, or
- * \returns `RMW_RET_INVALID_ARGUMENT` size is greater than RMW_GID_STORAGE_SIZE, or
- * \returns `RMW_RET_BAD_ALLOC` if allocation for string duplication fails, or
+ * \par Thread-safety
+ * Setting a member is a reentrant procedure, but access to the
+ * topic endpoint info data structure is not synchronized.
+ * It is not safe to read or write the `endpoint_type` member of the
+ * given `topic_endpoint` while setting it.
+ *
+ * \param[inout] topic_endpoint_info Data structure to be populated.
+ * \param[in] type Endpoint type to be set.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info` is NULL, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -161,19 +254,34 @@ rmw_topic_endpoint_info_set_endpoint_type(
rmw_topic_endpoint_info_t * topic_endpoint_info,
rmw_endpoint_type_t type);
-/// Set the gid in rmw_topic_endpoint_info_t.
+/// Set the endpoint gid in the given topic endpoint info data structure.
/**
- * Copies the values from gid into the gid member inside topic_endpoint_info.
+ * This functions copies the value of the `gid` argument to the data structure
+ * `endpoint_gid` member.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ * \par Thread-safety
+ * Setting a member is a reentrant procedure, but access to the
+ * topic endpoint info data structure is not synchronized.
+ * It is not safe to read or write the `gid` member of the
+ * given `topic_endpoint` while setting it.
*
- * \param[inout] topic_endpoint_info pointer to an initialized instance of rmw_topic_endpoint_info_t
- * \param[in] gid the gid value to set in rmw_topic_endpoint_info_t
- * \param[in] size the size of the gid param
- * \returns `RMW_RET_OK` on successfully setting the gid, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if any parameters are NULL, or
- * \returns `RMW_RET_INVALID_ARGUMENT` size is greater than RMW_GID_STORAGE_SIZE, or
+ * \param[inout] topic_endpoint_info Data structure to be populated.
+ * \param[in] gid Endpoint gid to be set.
+ * \param[in] size Size of the given `gid`.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `gid` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `size` is greater than RMW_GID_STORAGE_SIZE, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -183,18 +291,32 @@ rmw_topic_endpoint_info_set_gid(
const uint8_t gid[],
size_t size);
-/// Set the qos_profile in rmw_topic_endpoint_info_t.
+/// Set the endpoint QoS profile in the given topic endpoint info data structure.
/**
- * rmw_topic_endpoint_info_t has a member qos_profile of type const rmw_qos_profile_t *.
- * This function assigns the passed qos_profile pointer to the member.
+ * This functions assigns the value of the `qos_profile` argument to the data structure
+ * `qos_profile` member.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ * \par Thread-safety
+ * Setting a member is a reentrant procedure, but access to the
+ * topic endpoint info data structure is not synchronized.
+ * It is not safe to read or write the `qos_profile` member of the
+ * given `topic_endpoint` while setting it.
*
- * \param[inout] topic_endpoint_info pointer to an initialized instance of rmw_topic_endpoint_info_t
- * \param[in] qos_profile the qos_profile to set in rmw_topic_endpoint_info_t
- * \returns `RMW_RET_OK` on successfully setting the qos_profile, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if any parameters are NULL, or
+ * \param[inout] topic_endpoint_info Data structure to be populated.
+ * \param[in] qos_profile QoS profile to be set.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `qos_profile` is NULL, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
diff --git a/rmw/include/rmw/topic_endpoint_info_array.h b/rmw/include/rmw/topic_endpoint_info_array.h
index c85f2b00..a8cf0986 100644
--- a/rmw/include/rmw/topic_endpoint_info_array.h
+++ b/rmw/include/rmw/topic_endpoint_info_array.h
@@ -24,31 +24,41 @@ extern "C"
#include "rmw/topic_endpoint_info.h"
#include "rmw/visibility_control.h"
-/// Array of rmw_topic_endpoint_info_t
+/// Array of topic endpoint information
typedef struct RMW_PUBLIC_TYPE rmw_topic_endpoint_info_array_t
{
/// Size of the array.
size_t size;
- /// Pointer representing an array of rmw_topic_endpoint_info_t
+ /// Contiguous storage for topic endpoint information elements.
rmw_topic_endpoint_info_t * info_array;
} rmw_topic_endpoint_info_array_t;
-/// Return a rmw_topic_endpoint_info_array_t struct with members initialized to `NULL`.
+/// Return a zero initialized array of topic endpoint information.
RMW_PUBLIC
RMW_WARN_UNUSED
rmw_topic_endpoint_info_array_t
rmw_get_zero_initialized_topic_endpoint_info_array(void);
-/// Check that a rmw_topic_endpoint_info_array_t struct is zero initialized.
+/// Check that the given `topic_endpoint_info_array` is zero initialized.
/**
- * This function checks if the provided rmw_topic_endpoint_info_array_t is zero initialized or not.
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | Yes
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ * \par Thread-safety
+ * Access to the array of topic endpoint information is read-only, but it is not synchronized.
+ * Concurrent `topic_endpoint_info_array` reads are safe, but concurrent reads
+ * and writes are not.
*
- * \param[in] topic_endpoint_info_array the data structure to be checked
- * \returns `RMW_RET_OK` if topic_endpoint_info_array is zero initialized
- * \returns `RMW_RET_INVALID_ARGUMENT` if the parameter is NULL, or
- * \returns `RMW_RET_ERROR` if topic_endpoint_info_array is not zero initialized
+ * \param[in] topic_endpoint_info_array Array to be checked.
+ * \returns `RMW_RET_OK` if array is zero initialized, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info_array` is NULL, or
+ * \returns `RMW_RET_ERROR` if `topic_endpoint_info_array` is not zero initialized.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -56,26 +66,39 @@ rmw_ret_t
rmw_topic_endpoint_info_array_check_zero(
rmw_topic_endpoint_info_array_t * topic_endpoint_info_array);
-/// Initialize the info_array member inside rmw_topic_endpoint_info_array_t with the given size
+/// Initialize an array of topic endpoint information.
/**
- * The rmw_topic_endpoint_info_array_t has a member variable info_array which is an array of
- * type rmw_topic_endpoint_info_t.
- * This function allocates memory to this array to hold n elements,
- * where n is the value of the size param to this function.
- * The member `size` is updated accordingly.
+ * This function allocates space to hold `size` topic endpoint information elements.
+ * Both `info_array` and `size` members are updated accordingly.
*
- * topic_endpoint_info_array must be zero initialized before being passed into this function.
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ * \par Thread-safety
+ * Initialization is a reentrant procedure, but:
+ * - Access to the array of topic endpoint information is not synchronized.
+ * It is not safe to read or write `topic_endpoint_info_array` during initialization.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
*
- * \param[inout] topic_endpoint_info_array the data structure to initialise
- * \param[in] size the size of the array
- * \param[in] allocator the allocator to be used to allocate space
- * \returns `RMW_RET_OK` on successful init, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if any of the parameters are NULL, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if topic_endpoint_info_array is not zero initialized, or
+ * \param[inout] topic_endpoint_info_array Array to be initialized on success,
+ * but left unchanged on failure.
+ * \param[in] size Size of the array.
+ * \param[in] allocator Allocator to be used to populate `names_and_types`.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info_array` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info_array` is not
+ * a zero initialized array, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `allocator` is invalid,
+ * by rcutils_allocator_is_valid() definition, or
* \returns `RMW_BAD_ALLOC` if memory allocation fails, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
@@ -85,21 +108,38 @@ rmw_topic_endpoint_info_array_init_with_size(
size_t size,
rcutils_allocator_t * allocator);
-/// Finalize a rmw_topic_endpoint_info_array_t object.
+/// Finalize an array of topic endpoint information.
/**
- * The info_array member variable inside of rmw_topic_endpoint_info_array represents an array of
- * rmw_topic_endpoint_info_t.
- * When initializing this array, memory is allocated for it using the allocator.
- * This function reclaims any allocated resources within the object and also sets the value of size
- * to 0.
+ * This function deallocates the given array storage, and then zero initializes it.
+ * If a logical error, such as `RMW_RET_INVALID_ARGUMENT`, ensues, this function will
+ * return early, leaving the given array unchanged.
+ * Otherwise, it will proceed despite errors.
*
- * If a non RMW_RET_OK return value is returned, the RMW error message will be set
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
*
- * \param[inout] topic_endpoint_info_array object to be finalized
- * \param[in] allocator the allocator used to allocate memory to the object
- * \returns `RMW_RET_OK` on successfully reclaiming memory, or
- * \returns `RMW_RET_INVALID_ARGUMENT` if any parameters are NULL, or
+ * \par Thread-safety
+ * Finalization is a reentrant procedure, but:
+ * - Access to the array of topic endpoint information is not synchronized.
+ * It is not safe to read or write `topic_endpoint_info_array` during finalization.
+ * - The default allocators are thread-safe objects, but any custom `allocator` may not be.
+ * Check your allocator documentation for further reference.
+ *
+ * \pre Given `allocator` must be the same used to initialize the given `topic_endpoint_info_array`.
+ *
+ * \param[inout] topic_endpoint_info_array object to be finalized.
+ * \param[in] allocator Allocator used to populate the given `topic_endpoint_info_array`.
+ * \returns `RMW_RET_OK` if successful, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `topic_endpoint_info_array` is NULL, or
+ * \returns `RMW_RET_INVALID_ARGUMENT` if `allocator` is invalid,
+ * by rcutils_allocator_is_valid() definition, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
+ * \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED