diff --git a/rcl/include/rcl/client.h b/rcl/include/rcl/client.h
index ad8131b..d8bba97 100644
--- a/rcl/include/rcl/client.h
+++ b/rcl/include/rcl/client.h
@@ -370,6 +370,28 @@ RCL_WARN_UNUSED
rmw_client_t *
rcl_client_get_rmw_handle(const rcl_client_t * client);
+/// Check that the client is valid.
+/**
+ * The bool returned is `false` if client is invalid
+ * The bool returned is `true` otherwise.
+ * In the case where `false` is to be returned, an
+ * error message is set.
+ * This function cannot fail.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
+ *
+ * \param[in] client pointer to the rcl client
+ * \return `true` if `client` is valid, otherwise `false`
+ */
+bool
+rcl_client_is_valid(const rcl_client_t * client);
+
#if __cplusplus
}
#endif
diff --git a/rcl/include/rcl/publisher.h b/rcl/include/rcl/publisher.h
index aba70c8..315df65 100644
--- a/rcl/include/rcl/publisher.h
+++ b/rcl/include/rcl/publisher.h
@@ -336,6 +336,29 @@ RCL_WARN_UNUSED
rmw_publisher_t *
rcl_publisher_get_rmw_handle(const rcl_publisher_t * publisher);
+/// Check that the publisher is valid
+/**
+ * The bool returned is `false` if `publisher` is invalid.
+ * The bool returned is `true` otherwise.
+ * In the case where `false` is to be returned, an
+ * error message is set.
+ * This function cannot fail.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
+ *
+ * \param[in] publisher pointer to the rcl publisher
+ * \return `true` if the publisher is valid, otherwise `false`
+ */
+
+bool
+rcl_publisher_is_valid(const rcl_publisher_t * publisher);
+
#if __cplusplus
}
#endif
diff --git a/rcl/include/rcl/service.h b/rcl/include/rcl/service.h
index d4a6ac6..44e6f7e 100644
--- a/rcl/include/rcl/service.h
+++ b/rcl/include/rcl/service.h
@@ -382,6 +382,28 @@ RCL_WARN_UNUSED
rmw_service_t *
rcl_service_get_rmw_handle(const rcl_service_t * service);
+/// Check that the service is valid.
+/**
+ * The bool returned is `false` if `service` is invalid.
+ * The bool returned is `true` otherwise.
+ * In the case where `false` is to be returned, an
+ * error message is set.
+ * This function cannot fail.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
+ *
+ * \param[in] service pointer to the rcl service
+ * \return `true` if `service` is valid, otherwise `false`
+ */
+bool
+rcl_service_is_valid(const rcl_service_t * service);
+
#if __cplusplus
}
#endif
diff --git a/rcl/include/rcl/subscription.h b/rcl/include/rcl/subscription.h
index dbcb175..e78c213 100644
--- a/rcl/include/rcl/subscription.h
+++ b/rcl/include/rcl/subscription.h
@@ -339,6 +339,28 @@ RCL_WARN_UNUSED
rmw_subscription_t *
rcl_subscription_get_rmw_handle(const rcl_subscription_t * subscription);
+/// Check that the subscription is valid.
+/**
+ * The bool returned is `false` if `subscription` is invalid.
+ * The bool returned is `true` otherwise.
+ * In the case where `false` is to be returned, an
+ * error message is set.
+ * This function cannot fail.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
+ *
+ * \param[in] subscription pointer to the rcl subscription
+ * \return `true` if `subscription` is valid, otherwise `false`
+ */
+bool
+rcl_subscription_is_valid(const rcl_subscription_t * subscription);
+
#if __cplusplus
}
#endif
diff --git a/rcl/src/rcl/client.c b/rcl/src/rcl/client.c
index a0c6e98..6777bbc 100644
--- a/rcl/src/rcl/client.c
+++ b/rcl/src/rcl/client.c
@@ -201,29 +201,29 @@ rcl_client_get_default_options()
const char *
rcl_client_get_service_name(const rcl_client_t * client)
{
- const rcl_client_options_t * options = rcl_client_get_options(client);
- if (!options) {
+ if (!rcl_client_is_valid(client)) {
return NULL; // error already set
}
- RCL_CHECK_FOR_NULL_WITH_MSG(
- client->impl->rmw_handle, "client is invalid", return NULL, options->allocator);
return client->impl->rmw_handle->service_name;
}
+/* *INDENT-OFF* */
+#define _client_get_options(client) &client->impl->options;
+/* *INDENT-ON* */
+
const rcl_client_options_t *
rcl_client_get_options(const rcl_client_t * client)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(client, NULL, rcl_get_default_allocator());
- RCL_CHECK_FOR_NULL_WITH_MSG(
- client->impl, "client is invalid", return NULL, rcl_get_default_allocator());
- return &client->impl->options;
+ if (!rcl_client_is_valid(client)) {
+ return NULL; // error already set
+ }
+ return _client_get_options(client);
}
rmw_client_t *
rcl_client_get_rmw_handle(const rcl_client_t * client)
{
- const rcl_client_options_t * options = rcl_client_get_options(client);
- if (!options) {
+ if (!rcl_client_is_valid(client)) {
return NULL; // error already set
}
return client->impl->rmw_handle;
@@ -234,12 +234,12 @@ RCL_WARN_UNUSED
rcl_ret_t
rcl_send_request(const rcl_client_t * client, const void * ros_request, int64_t * sequence_number)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
+ if (!rcl_client_is_valid(client)) {
+ return RCL_RET_CLIENT_INVALID;
+ }
RCL_CHECK_ARGUMENT_FOR_NULL(ros_request, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
RCL_CHECK_ARGUMENT_FOR_NULL(
sequence_number, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
- RCL_CHECK_FOR_NULL_WITH_MSG(
- client->impl, "client is invalid", return RCL_RET_CLIENT_INVALID, rcl_get_default_allocator());
*sequence_number = rcl_atomic_load_int64_t(&client->impl->sequence_number);
if (rmw_send_request(
client->impl->rmw_handle, ros_request, sequence_number) != RMW_RET_OK)
@@ -259,9 +259,10 @@ rcl_take_response(
rmw_request_id_t * request_header,
void * ros_response)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
- RCL_CHECK_FOR_NULL_WITH_MSG(
- client->impl, "client is invalid", return RCL_RET_CLIENT_INVALID, rcl_get_default_allocator());
+ if (!rcl_client_is_valid(client)) {
+ return RCL_RET_CLIENT_INVALID;
+ }
+
RCL_CHECK_ARGUMENT_FOR_NULL(
request_header, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
RCL_CHECK_ARGUMENT_FOR_NULL(ros_response, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
@@ -280,7 +281,18 @@ rcl_take_response(
return RCL_RET_OK;
}
-
+bool rcl_client_is_valid(const rcl_client_t * client)
+{
+ const rcl_client_options_t * options;
+ RCL_CHECK_ARGUMENT_FOR_NULL(
+ client, false, rcl_get_default_allocator());
+ options = _client_get_options(client);
+ RCL_CHECK_FOR_NULL_WITH_MSG(
+ options, "client's options pointer is invalid", return false, rcl_get_default_allocator());
+ RCL_CHECK_FOR_NULL_WITH_MSG(
+ client->impl, "client's rmw implementation is invalid", return false, options->allocator);
+ return true;
+}
#if __cplusplus
}
#endif
diff --git a/rcl/src/rcl/publisher.c b/rcl/src/rcl/publisher.c
index 1adf98f..655b26d 100644
--- a/rcl/src/rcl/publisher.c
+++ b/rcl/src/rcl/publisher.c
@@ -199,16 +199,11 @@ rcl_publisher_get_default_options()
rcl_ret_t
rcl_publish(const rcl_publisher_t * publisher, const void * ros_message)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
- const rcl_publisher_options_t * options = rcl_publisher_get_options(publisher);
- if (!options) {
+ if (!rcl_publisher_is_valid(publisher)) {
return RCL_RET_PUBLISHER_INVALID;
}
- RCL_CHECK_ARGUMENT_FOR_NULL(ros_message, RCL_RET_INVALID_ARGUMENT, options->allocator);
- RCL_CHECK_FOR_NULL_WITH_MSG(
- publisher->impl, "publisher is invalid", return RCL_RET_PUBLISHER_INVALID, options->allocator);
if (rmw_publish(publisher->impl->rmw_handle, ros_message) != RMW_RET_OK) {
- RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), options->allocator);
+ RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), rcl_get_default_allocator());
return RCL_RET_ERROR;
}
return RCL_RET_OK;
@@ -217,35 +212,49 @@ rcl_publish(const rcl_publisher_t * publisher, const void * ros_message)
const char *
rcl_publisher_get_topic_name(const rcl_publisher_t * publisher)
{
- const rcl_publisher_options_t * options = rcl_publisher_get_options(publisher);
- if (!options) {
+ if (!rcl_publisher_is_valid(publisher)) {
return NULL;
}
- RCL_CHECK_FOR_NULL_WITH_MSG(
- publisher->impl, "publisher is invalid", return NULL, options->allocator);
- RCL_CHECK_FOR_NULL_WITH_MSG(
- publisher->impl->rmw_handle, "publisher is invalid", return NULL, options->allocator);
return publisher->impl->rmw_handle->topic_name;
}
+/* *INDENT-OFF* */
+#define _publisher_get_options(pub) &pub->impl->options
+/* *INDENT-ON* */
+
const rcl_publisher_options_t *
rcl_publisher_get_options(const rcl_publisher_t * publisher)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(publisher, NULL, rcl_get_default_allocator());
- RCL_CHECK_FOR_NULL_WITH_MSG(
- publisher->impl, "publisher is invalid", return NULL, rcl_get_default_allocator());
- return &publisher->impl->options;
+ if (!rcl_publisher_is_valid(publisher)) {
+ return NULL;
+ }
+ return _publisher_get_options(publisher);
}
rmw_publisher_t *
rcl_publisher_get_rmw_handle(const rcl_publisher_t * publisher)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(publisher, NULL, rcl_get_default_allocator());
- RCL_CHECK_FOR_NULL_WITH_MSG(
- publisher->impl, "publisher is invalid", return NULL, rcl_get_default_allocator());
+ if (!rcl_publisher_is_valid(publisher)) {
+ return NULL;
+ }
return publisher->impl->rmw_handle;
}
+bool
+rcl_publisher_is_valid(const rcl_publisher_t * publisher)
+{
+ const rcl_publisher_options_t * options;
+ RCL_CHECK_ARGUMENT_FOR_NULL(publisher, false, rcl_get_default_allocator());
+ options = _publisher_get_options(publisher);
+ RCL_CHECK_FOR_NULL_WITH_MSG(
+ options, "publisher's options pointer is invalid", return false, rcl_get_default_allocator());
+ RCL_CHECK_FOR_NULL_WITH_MSG(
+ publisher->impl, "publisher implementation is invalid", return false, options->allocator);
+ RCL_CHECK_FOR_NULL_WITH_MSG(
+ publisher->impl->rmw_handle, "publisher rmw handle invalid", return false, options->allocator);
+ return true;
+}
+
#if __cplusplus
}
#endif
diff --git a/rcl/src/rcl/service.c b/rcl/src/rcl/service.c
index dd37f27..ebfcb34 100644
--- a/rcl/src/rcl/service.c
+++ b/rcl/src/rcl/service.c
@@ -211,21 +211,25 @@ rcl_service_get_service_name(const rcl_service_t * service)
return service->impl->rmw_handle->service_name;
}
+/* *INDENT-OFF* */
+#define _service_get_options(service) &service->impl->options
+/* *INDENT-ON* */
+
const rcl_service_options_t *
rcl_service_get_options(const rcl_service_t * service)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(service, NULL, rcl_get_default_allocator());
- RCL_CHECK_FOR_NULL_WITH_MSG(
- service->impl, "service is invalid", return NULL, rcl_get_default_allocator());
- return &service->impl->options;
+ if (!rcl_service_is_valid(service)) {
+ return NULL;
+ }
+ return _service_get_options(service);
}
rmw_service_t *
rcl_service_get_rmw_handle(const rcl_service_t * service)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(service, NULL, rcl_get_default_allocator());
- RCL_CHECK_FOR_NULL_WITH_MSG(
- service->impl, "service is invalid", return NULL, rcl_get_default_allocator());
+ if (!rcl_service_is_valid(service)) {
+ return NULL;
+ }
return service->impl->rmw_handle;
}
@@ -235,11 +239,7 @@ rcl_take_request(
rmw_request_id_t * request_header,
void * ros_request)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
const rcl_service_options_t * options = rcl_service_get_options(service);
- if (!options) {
- return RCL_RET_SERVICE_INVALID;
- }
RCL_CHECK_ARGUMENT_FOR_NULL(request_header, RCL_RET_INVALID_ARGUMENT, options->allocator);
RCL_CHECK_ARGUMENT_FOR_NULL(ros_request, RCL_RET_INVALID_ARGUMENT, options->allocator);
@@ -262,11 +262,7 @@ rcl_send_response(
rmw_request_id_t * request_header,
void * ros_response)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
const rcl_service_options_t * options = rcl_service_get_options(service);
- if (!options) {
- return RCL_RET_SERVICE_INVALID;
- }
RCL_CHECK_ARGUMENT_FOR_NULL(request_header, RCL_RET_INVALID_ARGUMENT, options->allocator);
RCL_CHECK_ARGUMENT_FOR_NULL(ros_response, RCL_RET_INVALID_ARGUMENT, options->allocator);
@@ -280,6 +276,27 @@ rcl_send_response(
return RCL_RET_OK;
}
+bool
+rcl_service_is_valid(const rcl_service_t * service)
+{
+ const rcl_service_options_t * options;
+ RCL_CHECK_ARGUMENT_FOR_NULL(service, false, rcl_get_default_allocator());
+ options = _service_get_options(service);
+ RCL_CHECK_FOR_NULL_WITH_MSG(options,
+ "service's options pointer is invalid",
+ return false,
+ rcl_get_default_allocator());
+ RCL_CHECK_FOR_NULL_WITH_MSG(service->impl,
+ "service implementation is invalid",
+ return false,
+ options->allocator);
+ RCL_CHECK_FOR_NULL_WITH_MSG(service->impl->rmw_handle,
+ "service's rmw handle is invalid",
+ return false,
+ options->allocator);
+ return true;
+}
+
#if __cplusplus
}
#endif
diff --git a/rcl/src/rcl/subscription.c b/rcl/src/rcl/subscription.c
index 343c393..fd3cd73 100644
--- a/rcl/src/rcl/subscription.c
+++ b/rcl/src/rcl/subscription.c
@@ -231,34 +231,55 @@ rcl_take(
const char *
rcl_subscription_get_topic_name(const rcl_subscription_t * subscription)
{
- const rcl_subscription_options_t * options = rcl_subscription_get_options(subscription);
- if (!options) {
+ if (!rcl_subscription_is_valid(subscription)) {
return NULL;
}
- RCL_CHECK_FOR_NULL_WITH_MSG(
- subscription->impl->rmw_handle,
- "subscription is invalid", return NULL, options->allocator);
return subscription->impl->rmw_handle->topic_name;
}
+/* *INDENT-OFF* */
+#define _subscription_get_options(subscription) &subscription->impl->options
+/* *INDENT-ON* */
+
const rcl_subscription_options_t *
rcl_subscription_get_options(const rcl_subscription_t * subscription)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(subscription, NULL, rcl_get_default_allocator());
- RCL_CHECK_FOR_NULL_WITH_MSG(
- subscription->impl, "subscription is invalid", return NULL, rcl_get_default_allocator());
- return &subscription->impl->options;
+ if (!rcl_subscription_is_valid(subscription)) {
+ return NULL;
+ }
+ return _subscription_get_options(subscription);
}
rmw_subscription_t *
rcl_subscription_get_rmw_handle(const rcl_subscription_t * subscription)
{
- RCL_CHECK_ARGUMENT_FOR_NULL(subscription, NULL, rcl_get_default_allocator());
- RCL_CHECK_FOR_NULL_WITH_MSG(
- subscription->impl, "subscription is invalid", return NULL, rcl_get_default_allocator());
+ if (!rcl_subscription_is_valid(subscription)) {
+ return NULL;
+ }
return subscription->impl->rmw_handle;
}
+bool
+rcl_subscription_is_valid(const rcl_subscription_t * subscription)
+{
+ const rcl_subscription_options_t * options;
+ RCL_CHECK_ARGUMENT_FOR_NULL(subscription, false, rcl_get_default_allocator());
+ options = _subscription_get_options(subscription);
+ RCL_CHECK_FOR_NULL_WITH_MSG(options,
+ "subscription's option pointer is invalid",
+ return false,
+ rcl_get_default_allocator());
+ RCL_CHECK_FOR_NULL_WITH_MSG(subscription->impl,
+ "subscription implementation is invalid",
+ return false,
+ options->allocator);
+ RCL_CHECK_FOR_NULL_WITH_MSG(subscription->impl->rmw_handle,
+ "subscription implementation rmw_handle is invalid",
+ return false,
+ options->allocator);
+ return true;
+}
+
#if __cplusplus
}
#endif