Implement is valid methods (#103)

* Implemented service is valid check.

* Added an is-valid check for publishers.

* Changed the checks to the single call to

* Added subscription is_valid function, and replaced individual checks with a call to the function in the subscription code.

* Added documentation for is_valid functions.

* Moved the options pointer check into the is_valid function.

* Implemented client checks.
This commit is contained in:
Hunter Allen 2017-07-18 13:12:06 -07:00 committed by GitHub
parent a57f66b54c
commit af03d0c44d
8 changed files with 212 additions and 64 deletions

View file

@ -370,6 +370,28 @@ RCL_WARN_UNUSED
rmw_client_t * rmw_client_t *
rcl_client_get_rmw_handle(const rcl_client_t * client); 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.
*
* <hr>
* 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 #if __cplusplus
} }
#endif #endif

View file

@ -336,6 +336,29 @@ RCL_WARN_UNUSED
rmw_publisher_t * rmw_publisher_t *
rcl_publisher_get_rmw_handle(const rcl_publisher_t * publisher); 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.
*
* <hr>
* 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 #if __cplusplus
} }
#endif #endif

View file

@ -382,6 +382,28 @@ RCL_WARN_UNUSED
rmw_service_t * rmw_service_t *
rcl_service_get_rmw_handle(const rcl_service_t * service); 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.
*
* <hr>
* 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 #if __cplusplus
} }
#endif #endif

View file

@ -339,6 +339,28 @@ RCL_WARN_UNUSED
rmw_subscription_t * rmw_subscription_t *
rcl_subscription_get_rmw_handle(const rcl_subscription_t * subscription); 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.
*
* <hr>
* 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 #if __cplusplus
} }
#endif #endif

View file

@ -201,29 +201,29 @@ rcl_client_get_default_options()
const char * const char *
rcl_client_get_service_name(const rcl_client_t * client) rcl_client_get_service_name(const rcl_client_t * client)
{ {
const rcl_client_options_t * options = rcl_client_get_options(client); if (!rcl_client_is_valid(client)) {
if (!options) {
return NULL; // error already set 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; return client->impl->rmw_handle->service_name;
} }
/* *INDENT-OFF* */
#define _client_get_options(client) &client->impl->options;
/* *INDENT-ON* */
const rcl_client_options_t * const rcl_client_options_t *
rcl_client_get_options(const rcl_client_t * client) rcl_client_get_options(const rcl_client_t * client)
{ {
RCL_CHECK_ARGUMENT_FOR_NULL(client, NULL, rcl_get_default_allocator()); if (!rcl_client_is_valid(client)) {
RCL_CHECK_FOR_NULL_WITH_MSG( return NULL; // error already set
client->impl, "client is invalid", return NULL, rcl_get_default_allocator()); }
return &client->impl->options; return _client_get_options(client);
} }
rmw_client_t * rmw_client_t *
rcl_client_get_rmw_handle(const rcl_client_t * client) rcl_client_get_rmw_handle(const rcl_client_t * client)
{ {
const rcl_client_options_t * options = rcl_client_get_options(client); if (!rcl_client_is_valid(client)) {
if (!options) {
return NULL; // error already set return NULL; // error already set
} }
return client->impl->rmw_handle; return client->impl->rmw_handle;
@ -234,12 +234,12 @@ RCL_WARN_UNUSED
rcl_ret_t rcl_ret_t
rcl_send_request(const rcl_client_t * client, const void * ros_request, int64_t * sequence_number) 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(ros_request, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
RCL_CHECK_ARGUMENT_FOR_NULL( RCL_CHECK_ARGUMENT_FOR_NULL(
sequence_number, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); 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); *sequence_number = rcl_atomic_load_int64_t(&client->impl->sequence_number);
if (rmw_send_request( if (rmw_send_request(
client->impl->rmw_handle, ros_request, sequence_number) != RMW_RET_OK) client->impl->rmw_handle, ros_request, sequence_number) != RMW_RET_OK)
@ -259,9 +259,10 @@ rcl_take_response(
rmw_request_id_t * request_header, rmw_request_id_t * request_header,
void * ros_response) void * ros_response)
{ {
RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); if (!rcl_client_is_valid(client)) {
RCL_CHECK_FOR_NULL_WITH_MSG( return RCL_RET_CLIENT_INVALID;
client->impl, "client is invalid", return RCL_RET_CLIENT_INVALID, rcl_get_default_allocator()); }
RCL_CHECK_ARGUMENT_FOR_NULL( RCL_CHECK_ARGUMENT_FOR_NULL(
request_header, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); 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()); 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; 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 #if __cplusplus
} }
#endif #endif

View file

@ -199,16 +199,11 @@ rcl_publisher_get_default_options()
rcl_ret_t rcl_ret_t
rcl_publish(const rcl_publisher_t * publisher, const void * ros_message) 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()); if (!rcl_publisher_is_valid(publisher)) {
const rcl_publisher_options_t * options = rcl_publisher_get_options(publisher);
if (!options) {
return RCL_RET_PUBLISHER_INVALID; 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) { 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_ERROR;
} }
return RCL_RET_OK; return RCL_RET_OK;
@ -217,35 +212,49 @@ rcl_publish(const rcl_publisher_t * publisher, const void * ros_message)
const char * const char *
rcl_publisher_get_topic_name(const rcl_publisher_t * publisher) rcl_publisher_get_topic_name(const rcl_publisher_t * publisher)
{ {
const rcl_publisher_options_t * options = rcl_publisher_get_options(publisher); if (!rcl_publisher_is_valid(publisher)) {
if (!options) {
return NULL; 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; return publisher->impl->rmw_handle->topic_name;
} }
/* *INDENT-OFF* */
#define _publisher_get_options(pub) &pub->impl->options
/* *INDENT-ON* */
const rcl_publisher_options_t * const rcl_publisher_options_t *
rcl_publisher_get_options(const rcl_publisher_t * publisher) rcl_publisher_get_options(const rcl_publisher_t * publisher)
{ {
RCL_CHECK_ARGUMENT_FOR_NULL(publisher, NULL, rcl_get_default_allocator()); if (!rcl_publisher_is_valid(publisher)) {
RCL_CHECK_FOR_NULL_WITH_MSG( return NULL;
publisher->impl, "publisher is invalid", return NULL, rcl_get_default_allocator()); }
return &publisher->impl->options; return _publisher_get_options(publisher);
} }
rmw_publisher_t * rmw_publisher_t *
rcl_publisher_get_rmw_handle(const rcl_publisher_t * publisher) rcl_publisher_get_rmw_handle(const rcl_publisher_t * publisher)
{ {
RCL_CHECK_ARGUMENT_FOR_NULL(publisher, NULL, rcl_get_default_allocator()); if (!rcl_publisher_is_valid(publisher)) {
RCL_CHECK_FOR_NULL_WITH_MSG( return NULL;
publisher->impl, "publisher is invalid", return NULL, rcl_get_default_allocator()); }
return publisher->impl->rmw_handle; 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 #if __cplusplus
} }
#endif #endif

View file

@ -211,21 +211,25 @@ rcl_service_get_service_name(const rcl_service_t * service)
return service->impl->rmw_handle->service_name; return service->impl->rmw_handle->service_name;
} }
/* *INDENT-OFF* */
#define _service_get_options(service) &service->impl->options
/* *INDENT-ON* */
const rcl_service_options_t * const rcl_service_options_t *
rcl_service_get_options(const rcl_service_t * service) rcl_service_get_options(const rcl_service_t * service)
{ {
RCL_CHECK_ARGUMENT_FOR_NULL(service, NULL, rcl_get_default_allocator()); if (!rcl_service_is_valid(service)) {
RCL_CHECK_FOR_NULL_WITH_MSG( return NULL;
service->impl, "service is invalid", return NULL, rcl_get_default_allocator()); }
return &service->impl->options; return _service_get_options(service);
} }
rmw_service_t * rmw_service_t *
rcl_service_get_rmw_handle(const rcl_service_t * service) rcl_service_get_rmw_handle(const rcl_service_t * service)
{ {
RCL_CHECK_ARGUMENT_FOR_NULL(service, NULL, rcl_get_default_allocator()); if (!rcl_service_is_valid(service)) {
RCL_CHECK_FOR_NULL_WITH_MSG( return NULL;
service->impl, "service is invalid", return NULL, rcl_get_default_allocator()); }
return service->impl->rmw_handle; return service->impl->rmw_handle;
} }
@ -235,11 +239,7 @@ rcl_take_request(
rmw_request_id_t * request_header, rmw_request_id_t * request_header,
void * ros_request) 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); 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(request_header, RCL_RET_INVALID_ARGUMENT, options->allocator);
RCL_CHECK_ARGUMENT_FOR_NULL(ros_request, 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, rmw_request_id_t * request_header,
void * ros_response) 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); 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(request_header, RCL_RET_INVALID_ARGUMENT, options->allocator);
RCL_CHECK_ARGUMENT_FOR_NULL(ros_response, 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; 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 #if __cplusplus
} }
#endif #endif

View file

@ -231,34 +231,55 @@ rcl_take(
const char * const char *
rcl_subscription_get_topic_name(const rcl_subscription_t * subscription) rcl_subscription_get_topic_name(const rcl_subscription_t * subscription)
{ {
const rcl_subscription_options_t * options = rcl_subscription_get_options(subscription); if (!rcl_subscription_is_valid(subscription)) {
if (!options) {
return NULL; 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; return subscription->impl->rmw_handle->topic_name;
} }
/* *INDENT-OFF* */
#define _subscription_get_options(subscription) &subscription->impl->options
/* *INDENT-ON* */
const rcl_subscription_options_t * const rcl_subscription_options_t *
rcl_subscription_get_options(const rcl_subscription_t * subscription) rcl_subscription_get_options(const rcl_subscription_t * subscription)
{ {
RCL_CHECK_ARGUMENT_FOR_NULL(subscription, NULL, rcl_get_default_allocator()); if (!rcl_subscription_is_valid(subscription)) {
RCL_CHECK_FOR_NULL_WITH_MSG( return NULL;
subscription->impl, "subscription is invalid", return NULL, rcl_get_default_allocator()); }
return &subscription->impl->options; return _subscription_get_options(subscription);
} }
rmw_subscription_t * rmw_subscription_t *
rcl_subscription_get_rmw_handle(const rcl_subscription_t * subscription) rcl_subscription_get_rmw_handle(const rcl_subscription_t * subscription)
{ {
RCL_CHECK_ARGUMENT_FOR_NULL(subscription, NULL, rcl_get_default_allocator()); if (!rcl_subscription_is_valid(subscription)) {
RCL_CHECK_FOR_NULL_WITH_MSG( return NULL;
subscription->impl, "subscription is invalid", return NULL, rcl_get_default_allocator()); }
return subscription->impl->rmw_handle; 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 #if __cplusplus
} }
#endif #endif