move allocator and error handling to c utilities (#122)
* moved allocator to c_utilities * moved error_handling to c_utilities * refactor uses of RCL_SET_ERROR_MSG with allocator * add missing guard condition functions and tests * add missing timer functions * refactor rcl_lifecycyle * missed an instance of RCL_SET_ERROR_MSG * fix segfaults in error cases for rcl_lifecycle * remove extra header * check return code of rcl_lifecycle_init_default_state_machine
This commit is contained in:
parent
415612f8af
commit
90176d9f1a
33 changed files with 872 additions and 618 deletions
|
@ -23,7 +23,6 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(${PROJECT_NAME}_sources
|
set(${PROJECT_NAME}_sources
|
||||||
src/rcl/allocator.c
|
|
||||||
src/rcl/client.c
|
src/rcl/client.c
|
||||||
src/rcl/common.c
|
src/rcl/common.c
|
||||||
src/rcl/graph.c
|
src/rcl/graph.c
|
||||||
|
@ -66,6 +65,7 @@ install(
|
||||||
set(rcl_lib_dir "$<TARGET_FILE_DIR:${PROJECT_NAME}>")
|
set(rcl_lib_dir "$<TARGET_FILE_DIR:${PROJECT_NAME}>")
|
||||||
|
|
||||||
ament_export_dependencies(ament_cmake)
|
ament_export_dependencies(ament_cmake)
|
||||||
|
ament_export_dependencies(c_utilities)
|
||||||
ament_export_dependencies(rcl_interfaces)
|
ament_export_dependencies(rcl_interfaces)
|
||||||
ament_export_dependencies(rmw)
|
ament_export_dependencies(rmw)
|
||||||
ament_export_dependencies(rmw_implementation)
|
ament_export_dependencies(rmw_implementation)
|
||||||
|
|
|
@ -20,79 +20,13 @@ extern "C"
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "rcl/macros.h"
|
#include "c_utilities/allocator.h"
|
||||||
#include "rcl/types.h"
|
|
||||||
#include "rcl/visibility_control.h"
|
|
||||||
|
|
||||||
/// Encapsulation of an allocator.
|
typedef utilities_allocator_t rcl_allocator_t;
|
||||||
/**
|
|
||||||
* The default allocator uses std::malloc(), std::free(), and std::realloc().
|
|
||||||
* It can be obtained using rcl_get_default_allocator().
|
|
||||||
*
|
|
||||||
* The allocator should be trivially copyable.
|
|
||||||
* Meaning that the struct should continue to work after being assignment
|
|
||||||
* copied into a new struct.
|
|
||||||
* Specifically the object pointed to by the state pointer should remain valid
|
|
||||||
* until all uses of the allocator have been made.
|
|
||||||
* Particular care should be taken when giving an allocator to rcl_init_* where
|
|
||||||
* it is stored within another object and used later.
|
|
||||||
*/
|
|
||||||
typedef struct rcl_allocator_t
|
|
||||||
{
|
|
||||||
/// Allocate memory, given a size and the `state` pointer.
|
|
||||||
/** An error should be indicated by returning `NULL`. */
|
|
||||||
void * (*allocate)(size_t size, void * state);
|
|
||||||
/// Deallocate previously allocated memory, mimicking std::free().
|
|
||||||
/** Also takes the `state` pointer. */
|
|
||||||
void (* deallocate)(void * pointer, void * state);
|
|
||||||
/// Reallocate if possible, otherwise it deallocates and allocates.
|
|
||||||
/**
|
|
||||||
* Also takes the `state` pointer.
|
|
||||||
*
|
|
||||||
* If unsupported then do deallocate and then allocate.
|
|
||||||
* This should behave as std::realloc() does, as opposed to posix's
|
|
||||||
* [reallocf](https://linux.die.net/man/3/reallocf), i.e. the memory given
|
|
||||||
* by pointer will not be free'd automatically if std::realloc() fails.
|
|
||||||
* For reallocf-like behavior use rcl_reallocf().
|
|
||||||
* This function must be able to take an input pointer of `NULL` and succeed.
|
|
||||||
*/
|
|
||||||
void * (*reallocate)(void * pointer, size_t size, void * state);
|
|
||||||
/// Implementation defined state storage.
|
|
||||||
/** This is passed as the final parameter to other allocator functions. */
|
|
||||||
void * state;
|
|
||||||
} rcl_allocator_t;
|
|
||||||
|
|
||||||
/// Return a properly initialized rcl_allocator_t with default values.
|
#define rcl_get_default_allocator utilities_get_default_allocator
|
||||||
/**
|
|
||||||
* This defaults to:
|
|
||||||
*
|
|
||||||
* - allocate = wraps std::malloc()
|
|
||||||
* - deallocate = wraps std::free()
|
|
||||||
* - reallocate = wrapps std::realloc()
|
|
||||||
* - state = `NULL`
|
|
||||||
*
|
|
||||||
* <hr>
|
|
||||||
* Attribute | Adherence
|
|
||||||
* ------------------ | -------------
|
|
||||||
* Allocates Memory | No
|
|
||||||
* Thread-Safe | Yes
|
|
||||||
* Uses Atomics | No
|
|
||||||
* Lock-Free | Yes
|
|
||||||
*/
|
|
||||||
RCL_PUBLIC
|
|
||||||
RCL_WARN_UNUSED
|
|
||||||
rcl_allocator_t
|
|
||||||
rcl_get_default_allocator(void);
|
|
||||||
|
|
||||||
/// Emulate the behavior of [reallocf](https://linux.die.net/man/3/reallocf).
|
#define rcl_reallocf utilities_reallocf
|
||||||
/**
|
|
||||||
* This function will return `NULL` if the allocator is `NULL` or has `NULL` for
|
|
||||||
* function pointer fields.
|
|
||||||
*/
|
|
||||||
RCL_PUBLIC
|
|
||||||
RCL_WARN_UNUSED
|
|
||||||
void *
|
|
||||||
rcl_reallocf(void * pointer, size_t size, rcl_allocator_t * allocator);
|
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,24 +15,34 @@
|
||||||
#ifndef RCL__ERROR_HANDLING_H_
|
#ifndef RCL__ERROR_HANDLING_H_
|
||||||
#define RCL__ERROR_HANDLING_H_
|
#define RCL__ERROR_HANDLING_H_
|
||||||
|
|
||||||
#include "rmw/error_handling.h"
|
#include "c_utilities/error_handling.h"
|
||||||
|
|
||||||
/* The error handling in RCL is just an alias to the error handling in RMW. */
|
/// The error handling in RCL is just an alias to the error handling in c_utilities.
|
||||||
|
/**
|
||||||
|
* Allocators given to functions in rcl are passed along to the error handling
|
||||||
|
* on a "best effort" basis.
|
||||||
|
* In some situations, like when NULL is passed for the allocator or something
|
||||||
|
* else that contains it, the allocator is not available to be passed to the
|
||||||
|
* RCL_SET_ERROR_MSG macro.
|
||||||
|
* In these cases, the default allocator rcl_get_default_allocator() is used.
|
||||||
|
* Since these are considered fatal errors, as opposed to errors that might
|
||||||
|
* occur during normal runtime, is should be okay to use the default allocator.
|
||||||
|
*/
|
||||||
|
|
||||||
typedef rmw_error_state_t rcl_error_state_t;
|
typedef utilities_error_state_t rcl_error_state_t;
|
||||||
|
|
||||||
#define rcl_set_error_state rmw_set_error_state
|
#define rcl_set_error_state utilities_set_error_state
|
||||||
|
|
||||||
#define RCL_SET_ERROR_MSG(msg) RMW_SET_ERROR_MSG(msg)
|
#define RCL_SET_ERROR_MSG(msg, allocator) UTILITIES_SET_ERROR_MSG(msg, allocator)
|
||||||
|
|
||||||
#define rcl_error_is_set rmw_error_is_set
|
#define rcl_error_is_set utilities_error_is_set
|
||||||
|
|
||||||
#define rcl_get_error_state rmw_get_error_state
|
#define rcl_get_error_state utilities_get_error_state
|
||||||
|
|
||||||
#define rcl_get_error_string rmw_get_error_string
|
#define rcl_get_error_string utilities_get_error_string
|
||||||
|
|
||||||
#define rcl_get_error_string_safe rmw_get_error_string_safe
|
#define rcl_get_error_string_safe utilities_get_error_string_safe
|
||||||
|
|
||||||
#define rcl_reset_error rmw_reset_error
|
#define rcl_reset_error utilities_reset_error
|
||||||
|
|
||||||
#endif // RCL__ERROR_HANDLING_H_
|
#endif // RCL__ERROR_HANDLING_H_
|
||||||
|
|
|
@ -63,6 +63,7 @@ rcl_get_zero_initialized_topic_names_and_types(void);
|
||||||
* <i>[1] implementation may need to protect the data structure with a lock</i>
|
* <i>[1] implementation may need to protect the data structure with a lock</i>
|
||||||
*
|
*
|
||||||
* \param[in] node the handle to the node being used to query the ROS graph
|
* \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] topic_names_and_types list of topic names and their types
|
* \param[out] topic_names_and_types list of topic names and their types
|
||||||
* \return `RCL_RET_OK` if the query was successful, or
|
* \return `RCL_RET_OK` if the query was successful, or
|
||||||
* \return `RCL_RET_NODE_INVALID` if the node is invalid, or
|
* \return `RCL_RET_NODE_INVALID` if the node is invalid, or
|
||||||
|
@ -74,6 +75,7 @@ RCL_WARN_UNUSED
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_get_topic_names_and_types(
|
rcl_get_topic_names_and_types(
|
||||||
const rcl_node_t * node,
|
const rcl_node_t * node,
|
||||||
|
rcl_allocator_t allocator,
|
||||||
rcl_topic_names_and_types_t * topic_names_and_types);
|
rcl_topic_names_and_types_t * topic_names_and_types);
|
||||||
|
|
||||||
/// Destroy a struct which was previously given to rcl_get_topic_names_and_types.
|
/// Destroy a struct which was previously given to rcl_get_topic_names_and_types.
|
||||||
|
@ -151,6 +153,7 @@ RCL_WARN_UNUSED
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_get_node_names(
|
rcl_get_node_names(
|
||||||
const rcl_node_t * node,
|
const rcl_node_t * node,
|
||||||
|
rcl_allocator_t allocator,
|
||||||
utilities_string_array_t * node_names);
|
utilities_string_array_t * node_names);
|
||||||
|
|
||||||
/// Return the number of publishers on a given topic.
|
/// Return the number of publishers on a given topic.
|
||||||
|
@ -166,6 +169,9 @@ rcl_get_node_names(
|
||||||
* The count parameter must not be `NULL`, and must point to a valid bool.
|
* The count parameter must not be `NULL`, and must point to a valid bool.
|
||||||
* The count parameter is the output for this function and will be set.
|
* The count parameter is the output for this function and will be set.
|
||||||
*
|
*
|
||||||
|
* In the event that error handling needs to allocate memory, this function
|
||||||
|
* will try to use the node's allocator.
|
||||||
|
*
|
||||||
* <hr>
|
* <hr>
|
||||||
* Attribute | Adherence
|
* Attribute | Adherence
|
||||||
* ------------------ | -------------
|
* ------------------ | -------------
|
||||||
|
@ -204,6 +210,9 @@ rcl_count_publishers(
|
||||||
* The count parameter must not be `NULL`, and must point to a valid bool.
|
* The count parameter must not be `NULL`, and must point to a valid bool.
|
||||||
* The count parameter is the output for this function and will be set.
|
* The count parameter is the output for this function and will be set.
|
||||||
*
|
*
|
||||||
|
* In the event that error handling needs to allocate memory, this function
|
||||||
|
* will try to use the node's allocator.
|
||||||
|
*
|
||||||
* <hr>
|
* <hr>
|
||||||
* Attribute | Adherence
|
* Attribute | Adherence
|
||||||
* ------------------ | -------------
|
* ------------------ | -------------
|
||||||
|
@ -244,6 +253,9 @@ rcl_count_subscribers(
|
||||||
* The is_available parameter must not be `NULL`, and must point a bool variable.
|
* The is_available parameter must not be `NULL`, and must point a bool variable.
|
||||||
* The result of the check will be stored in the is_available parameter.
|
* The result of the check will be stored in the is_available parameter.
|
||||||
*
|
*
|
||||||
|
* In the event that error handling needs to allocate memory, this function
|
||||||
|
* will try to use the node's allocator.
|
||||||
|
*
|
||||||
* <hr>
|
* <hr>
|
||||||
* Attribute | Adherence
|
* Attribute | Adherence
|
||||||
* ------------------ | -------------
|
* ------------------ | -------------
|
||||||
|
|
|
@ -189,6 +189,31 @@ RCL_WARN_UNUSED
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_trigger_guard_condition(rcl_guard_condition_t * guard_condition);
|
rcl_trigger_guard_condition(rcl_guard_condition_t * guard_condition);
|
||||||
|
|
||||||
|
/// Return the guard condition options.
|
||||||
|
/**
|
||||||
|
* Returned is a pointer to the internally held rcl_guard_condition_options_t.
|
||||||
|
* This function can fail, and therefore return `NULL`, if the:
|
||||||
|
* - guard_condition is `NULL`
|
||||||
|
* - guard_condition is invalid (never called init, called fini, or invalid node)
|
||||||
|
*
|
||||||
|
* The returned pointer is made invalid if the guard condition is finalized.
|
||||||
|
*
|
||||||
|
* <hr>
|
||||||
|
* Attribute | Adherence
|
||||||
|
* ------------------ | -------------
|
||||||
|
* Allocates Memory | No
|
||||||
|
* Thread-Safe | No
|
||||||
|
* Uses Atomics | No
|
||||||
|
* Lock-Free | Yes
|
||||||
|
*
|
||||||
|
* \param[in] guard_condition pointer to the rcl guard_condition
|
||||||
|
* \return rcl guard condition options if successful, otherwise `NULL`
|
||||||
|
*/
|
||||||
|
RCL_PUBLIC
|
||||||
|
RCL_WARN_UNUSED
|
||||||
|
const rcl_guard_condition_options_t *
|
||||||
|
rcl_guard_condition_get_options(const rcl_guard_condition_t * guard_condition);
|
||||||
|
|
||||||
/// Return the rmw guard condition handle.
|
/// Return the rmw guard condition handle.
|
||||||
/**
|
/**
|
||||||
* The handle returned is a pointer to the internally held rmw handle.
|
* The handle returned is a pointer to the internally held rmw handle.
|
||||||
|
@ -207,7 +232,7 @@ rcl_trigger_guard_condition(rcl_guard_condition_t * guard_condition);
|
||||||
* <hr>
|
* <hr>
|
||||||
* Attribute | Adherence
|
* Attribute | Adherence
|
||||||
* ------------------ | -------------
|
* ------------------ | -------------
|
||||||
* Allocates Memory | Yes
|
* Allocates Memory | No
|
||||||
* Thread-Safe | No
|
* Thread-Safe | No
|
||||||
* Uses Atomics | No
|
* Uses Atomics | No
|
||||||
* Lock-Free | Yes
|
* Lock-Free | Yes
|
||||||
|
|
|
@ -504,6 +504,28 @@ RCL_WARN_UNUSED
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_timer_reset(rcl_timer_t * timer);
|
rcl_timer_reset(rcl_timer_t * timer);
|
||||||
|
|
||||||
|
/// Return the allocator for the timer.
|
||||||
|
/**
|
||||||
|
* This function can fail, and therefore return `NULL`, if:
|
||||||
|
* - timer is `NULL`
|
||||||
|
* - timer has not been initialized (the implementation is invalid)
|
||||||
|
*
|
||||||
|
* The returned pointer is only valid as long as the timer object is valid.
|
||||||
|
*
|
||||||
|
* <hr>
|
||||||
|
* Attribute | Adherence
|
||||||
|
* ------------------ | -------------
|
||||||
|
* Allocates Memory | No
|
||||||
|
* Thread-Safe | Yes
|
||||||
|
* Uses Atomics | No
|
||||||
|
* Lock-Free | Yes
|
||||||
|
*
|
||||||
|
* \param[inout] timer handle to the timer object
|
||||||
|
* \return pointer to the allocator, or `NULL` if an error occurred
|
||||||
|
*/
|
||||||
|
const rcl_allocator_t *
|
||||||
|
rcl_timer_get_allocator(const rcl_timer_t * timer);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,12 +13,15 @@
|
||||||
|
|
||||||
<build_export_depend>rmw</build_export_depend>
|
<build_export_depend>rmw</build_export_depend>
|
||||||
|
|
||||||
|
<build_depend>c_utilities</build_depend>
|
||||||
<build_depend>rcl_interfaces</build_depend>
|
<build_depend>rcl_interfaces</build_depend>
|
||||||
<build_depend>rosidl_generator_c</build_depend>
|
<build_depend>rosidl_generator_c</build_depend>
|
||||||
|
<build_export_depend>c_utilities</build_export_depend>
|
||||||
<build_export_depend>rcl_interfaces</build_export_depend>
|
<build_export_depend>rcl_interfaces</build_export_depend>
|
||||||
<build_export_depend>rosidl_generator_c</build_export_depend>
|
<build_export_depend>rosidl_generator_c</build_export_depend>
|
||||||
|
|
||||||
<exec_depend>ament_cmake</exec_depend>
|
<exec_depend>ament_cmake</exec_depend>
|
||||||
|
<exec_depend>c_utilities</exec_depend>
|
||||||
<exec_depend>rosidl_default_runtime</exec_depend>
|
<exec_depend>rosidl_default_runtime</exec_depend>
|
||||||
|
|
||||||
<depend>rmw_implementation</depend>
|
<depend>rmw_implementation</depend>
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
// Copyright 2015 Open Source Robotics Foundation, Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "rcl/allocator.h"
|
|
||||||
#include "rcl/error_handling.h"
|
|
||||||
|
|
||||||
static void *
|
|
||||||
__default_allocate(size_t size, void * state)
|
|
||||||
{
|
|
||||||
(void)state; // unused
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
__default_deallocate(void * pointer, void * state)
|
|
||||||
{
|
|
||||||
(void)state; // unused
|
|
||||||
free(pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
__default_reallocate(void * pointer, size_t size, void * state)
|
|
||||||
{
|
|
||||||
(void)state; // unused
|
|
||||||
return realloc(pointer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
rcl_allocator_t
|
|
||||||
rcl_get_default_allocator()
|
|
||||||
{
|
|
||||||
static rcl_allocator_t default_allocator = {
|
|
||||||
__default_allocate,
|
|
||||||
__default_deallocate,
|
|
||||||
__default_reallocate,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
return default_allocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
rcl_reallocf(void * pointer, size_t size, rcl_allocator_t * allocator)
|
|
||||||
{
|
|
||||||
if (!allocator || !allocator->reallocate || !allocator->deallocate) {
|
|
||||||
RCL_SET_ERROR_MSG("invalid allocator or allocator function pointers");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
void * new_pointer = allocator->reallocate(pointer, size, allocator->state);
|
|
||||||
if (!new_pointer) {
|
|
||||||
allocator->deallocate(pointer, allocator->state);
|
|
||||||
}
|
|
||||||
return new_pointer;
|
|
||||||
}
|
|
|
@ -21,6 +21,7 @@ extern "C"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "rmw/error_handling.h"
|
||||||
#include "rmw/rmw.h"
|
#include "rmw/rmw.h"
|
||||||
|
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
|
@ -49,29 +50,34 @@ rcl_client_init(
|
||||||
const rcl_client_options_t * options)
|
const rcl_client_options_t * options)
|
||||||
{
|
{
|
||||||
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
// check the options and allocator first, so the allocator can be passed to errors
|
||||||
if (!node->impl) {
|
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_SET_ERROR_MSG("invalid node");
|
|
||||||
return RCL_RET_NODE_INVALID;
|
|
||||||
}
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(service_name, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
if (client->impl) {
|
|
||||||
RCL_SET_ERROR_MSG("client already initialized, or memory was unintialized");
|
|
||||||
return RCL_RET_ALREADY_INIT;
|
|
||||||
}
|
|
||||||
const rcl_allocator_t * allocator = &options->allocator;
|
const rcl_allocator_t * allocator = &options->allocator;
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->allocate, "allocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->allocate, "allocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->deallocate, "deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->deallocate, "deallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
if (!node->impl) {
|
||||||
|
RCL_SET_ERROR_MSG("invalid node", *allocator);
|
||||||
|
return RCL_RET_NODE_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(service_name, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
if (client->impl) {
|
||||||
|
RCL_SET_ERROR_MSG("client already initialized, or memory was unintialized", *allocator);
|
||||||
|
return RCL_RET_ALREADY_INIT;
|
||||||
|
}
|
||||||
// Allocate space for the implementation struct.
|
// Allocate space for the implementation struct.
|
||||||
client->impl = (rcl_client_impl_t *)allocator->allocate(
|
client->impl = (rcl_client_impl_t *)allocator->allocate(
|
||||||
sizeof(rcl_client_impl_t), allocator->state);
|
sizeof(rcl_client_impl_t), allocator->state);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
client->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
|
client->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC, *allocator);
|
||||||
// Fill out implementation struct.
|
// Fill out implementation struct.
|
||||||
// rmw handle (create rmw client)
|
// rmw handle (create rmw client)
|
||||||
// TODO(wjwwood): pass along the allocator to rmw when it supports it
|
// TODO(wjwwood): pass along the allocator to rmw when it supports it
|
||||||
|
@ -81,7 +87,7 @@ rcl_client_init(
|
||||||
service_name,
|
service_name,
|
||||||
&options->qos);
|
&options->qos);
|
||||||
if (!client->impl->rmw_handle) {
|
if (!client->impl->rmw_handle) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), *allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
// options
|
// options
|
||||||
|
@ -99,16 +105,16 @@ rcl_client_fini(rcl_client_t * client, rcl_node_t * node)
|
||||||
{
|
{
|
||||||
(void)node;
|
(void)node;
|
||||||
rcl_ret_t result = RCL_RET_OK;
|
rcl_ret_t result = RCL_RET_OK;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (client->impl) {
|
if (client->impl) {
|
||||||
|
rcl_allocator_t allocator = client->impl->options.allocator;
|
||||||
rmw_ret_t ret =
|
rmw_ret_t ret =
|
||||||
rmw_destroy_client(rcl_node_get_rmw_handle(node), client->impl->rmw_handle);
|
rmw_destroy_client(rcl_node_get_rmw_handle(node), client->impl->rmw_handle);
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), allocator);
|
||||||
result = RCL_RET_ERROR;
|
result = RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
rcl_allocator_t allocator = client->impl->options.allocator;
|
|
||||||
allocator.deallocate(client->impl, allocator.state);
|
allocator.deallocate(client->impl, allocator.state);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -128,29 +134,31 @@ 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)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(client, NULL);
|
const rcl_client_options_t * options = rcl_client_get_options(client);
|
||||||
|
if (!options) {
|
||||||
|
return NULL; // error already set
|
||||||
|
}
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
client->impl, "client is invalid", return NULL);
|
client->impl->rmw_handle, "client is invalid", return NULL, options->allocator);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
client->impl->rmw_handle, "client is invalid", return NULL);
|
|
||||||
return client->impl->rmw_handle->service_name;
|
return client->impl->rmw_handle->service_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_CHECK_ARGUMENT_FOR_NULL(client, NULL, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
client->impl, "client is invalid", return NULL);
|
client->impl, "client is invalid", return NULL, rcl_get_default_allocator());
|
||||||
return &client->impl->options;
|
return &client->impl->options;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(client, NULL);
|
const rcl_client_options_t * options = rcl_client_get_options(client);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
if (!options) {
|
||||||
client->impl, "client is invalid", return NULL);
|
return NULL; // error already set
|
||||||
|
}
|
||||||
return client->impl->rmw_handle;
|
return client->impl->rmw_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,16 +167,17 @@ 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_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(ros_request, RCL_RET_INVALID_ARGUMENT);
|
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_CHECK_ARGUMENT_FOR_NULL(
|
||||||
|
sequence_number, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
client->impl, "client is invalid", return RCL_RET_INVALID_ARGUMENT);
|
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)
|
||||||
{
|
{
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), client->impl->options.allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
rcl_atomic_exchange_int64_t(&client->impl->sequence_number, *sequence_number);
|
rcl_atomic_exchange_int64_t(&client->impl->sequence_number, *sequence_number);
|
||||||
|
@ -183,21 +192,22 @@ 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_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
client->impl, "client is invalid", return RCL_RET_INVALID_ARGUMENT);
|
client->impl, "client is invalid", return RCL_RET_CLIENT_INVALID, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(request_header, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(ros_response, RCL_RET_INVALID_ARGUMENT);
|
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());
|
||||||
|
|
||||||
bool taken = false;
|
bool taken = false;
|
||||||
if (rmw_take_response(
|
if (rmw_take_response(
|
||||||
client->impl->rmw_handle, request_header, ros_response, &taken) != RMW_RET_OK)
|
client->impl->rmw_handle, request_header, ros_response, &taken) != RMW_RET_OK)
|
||||||
{
|
{
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), client->impl->options.allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
if (!taken) {
|
if (!taken) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), client->impl->options.allocator);
|
||||||
return RCL_RET_CLIENT_TAKE_FAILED;
|
return RCL_RET_CLIENT_TAKE_FAILED;
|
||||||
}
|
}
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
|
|
|
@ -21,6 +21,8 @@ extern "C"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "rcl/allocator.h"
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
# define WINDOWS_ENV_BUFFER_SIZE 2048
|
# define WINDOWS_ENV_BUFFER_SIZE 2048
|
||||||
static char __env_buffer[WINDOWS_ENV_BUFFER_SIZE];
|
static char __env_buffer[WINDOWS_ENV_BUFFER_SIZE];
|
||||||
|
@ -29,8 +31,8 @@ static char __env_buffer[WINDOWS_ENV_BUFFER_SIZE];
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_impl_getenv(const char * env_name, const char ** env_value)
|
rcl_impl_getenv(const char * env_name, const char ** env_value)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(env_name, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(env_name, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(env_value, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(env_value, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
*env_value = NULL;
|
*env_value = NULL;
|
||||||
#if !defined(WIN32)
|
#if !defined(WIN32)
|
||||||
*env_value = getenv(env_name);
|
*env_value = getenv(env_name);
|
||||||
|
@ -41,7 +43,7 @@ rcl_impl_getenv(const char * env_name, const char ** env_value)
|
||||||
size_t required_size;
|
size_t required_size;
|
||||||
errno_t ret = getenv_s(&required_size, __env_buffer, sizeof(__env_buffer), env_name);
|
errno_t ret = getenv_s(&required_size, __env_buffer, sizeof(__env_buffer), env_name);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
RCL_SET_ERROR_MSG("value in env variable too large to read in");
|
RCL_SET_ERROR_MSG("value in env variable too large to read in", rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
__env_buffer[WINDOWS_ENV_BUFFER_SIZE - 1] = '\0';
|
__env_buffer[WINDOWS_ENV_BUFFER_SIZE - 1] = '\0';
|
||||||
|
|
|
@ -23,12 +23,13 @@ extern "C"
|
||||||
#include "rcl/error_handling.h"
|
#include "rcl/error_handling.h"
|
||||||
#include "rcl/types.h"
|
#include "rcl/types.h"
|
||||||
|
|
||||||
#define RCL_CHECK_ARGUMENT_FOR_NULL(argument, error_return_type) \
|
#define RCL_CHECK_ARGUMENT_FOR_NULL(argument, error_return_type, allocator) \
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(argument, #argument " argument is null", return error_return_type)
|
RCL_CHECK_FOR_NULL_WITH_MSG(argument, #argument " argument is null", \
|
||||||
|
return error_return_type, allocator)
|
||||||
|
|
||||||
#define RCL_CHECK_FOR_NULL_WITH_MSG(value, msg, error_statement) \
|
#define RCL_CHECK_FOR_NULL_WITH_MSG(value, msg, error_statement, allocator) \
|
||||||
if (!(value)) { \
|
if (!(value)) { \
|
||||||
RCL_SET_ERROR_MSG(msg); \
|
RCL_SET_ERROR_MSG(msg, allocator); \
|
||||||
error_statement; \
|
error_statement; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,23 +33,24 @@ rcl_get_zero_initialized_topic_names_and_types(void)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_get_topic_names_and_types(
|
rcl_get_topic_names_and_types(
|
||||||
const rcl_node_t * node,
|
const rcl_node_t * node,
|
||||||
|
rcl_allocator_t allocator,
|
||||||
rcl_topic_names_and_types_t * topic_names_and_types)
|
rcl_topic_names_and_types_t * topic_names_and_types)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, allocator);
|
||||||
if (!rcl_node_is_valid(node)) {
|
if (!rcl_node_is_valid(node)) {
|
||||||
return RCL_RET_NODE_INVALID;
|
return RCL_RET_NODE_INVALID;
|
||||||
}
|
}
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(topic_names_and_types, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(topic_names_and_types, RCL_RET_INVALID_ARGUMENT, allocator);
|
||||||
if (topic_names_and_types->topic_count != 0) {
|
if (topic_names_and_types->topic_count != 0) {
|
||||||
RCL_SET_ERROR_MSG("topic count is not zero");
|
RCL_SET_ERROR_MSG("topic count is not zero", allocator);
|
||||||
return RCL_RET_INVALID_ARGUMENT;
|
return RCL_RET_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
if (topic_names_and_types->topic_names) {
|
if (topic_names_and_types->topic_names) {
|
||||||
RCL_SET_ERROR_MSG("topic names is not null");
|
RCL_SET_ERROR_MSG("topic names is not null", allocator);
|
||||||
return RCL_RET_INVALID_ARGUMENT;
|
return RCL_RET_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
if (topic_names_and_types->type_names) {
|
if (topic_names_and_types->type_names) {
|
||||||
RCL_SET_ERROR_MSG("type names is not null");
|
RCL_SET_ERROR_MSG("type names is not null", allocator);
|
||||||
return RCL_RET_INVALID_ARGUMENT;
|
return RCL_RET_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
return rmw_get_topic_names_and_types(
|
return rmw_get_topic_names_and_types(
|
||||||
|
@ -62,26 +63,28 @@ rcl_ret_t
|
||||||
rcl_destroy_topic_names_and_types(
|
rcl_destroy_topic_names_and_types(
|
||||||
rcl_topic_names_and_types_t * topic_names_and_types)
|
rcl_topic_names_and_types_t * topic_names_and_types)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(topic_names_and_types, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(
|
||||||
|
topic_names_and_types, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
return rmw_destroy_topic_names_and_types(topic_names_and_types);
|
return rmw_destroy_topic_names_and_types(topic_names_and_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_get_node_names(
|
rcl_get_node_names(
|
||||||
const rcl_node_t * node,
|
const rcl_node_t * node,
|
||||||
|
rcl_allocator_t allocator,
|
||||||
utilities_string_array_t * node_names)
|
utilities_string_array_t * node_names)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, allocator);
|
||||||
if (!rcl_node_is_valid(node)) {
|
if (!rcl_node_is_valid(node)) {
|
||||||
return RCL_RET_NODE_INVALID;
|
return RCL_RET_NODE_INVALID;
|
||||||
}
|
}
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node_names, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node_names, RCL_RET_INVALID_ARGUMENT, allocator);
|
||||||
if (node_names->size != 0) {
|
if (node_names->size != 0) {
|
||||||
RCL_SET_ERROR_MSG("node_names size is not zero");
|
RCL_SET_ERROR_MSG("node_names size is not zero", allocator);
|
||||||
return RCL_RET_INVALID_ARGUMENT;
|
return RCL_RET_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
if (node_names->data) {
|
if (node_names->data) {
|
||||||
RCL_SET_ERROR_MSG("node_names is not null");
|
RCL_SET_ERROR_MSG("node_names is not null", allocator);
|
||||||
return RCL_RET_INVALID_ARGUMENT;
|
return RCL_RET_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
return rmw_get_node_names(
|
return rmw_get_node_names(
|
||||||
|
@ -95,12 +98,16 @@ rcl_count_publishers(
|
||||||
const char * topic_name,
|
const char * topic_name,
|
||||||
size_t * count)
|
size_t * count)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (!rcl_node_is_valid(node)) {
|
if (!rcl_node_is_valid(node)) {
|
||||||
return RCL_RET_NODE_INVALID;
|
return RCL_RET_NODE_INVALID;
|
||||||
}
|
}
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT);
|
const rcl_node_options_t * node_options = rcl_node_get_options(node);
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(count, RCL_RET_INVALID_ARGUMENT);
|
if (!node_options) {
|
||||||
|
return RCL_RET_NODE_INVALID; // shouldn't happen, but error is already set if so
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT, node_options->allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(count, RCL_RET_INVALID_ARGUMENT, node_options->allocator);
|
||||||
return rmw_count_publishers(rcl_node_get_rmw_handle(node), topic_name, count);
|
return rmw_count_publishers(rcl_node_get_rmw_handle(node), topic_name, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,12 +117,16 @@ rcl_count_subscribers(
|
||||||
const char * topic_name,
|
const char * topic_name,
|
||||||
size_t * count)
|
size_t * count)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (!rcl_node_is_valid(node)) {
|
if (!rcl_node_is_valid(node)) {
|
||||||
return RCL_RET_NODE_INVALID;
|
return RCL_RET_NODE_INVALID;
|
||||||
}
|
}
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT);
|
const rcl_node_options_t * node_options = rcl_node_get_options(node);
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(count, RCL_RET_INVALID_ARGUMENT);
|
if (!node_options) {
|
||||||
|
return RCL_RET_NODE_INVALID; // shouldn't happen, but error is already set if so
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT, node_options->allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(count, RCL_RET_INVALID_ARGUMENT, node_options->allocator);
|
||||||
return rmw_count_subscribers(rcl_node_get_rmw_handle(node), topic_name, count);
|
return rmw_count_subscribers(rcl_node_get_rmw_handle(node), topic_name, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,12 +136,16 @@ rcl_service_server_is_available(
|
||||||
const rcl_client_t * client,
|
const rcl_client_t * client,
|
||||||
bool * is_available)
|
bool * is_available)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (!rcl_node_is_valid(node)) {
|
if (!rcl_node_is_valid(node)) {
|
||||||
return RCL_RET_NODE_INVALID;
|
return RCL_RET_NODE_INVALID;
|
||||||
}
|
}
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT);
|
const rcl_node_options_t * node_options = rcl_node_get_options(node);
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(is_available, RCL_RET_INVALID_ARGUMENT);
|
if (!node_options) {
|
||||||
|
return RCL_RET_NODE_INVALID; // shouldn't happen, but error is already set if so
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, node_options->allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(is_available, RCL_RET_INVALID_ARGUMENT, node_options->allocator);
|
||||||
return rmw_service_server_is_available(
|
return rmw_service_server_is_available(
|
||||||
rcl_node_get_rmw_handle(node),
|
rcl_node_get_rmw_handle(node),
|
||||||
rcl_client_get_rmw_handle(client),
|
rcl_client_get_rmw_handle(client),
|
||||||
|
|
|
@ -21,6 +21,7 @@ extern "C"
|
||||||
|
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
#include "rcl/rcl.h"
|
#include "rcl/rcl.h"
|
||||||
|
#include "rmw/error_handling.h"
|
||||||
#include "rmw/rmw.h"
|
#include "rmw/rmw.h"
|
||||||
|
|
||||||
typedef struct rcl_guard_condition_impl_t
|
typedef struct rcl_guard_condition_impl_t
|
||||||
|
@ -45,22 +46,30 @@ __rcl_guard_condition_init_from_rmw_impl(
|
||||||
// This function will create an rmw_guard_condition if the parameter is null.
|
// This function will create an rmw_guard_condition if the parameter is null.
|
||||||
|
|
||||||
// Perform argument validation.
|
// Perform argument validation.
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(guard_condition, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
const rcl_allocator_t * allocator = &options.allocator;
|
const rcl_allocator_t * allocator = &options.allocator;
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->allocate, "allocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->allocate, "allocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->deallocate, "deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->deallocate, "deallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(guard_condition, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
// Ensure the guard_condition handle is zero initialized.
|
// Ensure the guard_condition handle is zero initialized.
|
||||||
if (guard_condition->impl) {
|
if (guard_condition->impl) {
|
||||||
RCL_SET_ERROR_MSG("guard_condition already initialized, or memory was unintialized");
|
RCL_SET_ERROR_MSG(
|
||||||
|
"guard_condition already initialized, or memory was unintialized", *allocator);
|
||||||
return RCL_RET_ALREADY_INIT;
|
return RCL_RET_ALREADY_INIT;
|
||||||
}
|
}
|
||||||
|
// Make sure rcl has been initialized.
|
||||||
|
if (!rcl_ok()) {
|
||||||
|
RCL_SET_ERROR_MSG("rcl_init() has not been called", *allocator);
|
||||||
|
return RCL_RET_NOT_INIT;
|
||||||
|
}
|
||||||
// Allocate space for the guard condition impl.
|
// Allocate space for the guard condition impl.
|
||||||
guard_condition->impl = (rcl_guard_condition_impl_t *)allocator->allocate(
|
guard_condition->impl = (rcl_guard_condition_impl_t *)allocator->allocate(
|
||||||
sizeof(rcl_guard_condition_impl_t), allocator->state);
|
sizeof(rcl_guard_condition_impl_t), allocator->state);
|
||||||
if (!guard_condition->impl) {
|
if (!guard_condition->impl) {
|
||||||
RCL_SET_ERROR_MSG("allocating memory failed");
|
RCL_SET_ERROR_MSG("allocating memory failed", *allocator);
|
||||||
return RCL_RET_BAD_ALLOC;
|
return RCL_RET_BAD_ALLOC;
|
||||||
}
|
}
|
||||||
// Create the rmw guard condition.
|
// Create the rmw guard condition.
|
||||||
|
@ -73,7 +82,7 @@ __rcl_guard_condition_init_from_rmw_impl(
|
||||||
if (!guard_condition->impl->rmw_handle) {
|
if (!guard_condition->impl->rmw_handle) {
|
||||||
// Deallocate impl and exit.
|
// Deallocate impl and exit.
|
||||||
allocator->deallocate(guard_condition->impl, allocator->state);
|
allocator->deallocate(guard_condition->impl, allocator->state);
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), *allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,22 +113,20 @@ rcl_ret_t
|
||||||
rcl_guard_condition_fini(rcl_guard_condition_t * guard_condition)
|
rcl_guard_condition_fini(rcl_guard_condition_t * guard_condition)
|
||||||
{
|
{
|
||||||
// Perform argument validation.
|
// Perform argument validation.
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(guard_condition, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(
|
||||||
|
guard_condition, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
rcl_ret_t result = RCL_RET_OK;
|
rcl_ret_t result = RCL_RET_OK;
|
||||||
if (guard_condition->impl) {
|
if (guard_condition->impl) {
|
||||||
|
// assuming the allocator is valid because it is checked in rcl_guard_condition_init()
|
||||||
|
rcl_allocator_t allocator = guard_condition->impl->options.allocator;
|
||||||
if (guard_condition->impl->rmw_handle) {
|
if (guard_condition->impl->rmw_handle) {
|
||||||
if (rmw_destroy_guard_condition(guard_condition->impl->rmw_handle) != RMW_RET_OK) {
|
if (rmw_destroy_guard_condition(guard_condition->impl->rmw_handle) != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), allocator);
|
||||||
result = RCL_RET_ERROR;
|
result = RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rcl_allocator_t allocator = guard_condition->impl->options.allocator;
|
allocator.deallocate(guard_condition->impl, allocator.state);
|
||||||
if (allocator.deallocate) {
|
guard_condition->impl = NULL;
|
||||||
allocator.deallocate(guard_condition->impl, allocator.state);
|
|
||||||
} else {
|
|
||||||
RCL_SET_ERROR_MSG("deallocate not set");
|
|
||||||
result = RCL_RET_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -136,26 +143,38 @@ rcl_guard_condition_get_default_options()
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_trigger_guard_condition(rcl_guard_condition_t * guard_condition)
|
rcl_trigger_guard_condition(rcl_guard_condition_t * guard_condition)
|
||||||
{
|
{
|
||||||
// Perform argument validation.
|
const rcl_guard_condition_options_t * options = rcl_guard_condition_get_options(guard_condition);
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(guard_condition, RCL_RET_INVALID_ARGUMENT);
|
if (!options) {
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
return RCL_RET_INVALID_ARGUMENT; // error already set
|
||||||
guard_condition->impl,
|
}
|
||||||
"guard condition implementation is invalid",
|
|
||||||
return RCL_RET_INVALID_ARGUMENT);
|
|
||||||
// Trigger the guard condition.
|
// Trigger the guard condition.
|
||||||
if (rmw_trigger_guard_condition(guard_condition->impl->rmw_handle) != RMW_RET_OK) {
|
if (rmw_trigger_guard_condition(guard_condition->impl->rmw_handle) != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rcl_guard_condition_options_t *
|
||||||
|
rcl_guard_condition_get_options(const rcl_guard_condition_t * guard_condition)
|
||||||
|
{
|
||||||
|
// Perform argument validation.
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(guard_condition, NULL, rcl_get_default_allocator());
|
||||||
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
guard_condition->impl,
|
||||||
|
"guard condition implementation is invalid",
|
||||||
|
return NULL,
|
||||||
|
rcl_get_default_allocator());
|
||||||
|
return &guard_condition->impl->options;
|
||||||
|
}
|
||||||
|
|
||||||
rmw_guard_condition_t *
|
rmw_guard_condition_t *
|
||||||
rcl_guard_condition_get_rmw_handle(const rcl_guard_condition_t * guard_condition)
|
rcl_guard_condition_get_rmw_handle(const rcl_guard_condition_t * guard_condition)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(guard_condition, NULL);
|
const rcl_guard_condition_options_t * options = rcl_guard_condition_get_options(guard_condition);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
if (!options) {
|
||||||
guard_condition->impl, "guard condition implementation is invalid", return NULL);
|
return NULL; // error already set
|
||||||
|
}
|
||||||
return guard_condition->impl->rmw_handle;
|
return guard_condition->impl->rmw_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ extern "C"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "rcl/rcl.h"
|
#include "rcl/rcl.h"
|
||||||
|
#include "rmw/error_handling.h"
|
||||||
#include "rmw/rmw.h"
|
#include "rmw/rmw.h"
|
||||||
#include "rmw/validate_namespace.h"
|
#include "rmw/validate_namespace.h"
|
||||||
#include "rmw/validate_node_name.h"
|
#include "rmw/validate_node_name.h"
|
||||||
|
@ -69,29 +70,34 @@ rcl_node_init(
|
||||||
rcl_guard_condition_get_default_options();
|
rcl_guard_condition_get_default_options();
|
||||||
rcl_ret_t ret;
|
rcl_ret_t ret;
|
||||||
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(name, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(namespace_, RCL_RET_INVALID_ARGUMENT);
|
// Check options and allocator first, so allocator can be used for errors.
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
const rcl_allocator_t * allocator = &options->allocator;
|
||||||
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
allocator->allocate, "allocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
allocator->deallocate, "deallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(name, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(namespace_, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
if (node->impl) {
|
if (node->impl) {
|
||||||
RCL_SET_ERROR_MSG("node already initialized, or struct memory was unintialized");
|
RCL_SET_ERROR_MSG("node already initialized, or struct memory was unintialized", *allocator);
|
||||||
return RCL_RET_ALREADY_INIT;
|
return RCL_RET_ALREADY_INIT;
|
||||||
}
|
}
|
||||||
// Make sure rcl has been initialized.
|
// Make sure rcl has been initialized.
|
||||||
if (!rcl_ok()) {
|
if (!rcl_ok()) {
|
||||||
RCL_SET_ERROR_MSG("rcl_init() has not been called");
|
RCL_SET_ERROR_MSG("rcl_init() has not been called", *allocator);
|
||||||
return RCL_RET_NOT_INIT;
|
return RCL_RET_NOT_INIT;
|
||||||
}
|
}
|
||||||
const rcl_allocator_t * allocator = &options->allocator;
|
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
allocator->allocate, "allocate not set", return RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
allocator->deallocate, "deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
|
||||||
// Make sure the node name is valid before allocating memory.
|
// Make sure the node name is valid before allocating memory.
|
||||||
int validation_result = 0;
|
int validation_result = 0;
|
||||||
ret = rmw_validate_node_name(name, &validation_result, NULL);
|
ret = rmw_validate_node_name(name, &validation_result, NULL);
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), *allocator);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (validation_result != RMW_NODE_NAME_VALID) {
|
if (validation_result != RMW_NODE_NAME_VALID) {
|
||||||
|
@ -99,7 +105,7 @@ rcl_node_init(
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
msg = "unknown validation_result, this should not happen";
|
msg = "unknown validation_result, this should not happen";
|
||||||
}
|
}
|
||||||
RCL_SET_ERROR_MSG(msg);
|
RCL_SET_ERROR_MSG(msg, *allocator);
|
||||||
return RCL_RET_NODE_INVALID_NAME;
|
return RCL_RET_NODE_INVALID_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +123,8 @@ rcl_node_init(
|
||||||
// TODO(wjwwood): replace with generic strcat that takes an allocator once available
|
// TODO(wjwwood): replace with generic strcat that takes an allocator once available
|
||||||
// length + 2, because new leading / and terminating \0
|
// length + 2, because new leading / and terminating \0
|
||||||
char * temp = (char *)allocator->allocate(namespace_length + 2, allocator->state);
|
char * temp = (char *)allocator->allocate(namespace_length + 2, allocator->state);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(temp, "allocating memory failed", return RCL_RET_BAD_ALLOC);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
temp, "allocating memory failed", return RCL_RET_BAD_ALLOC, *allocator);
|
||||||
temp[0] = '/';
|
temp[0] = '/';
|
||||||
memcpy(temp + 1, namespace_, strlen(namespace_) + 1);
|
memcpy(temp + 1, namespace_, strlen(namespace_) + 1);
|
||||||
local_namespace_ = temp;
|
local_namespace_ = temp;
|
||||||
|
@ -127,7 +134,7 @@ rcl_node_init(
|
||||||
validation_result = 0;
|
validation_result = 0;
|
||||||
ret = rmw_validate_namespace(local_namespace_, &validation_result, NULL);
|
ret = rmw_validate_namespace(local_namespace_, &validation_result, NULL);
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), *allocator);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (validation_result != RMW_NAMESPACE_VALID) {
|
if (validation_result != RMW_NAMESPACE_VALID) {
|
||||||
|
@ -137,16 +144,17 @@ rcl_node_init(
|
||||||
LOCAL_SNPRINTF(
|
LOCAL_SNPRINTF(
|
||||||
fixed_msg, sizeof(fixed_msg),
|
fixed_msg, sizeof(fixed_msg),
|
||||||
"unknown validation_result '%d', this should not happen", validation_result);
|
"unknown validation_result '%d', this should not happen", validation_result);
|
||||||
RCL_SET_ERROR_MSG(fixed_msg);
|
RCL_SET_ERROR_MSG(fixed_msg, *allocator);
|
||||||
} else {
|
} else {
|
||||||
RCL_SET_ERROR_MSG(msg);
|
RCL_SET_ERROR_MSG(msg, *allocator);
|
||||||
}
|
}
|
||||||
return RCL_RET_NODE_INVALID_NAMESPACE;
|
return RCL_RET_NODE_INVALID_NAMESPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate space for the implementation struct.
|
// Allocate space for the implementation struct.
|
||||||
node->impl = (rcl_node_impl_t *)allocator->allocate(sizeof(rcl_node_impl_t), allocator->state);
|
node->impl = (rcl_node_impl_t *)allocator->allocate(sizeof(rcl_node_impl_t), allocator->state);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(node->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
node->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC, *allocator);
|
||||||
node->impl->rmw_node_handle = NULL;
|
node->impl->rmw_node_handle = NULL;
|
||||||
node->impl->graph_guard_condition = NULL;
|
node->impl->graph_guard_condition = NULL;
|
||||||
// Initialize node impl.
|
// Initialize node impl.
|
||||||
|
@ -162,7 +170,7 @@ rcl_node_init(
|
||||||
if (ros_domain_id) {
|
if (ros_domain_id) {
|
||||||
unsigned long number = strtoul(ros_domain_id, NULL, 0); // NOLINT(runtime/int)
|
unsigned long number = strtoul(ros_domain_id, NULL, 0); // NOLINT(runtime/int)
|
||||||
if (number == ULONG_MAX) {
|
if (number == ULONG_MAX) {
|
||||||
RCL_SET_ERROR_MSG("failed to interpret ROS_DOMAIN_ID as integral number");
|
RCL_SET_ERROR_MSG("failed to interpret ROS_DOMAIN_ID as integral number", *allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
domain_id = (size_t)number;
|
domain_id = (size_t)number;
|
||||||
|
@ -174,7 +182,7 @@ rcl_node_init(
|
||||||
node->impl->actual_domain_id = domain_id;
|
node->impl->actual_domain_id = domain_id;
|
||||||
node->impl->rmw_node_handle = rmw_create_node(name, local_namespace_, domain_id);
|
node->impl->rmw_node_handle = rmw_create_node(name, local_namespace_, domain_id);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
node->impl->rmw_node_handle, rmw_get_error_string_safe(), goto fail);
|
node->impl->rmw_node_handle, rmw_get_error_string_safe(), goto fail, *allocator);
|
||||||
// free local_namespace_ if necessary
|
// free local_namespace_ if necessary
|
||||||
if (should_free_local_namespace_) {
|
if (should_free_local_namespace_) {
|
||||||
allocator->deallocate((char *)local_namespace_, allocator->state);
|
allocator->deallocate((char *)local_namespace_, allocator->state);
|
||||||
|
@ -184,7 +192,7 @@ rcl_node_init(
|
||||||
// graph guard condition
|
// graph guard condition
|
||||||
rmw_graph_guard_condition = rmw_node_get_graph_guard_condition(node->impl->rmw_node_handle);
|
rmw_graph_guard_condition = rmw_node_get_graph_guard_condition(node->impl->rmw_node_handle);
|
||||||
if (!rmw_graph_guard_condition) {
|
if (!rmw_graph_guard_condition) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), *allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
node->impl->graph_guard_condition = (rcl_guard_condition_t *)allocator->allocate(
|
node->impl->graph_guard_condition = (rcl_guard_condition_t *)allocator->allocate(
|
||||||
|
@ -192,7 +200,8 @@ rcl_node_init(
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
node->impl->graph_guard_condition,
|
node->impl->graph_guard_condition,
|
||||||
"allocating memory failed",
|
"allocating memory failed",
|
||||||
goto fail
|
goto fail,
|
||||||
|
*allocator
|
||||||
);
|
);
|
||||||
*node->impl->graph_guard_condition = rcl_get_zero_initialized_guard_condition();
|
*node->impl->graph_guard_condition = rcl_get_zero_initialized_guard_condition();
|
||||||
graph_guard_condition_options.allocator = *allocator;
|
graph_guard_condition_options.allocator = *allocator;
|
||||||
|
@ -233,20 +242,19 @@ fail:
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_node_fini(rcl_node_t * node)
|
rcl_node_fini(rcl_node_t * node)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (!node->impl) {
|
if (!node->impl) {
|
||||||
// Repeat calls to fini or calling fini on a zero initialized node is ok.
|
// Repeat calls to fini or calling fini on a zero initialized node is ok.
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
rcl_allocator_t allocator = node->impl->options.allocator;
|
||||||
rcl_ret_t result = RCL_RET_OK;
|
rcl_ret_t result = RCL_RET_OK;
|
||||||
rmw_ret_t ret = rmw_destroy_node(node->impl->rmw_node_handle);
|
rmw_ret_t ret = rmw_destroy_node(node->impl->rmw_node_handle);
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), allocator);
|
||||||
result = RCL_RET_ERROR;
|
result = RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
rcl_allocator_t allocator = node->impl->options.allocator;
|
// assuming that allocate and deallocate are ok since they are checked in init
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
allocator.deallocate, "deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
|
||||||
allocator.deallocate(node->impl, allocator.state);
|
allocator.deallocate(node->impl, allocator.state);
|
||||||
node->impl = NULL;
|
node->impl = NULL;
|
||||||
return result;
|
return result;
|
||||||
|
@ -255,10 +263,12 @@ rcl_node_fini(rcl_node_t * node)
|
||||||
bool
|
bool
|
||||||
rcl_node_is_valid(const rcl_node_t * node)
|
rcl_node_is_valid(const rcl_node_t * node)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, false);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, false, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(node->impl, "rcl node implementation is invalid", return false);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
node->impl, "rcl node implementation is invalid", return false, rcl_get_default_allocator());
|
||||||
if (node->impl->rcl_instance_id != rcl_get_instance_id()) {
|
if (node->impl->rcl_instance_id != rcl_get_instance_id()) {
|
||||||
RCL_SET_ERROR_MSG("rcl node is invalid, rcl instance id does not match");
|
RCL_SET_ERROR_MSG(
|
||||||
|
"rcl node is invalid, rcl instance id does not match", rcl_get_default_allocator());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -306,11 +316,12 @@ rcl_node_get_options(const rcl_node_t * node)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_node_get_domain_id(const rcl_node_t * node, size_t * domain_id)
|
rcl_node_get_domain_id(const rcl_node_t * node, size_t * domain_id)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(domain_id, RCL_RET_INVALID_ARGUMENT);
|
const rcl_node_options_t * node_options = rcl_node_get_options(node);
|
||||||
if (!rcl_node_is_valid(node)) {
|
if (!node_options) {
|
||||||
return RCL_RET_NODE_INVALID;
|
return RCL_RET_NODE_INVALID;
|
||||||
}
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(domain_id, RCL_RET_INVALID_ARGUMENT, node_options->allocator);
|
||||||
*domain_id = node->impl->actual_domain_id;
|
*domain_id = node->impl->actual_domain_id;
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
@ -327,8 +338,9 @@ rcl_node_get_rmw_handle(const rcl_node_t * node)
|
||||||
uint64_t
|
uint64_t
|
||||||
rcl_node_get_rcl_instance_id(const rcl_node_t * node)
|
rcl_node_get_rcl_instance_id(const rcl_node_t * node)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, 0);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, 0, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(node->impl, "node implementation is invalid", return 0);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
node->impl, "node implementation is invalid", return 0, rcl_get_default_allocator());
|
||||||
return node->impl->rcl_instance_id;
|
return node->impl->rcl_instance_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ extern "C"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
|
#include "rmw/error_handling.h"
|
||||||
#include "rmw/rmw.h"
|
#include "rmw/rmw.h"
|
||||||
|
|
||||||
typedef struct rcl_publisher_impl_t
|
typedef struct rcl_publisher_impl_t
|
||||||
|
@ -46,29 +47,35 @@ rcl_publisher_init(
|
||||||
const rcl_publisher_options_t * options)
|
const rcl_publisher_options_t * options)
|
||||||
{
|
{
|
||||||
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
// Check options and allocator first, so allocator can be used with errors.
|
||||||
if (!node->impl) {
|
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_SET_ERROR_MSG("invalid node");
|
|
||||||
return RCL_RET_NODE_INVALID;
|
|
||||||
}
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
if (publisher->impl) {
|
|
||||||
RCL_SET_ERROR_MSG("publisher already initialized, or memory was unintialized");
|
|
||||||
return RCL_RET_ALREADY_INIT;
|
|
||||||
}
|
|
||||||
const rcl_allocator_t * allocator = &options->allocator;
|
const rcl_allocator_t * allocator = &options->allocator;
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->allocate, "allocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->allocate, "allocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->deallocate, "deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->deallocate, "deallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
if (publisher->impl) {
|
||||||
|
RCL_SET_ERROR_MSG(
|
||||||
|
"publisher already initialized, or memory was unintialized", rcl_get_default_allocator());
|
||||||
|
return RCL_RET_ALREADY_INIT;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
if (!node->impl) {
|
||||||
|
RCL_SET_ERROR_MSG("invalid node", *allocator);
|
||||||
|
return RCL_RET_NODE_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
// Allocate space for the implementation struct.
|
// Allocate space for the implementation struct.
|
||||||
publisher->impl = (rcl_publisher_impl_t *)allocator->allocate(
|
publisher->impl = (rcl_publisher_impl_t *)allocator->allocate(
|
||||||
sizeof(rcl_publisher_impl_t), allocator->state);
|
sizeof(rcl_publisher_impl_t), allocator->state);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
publisher->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
|
publisher->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC, *allocator);
|
||||||
// Fill out implementation struct.
|
// Fill out implementation struct.
|
||||||
// rmw handle (create rmw publisher)
|
// rmw handle (create rmw publisher)
|
||||||
// TODO(wjwwood): pass along the allocator to rmw when it supports it
|
// TODO(wjwwood): pass along the allocator to rmw when it supports it
|
||||||
|
@ -78,7 +85,7 @@ rcl_publisher_init(
|
||||||
topic_name,
|
topic_name,
|
||||||
&(options->qos));
|
&(options->qos));
|
||||||
if (!publisher->impl->rmw_handle) {
|
if (!publisher->impl->rmw_handle) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), *allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
// options
|
// options
|
||||||
|
@ -95,16 +102,16 @@ rcl_ret_t
|
||||||
rcl_publisher_fini(rcl_publisher_t * publisher, rcl_node_t * node)
|
rcl_publisher_fini(rcl_publisher_t * publisher, rcl_node_t * node)
|
||||||
{
|
{
|
||||||
rcl_ret_t result = RCL_RET_OK;
|
rcl_ret_t result = RCL_RET_OK;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (publisher->impl) {
|
if (publisher->impl) {
|
||||||
|
rcl_allocator_t allocator = publisher->impl->options.allocator;
|
||||||
rmw_ret_t ret =
|
rmw_ret_t ret =
|
||||||
rmw_destroy_publisher(rcl_node_get_rmw_handle(node), publisher->impl->rmw_handle);
|
rmw_destroy_publisher(rcl_node_get_rmw_handle(node), publisher->impl->rmw_handle);
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), allocator);
|
||||||
result = RCL_RET_ERROR;
|
result = RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
rcl_allocator_t allocator = publisher->impl->options.allocator;
|
|
||||||
allocator.deallocate(publisher->impl, allocator.state);
|
allocator.deallocate(publisher->impl, allocator.state);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -124,12 +131,16 @@ 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_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(ros_message, RCL_RET_INVALID_ARGUMENT);
|
const rcl_publisher_options_t * options = rcl_publisher_get_options(publisher);
|
||||||
|
if (!options) {
|
||||||
|
return RCL_RET_PUBLISHER_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(ros_message, RCL_RET_INVALID_ARGUMENT, options->allocator);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
publisher->impl, "publisher is invalid", return RCL_RET_PUBLISHER_INVALID);
|
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());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
|
@ -138,29 +149,32 @@ 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)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(publisher, NULL);
|
const rcl_publisher_options_t * options = rcl_publisher_get_options(publisher);
|
||||||
|
if (!options) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
publisher->impl, "publisher is invalid", return NULL);
|
publisher->impl, "publisher is invalid", return NULL, options->allocator);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
publisher->impl->rmw_handle, "publisher is invalid", return NULL);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_CHECK_ARGUMENT_FOR_NULL(publisher, NULL, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
publisher->impl, "publisher is invalid", return NULL);
|
publisher->impl, "publisher is invalid", return NULL, rcl_get_default_allocator());
|
||||||
return &publisher->impl->options;
|
return &publisher->impl->options;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_CHECK_ARGUMENT_FOR_NULL(publisher, NULL, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
publisher->impl, "publisher is invalid", return NULL);
|
publisher->impl, "publisher is invalid", return NULL, rcl_get_default_allocator());
|
||||||
return publisher->impl->rmw_handle;
|
return publisher->impl->rmw_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ extern "C"
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
#include "./stdatomic_helper.h"
|
#include "./stdatomic_helper.h"
|
||||||
#include "rcl/error_handling.h"
|
#include "rcl/error_handling.h"
|
||||||
|
#include "rmw/error_handling.h"
|
||||||
|
|
||||||
static atomic_bool __rcl_is_initialized = ATOMIC_VAR_INIT(false);
|
static atomic_bool __rcl_is_initialized = ATOMIC_VAR_INIT(false);
|
||||||
static rcl_allocator_t __rcl_allocator;
|
static rcl_allocator_t __rcl_allocator;
|
||||||
|
@ -56,17 +57,22 @@ rcl_ret_t
|
||||||
rcl_init(int argc, char ** argv, rcl_allocator_t allocator)
|
rcl_init(int argc, char ** argv, rcl_allocator_t allocator)
|
||||||
{
|
{
|
||||||
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
||||||
if (argc > 0) {
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(argv, RCL_RET_INVALID_ARGUMENT);
|
// Check allocator first, so it can be used in other errors.
|
||||||
}
|
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator.allocate,
|
allocator.allocate,
|
||||||
"invalid allocator, allocate not set", return RCL_RET_INVALID_ARGUMENT);
|
"invalid allocator, allocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator.deallocate,
|
allocator.deallocate,
|
||||||
"invalid allocator, deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
"invalid allocator, deallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(argv, RCL_RET_INVALID_ARGUMENT, allocator);
|
||||||
|
}
|
||||||
if (rcl_atomic_exchange_bool(&__rcl_is_initialized, true)) {
|
if (rcl_atomic_exchange_bool(&__rcl_is_initialized, true)) {
|
||||||
RCL_SET_ERROR_MSG("rcl_init called while already initialized");
|
RCL_SET_ERROR_MSG("rcl_init called while already initialized", allocator);
|
||||||
return RCL_RET_ALREADY_INIT;
|
return RCL_RET_ALREADY_INIT;
|
||||||
}
|
}
|
||||||
// There is a race condition between the time __rcl_is_initialized is set true,
|
// There is a race condition between the time __rcl_is_initialized is set true,
|
||||||
|
@ -78,7 +84,7 @@ rcl_init(int argc, char ** argv, rcl_allocator_t allocator)
|
||||||
// Initialize rmw_init.
|
// Initialize rmw_init.
|
||||||
rmw_ret_t rmw_ret = rmw_init();
|
rmw_ret_t rmw_ret = rmw_init();
|
||||||
if (rmw_ret != RMW_RET_OK) {
|
if (rmw_ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), allocator);
|
||||||
fail_ret = RCL_RET_ERROR;
|
fail_ret = RCL_RET_ERROR;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +93,7 @@ rcl_init(int argc, char ** argv, rcl_allocator_t allocator)
|
||||||
__rcl_argc = argc;
|
__rcl_argc = argc;
|
||||||
__rcl_argv = (char **)__rcl_allocator.allocate(sizeof(char *) * argc, __rcl_allocator.state);
|
__rcl_argv = (char **)__rcl_allocator.allocate(sizeof(char *) * argc, __rcl_allocator.state);
|
||||||
if (!__rcl_argv) {
|
if (!__rcl_argv) {
|
||||||
RCL_SET_ERROR_MSG("allocation failed");
|
RCL_SET_ERROR_MSG("allocation failed", allocator);
|
||||||
fail_ret = RCL_RET_BAD_ALLOC;
|
fail_ret = RCL_RET_BAD_ALLOC;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +102,7 @@ rcl_init(int argc, char ** argv, rcl_allocator_t allocator)
|
||||||
for (i = 0; i < argc; ++i) {
|
for (i = 0; i < argc; ++i) {
|
||||||
__rcl_argv[i] = (char *)__rcl_allocator.allocate(strlen(argv[i]), __rcl_allocator.state);
|
__rcl_argv[i] = (char *)__rcl_allocator.allocate(strlen(argv[i]), __rcl_allocator.state);
|
||||||
if (!__rcl_argv[i]) {
|
if (!__rcl_argv[i]) {
|
||||||
RCL_SET_ERROR_MSG("allocation failed");
|
RCL_SET_ERROR_MSG("allocation failed", allocator);
|
||||||
fail_ret = RCL_RET_BAD_ALLOC;
|
fail_ret = RCL_RET_BAD_ALLOC;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +112,7 @@ rcl_init(int argc, char ** argv, rcl_allocator_t allocator)
|
||||||
if (rcl_atomic_load_uint64_t(&__rcl_instance_id) == 0) {
|
if (rcl_atomic_load_uint64_t(&__rcl_instance_id) == 0) {
|
||||||
// Roll over occurred.
|
// Roll over occurred.
|
||||||
__rcl_next_unique_id--; // roll back to avoid the next call succeeding.
|
__rcl_next_unique_id--; // roll back to avoid the next call succeeding.
|
||||||
RCL_SET_ERROR_MSG("unique rcl instance ids exhausted");
|
RCL_SET_ERROR_MSG("unique rcl instance ids exhausted", allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
|
@ -119,7 +125,8 @@ rcl_ret_t
|
||||||
rcl_shutdown()
|
rcl_shutdown()
|
||||||
{
|
{
|
||||||
if (!rcl_ok()) {
|
if (!rcl_ok()) {
|
||||||
RCL_SET_ERROR_MSG("rcl_shutdown called before rcl_init");
|
// must use default allocator here because __rcl_allocator may not be set yet
|
||||||
|
RCL_SET_ERROR_MSG("rcl_shutdown called before rcl_init", rcl_get_default_allocator());
|
||||||
return RCL_RET_NOT_INIT;
|
return RCL_RET_NOT_INIT;
|
||||||
}
|
}
|
||||||
__clean_up_init();
|
__clean_up_init();
|
||||||
|
|
|
@ -23,6 +23,7 @@ extern "C"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
|
#include "rmw/error_handling.h"
|
||||||
#include "rmw/rmw.h"
|
#include "rmw/rmw.h"
|
||||||
|
|
||||||
typedef struct rcl_service_impl_t
|
typedef struct rcl_service_impl_t
|
||||||
|
@ -47,29 +48,34 @@ rcl_service_init(
|
||||||
const rcl_service_options_t * options)
|
const rcl_service_options_t * options)
|
||||||
{
|
{
|
||||||
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
// Check options and allocator first, so the allocator can be used in errors.
|
||||||
if (!node->impl) {
|
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_SET_ERROR_MSG("invalid node");
|
|
||||||
return RCL_RET_NODE_INVALID;
|
|
||||||
}
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(service_name, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
if (service->impl) {
|
|
||||||
RCL_SET_ERROR_MSG("service already initialized, or memory was unintialized");
|
|
||||||
return RCL_RET_ALREADY_INIT;
|
|
||||||
}
|
|
||||||
const rcl_allocator_t * allocator = &options->allocator;
|
const rcl_allocator_t * allocator = &options->allocator;
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->allocate, "allocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->allocate, "allocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->deallocate, "deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->deallocate, "deallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
if (!node->impl) {
|
||||||
|
RCL_SET_ERROR_MSG("invalid node", *allocator);
|
||||||
|
return RCL_RET_NODE_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(service_name, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
if (service->impl) {
|
||||||
|
RCL_SET_ERROR_MSG("service already initialized, or memory was unintialized", *allocator);
|
||||||
|
return RCL_RET_ALREADY_INIT;
|
||||||
|
}
|
||||||
// Allocate space for the implementation struct.
|
// Allocate space for the implementation struct.
|
||||||
service->impl = (rcl_service_impl_t *)allocator->allocate(
|
service->impl = (rcl_service_impl_t *)allocator->allocate(
|
||||||
sizeof(rcl_service_impl_t), allocator->state);
|
sizeof(rcl_service_impl_t), allocator->state);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
service->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
|
service->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC, *allocator);
|
||||||
|
|
||||||
if (RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL == options->qos.durability) {
|
if (RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL == options->qos.durability) {
|
||||||
fprintf(stderr, "Warning: Setting QoS durability to 'transient local' for service servers "
|
fprintf(stderr, "Warning: Setting QoS durability to 'transient local' for service servers "
|
||||||
|
@ -84,7 +90,7 @@ rcl_service_init(
|
||||||
service_name,
|
service_name,
|
||||||
&options->qos);
|
&options->qos);
|
||||||
if (!service->impl->rmw_handle) {
|
if (!service->impl->rmw_handle) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), *allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
// options
|
// options
|
||||||
|
@ -101,16 +107,16 @@ rcl_ret_t
|
||||||
rcl_service_fini(rcl_service_t * service, rcl_node_t * node)
|
rcl_service_fini(rcl_service_t * service, rcl_node_t * node)
|
||||||
{
|
{
|
||||||
rcl_ret_t result = RCL_RET_OK;
|
rcl_ret_t result = RCL_RET_OK;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (service->impl) {
|
if (service->impl) {
|
||||||
|
rcl_allocator_t allocator = service->impl->options.allocator;
|
||||||
rmw_ret_t ret =
|
rmw_ret_t ret =
|
||||||
rmw_destroy_service(rcl_node_get_rmw_handle(node), service->impl->rmw_handle);
|
rmw_destroy_service(rcl_node_get_rmw_handle(node), service->impl->rmw_handle);
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), allocator);
|
||||||
result = RCL_RET_ERROR;
|
result = RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
rcl_allocator_t allocator = service->impl->options.allocator;
|
|
||||||
allocator.deallocate(service->impl, allocator.state);
|
allocator.deallocate(service->impl, allocator.state);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -130,29 +136,30 @@ rcl_service_get_default_options()
|
||||||
const char *
|
const char *
|
||||||
rcl_service_get_service_name(const rcl_service_t * service)
|
rcl_service_get_service_name(const rcl_service_t * service)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(service, NULL);
|
const rcl_service_options_t * options = rcl_service_get_options(service);
|
||||||
|
if (!options) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
service->impl, "service is invalid", return NULL);
|
service->impl->rmw_handle, "service is invalid", return NULL, options->allocator);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
service->impl->rmw_handle, "service is invalid", return NULL);
|
|
||||||
return service->impl->rmw_handle->service_name;
|
return service->impl->rmw_handle->service_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_CHECK_ARGUMENT_FOR_NULL(service, NULL, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
service->impl, "service is invalid", return NULL);
|
service->impl, "service is invalid", return NULL, rcl_get_default_allocator());
|
||||||
return &service->impl->options;
|
return &service->impl->options;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_CHECK_ARGUMENT_FOR_NULL(service, NULL, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
service->impl, "service is invalid", return NULL);
|
service->impl, "service is invalid", return NULL, rcl_get_default_allocator());
|
||||||
return service->impl->rmw_handle;
|
return service->impl->rmw_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,17 +169,19 @@ 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_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
const rcl_service_options_t * options = rcl_service_get_options(service);
|
||||||
service->impl, "service is invalid", return RCL_RET_INVALID_ARGUMENT);
|
if (!options) {
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(request_header, RCL_RET_INVALID_ARGUMENT);
|
return RCL_RET_SERVICE_INVALID;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(ros_request, RCL_RET_INVALID_ARGUMENT);
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
bool taken = false;
|
bool taken = false;
|
||||||
if (rmw_take_request(
|
if (rmw_take_request(
|
||||||
service->impl->rmw_handle, request_header, ros_request, &taken) != RMW_RET_OK)
|
service->impl->rmw_handle, request_header, ros_request, &taken) != RMW_RET_OK)
|
||||||
{
|
{
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
if (!taken) {
|
if (!taken) {
|
||||||
|
@ -187,16 +196,18 @@ 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_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
const rcl_service_options_t * options = rcl_service_get_options(service);
|
||||||
service->impl, "service is invalid", return RCL_RET_INVALID_ARGUMENT);
|
if (!options) {
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(request_header, RCL_RET_INVALID_ARGUMENT);
|
return RCL_RET_SERVICE_INVALID;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(ros_response, RCL_RET_INVALID_ARGUMENT);
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
if (rmw_send_response(
|
if (rmw_send_response(
|
||||||
service->impl->rmw_handle, request_header, ros_response) != RMW_RET_OK)
|
service->impl->rmw_handle, request_header, ros_response) != RMW_RET_OK)
|
||||||
{
|
{
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ extern "C"
|
||||||
|
|
||||||
#include "rcl/subscription.h"
|
#include "rcl/subscription.h"
|
||||||
|
|
||||||
|
#include "rmw/error_handling.h"
|
||||||
#include "rmw/rmw.h"
|
#include "rmw/rmw.h"
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
|
|
||||||
|
@ -44,25 +45,30 @@ rcl_subscription_init(
|
||||||
const rcl_subscription_options_t * options)
|
const rcl_subscription_options_t * options)
|
||||||
{
|
{
|
||||||
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(subscription, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
// Check options and allocator first, so the allocator can be used in errors.
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
if (subscription->impl) {
|
|
||||||
RCL_SET_ERROR_MSG("subscription already initialized, or memory was uninitialized");
|
|
||||||
return RCL_RET_ALREADY_INIT;
|
|
||||||
}
|
|
||||||
const rcl_allocator_t * allocator = &options->allocator;
|
const rcl_allocator_t * allocator = &options->allocator;
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->allocate, "allocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->allocate, "allocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
allocator->deallocate, "deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
allocator->deallocate, "deallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(subscription, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
|
if (subscription->impl) {
|
||||||
|
RCL_SET_ERROR_MSG("subscription already initialized, or memory was uninitialized", *allocator);
|
||||||
|
return RCL_RET_ALREADY_INIT;
|
||||||
|
}
|
||||||
// Allocate memory for the implementation struct.
|
// Allocate memory for the implementation struct.
|
||||||
subscription->impl = (rcl_subscription_impl_t *)allocator->allocate(
|
subscription->impl = (rcl_subscription_impl_t *)allocator->allocate(
|
||||||
sizeof(rcl_subscription_impl_t), allocator->state);
|
sizeof(rcl_subscription_impl_t), allocator->state);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
subscription->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
|
subscription->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC, *allocator);
|
||||||
// Fill out the implemenation struct.
|
// Fill out the implemenation struct.
|
||||||
// rmw_handle
|
// rmw_handle
|
||||||
// TODO(wjwwood): pass allocator once supported in rmw api.
|
// TODO(wjwwood): pass allocator once supported in rmw api.
|
||||||
|
@ -73,7 +79,7 @@ rcl_subscription_init(
|
||||||
&(options->qos),
|
&(options->qos),
|
||||||
options->ignore_local_publications);
|
options->ignore_local_publications);
|
||||||
if (!subscription->impl->rmw_handle) {
|
if (!subscription->impl->rmw_handle) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), *allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
// options
|
// options
|
||||||
|
@ -90,16 +96,16 @@ rcl_ret_t
|
||||||
rcl_subscription_fini(rcl_subscription_t * subscription, rcl_node_t * node)
|
rcl_subscription_fini(rcl_subscription_t * subscription, rcl_node_t * node)
|
||||||
{
|
{
|
||||||
rcl_ret_t result = RCL_RET_OK;
|
rcl_ret_t result = RCL_RET_OK;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(subscription, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(subscription, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (subscription->impl) {
|
if (subscription->impl) {
|
||||||
|
rcl_allocator_t allocator = subscription->impl->options.allocator;
|
||||||
rmw_ret_t ret =
|
rmw_ret_t ret =
|
||||||
rmw_destroy_subscription(rcl_node_get_rmw_handle(node), subscription->impl->rmw_handle);
|
rmw_destroy_subscription(rcl_node_get_rmw_handle(node), subscription->impl->rmw_handle);
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), allocator);
|
||||||
result = RCL_RET_ERROR;
|
result = RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
rcl_allocator_t allocator = subscription->impl->options.allocator;
|
|
||||||
allocator.deallocate(subscription->impl, allocator.state);
|
allocator.deallocate(subscription->impl, allocator.state);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -124,13 +130,18 @@ rcl_take(
|
||||||
void * ros_message,
|
void * ros_message,
|
||||||
rmw_message_info_t * message_info)
|
rmw_message_info_t * message_info)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(subscription, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(subscription, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(ros_message, RCL_RET_INVALID_ARGUMENT);
|
const rcl_subscription_options_t * options = rcl_subscription_get_options(subscription);
|
||||||
|
if (!options) {
|
||||||
|
return RCL_RET_SUBSCRIPTION_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(ros_message, RCL_RET_INVALID_ARGUMENT, options->allocator);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
subscription->impl, "subscription is invalid", return RCL_RET_SUBSCRIPTION_INVALID);
|
subscription->impl, "subscription is invalid",
|
||||||
|
return RCL_RET_SUBSCRIPTION_INVALID, options->allocator);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
subscription->impl->rmw_handle,
|
subscription->impl->rmw_handle,
|
||||||
"subscription is invalid", return RCL_RET_SUBSCRIPTION_INVALID);
|
"subscription is invalid", return RCL_RET_SUBSCRIPTION_INVALID, options->allocator);
|
||||||
// If message_info is NULL, use a place holder which can be discarded.
|
// If message_info is NULL, use a place holder which can be discarded.
|
||||||
rmw_message_info_t dummy_message_info;
|
rmw_message_info_t dummy_message_info;
|
||||||
rmw_message_info_t * message_info_local = message_info ? message_info : &dummy_message_info;
|
rmw_message_info_t * message_info_local = message_info ? message_info : &dummy_message_info;
|
||||||
|
@ -139,7 +150,7 @@ rcl_take(
|
||||||
rmw_ret_t ret =
|
rmw_ret_t ret =
|
||||||
rmw_take_with_info(subscription->impl->rmw_handle, ros_message, &taken, message_info_local);
|
rmw_take_with_info(subscription->impl->rmw_handle, ros_message, &taken, message_info_local);
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
if (!taken) {
|
if (!taken) {
|
||||||
|
@ -151,30 +162,31 @@ 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)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(subscription, NULL);
|
const rcl_subscription_options_t * options = rcl_subscription_get_options(subscription);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
if (!options) {
|
||||||
subscription->impl, "subscription is invalid", return NULL);
|
return NULL;
|
||||||
|
}
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
subscription->impl->rmw_handle,
|
subscription->impl->rmw_handle,
|
||||||
"subscription is invalid", return NULL);
|
"subscription is invalid", return NULL, options->allocator);
|
||||||
return subscription->impl->rmw_handle->topic_name;
|
return subscription->impl->rmw_handle->topic_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_CHECK_ARGUMENT_FOR_NULL(subscription, NULL, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
subscription->impl, "subscription is invalid", return NULL);
|
subscription->impl, "subscription is invalid", return NULL, rcl_get_default_allocator());
|
||||||
return &subscription->impl->options;
|
return &subscription->impl->options;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_CHECK_ARGUMENT_FOR_NULL(subscription, NULL, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
subscription->impl, "subscription is invalid", return NULL);
|
subscription->impl, "subscription is invalid", return NULL, rcl_get_default_allocator());
|
||||||
return subscription->impl->rmw_handle;
|
return subscription->impl->rmw_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
#include "./stdatomic_helper.h"
|
#include "./stdatomic_helper.h"
|
||||||
|
#include "rcl/allocator.h"
|
||||||
#include "rcl/error_handling.h"
|
#include "rcl/error_handling.h"
|
||||||
|
|
||||||
// Process default ROS time sources
|
// Process default ROS time sources
|
||||||
|
@ -91,9 +92,10 @@ rcl_init_time_source(
|
||||||
enum rcl_time_source_type_t time_source_type, rcl_time_source_t * time_source
|
enum rcl_time_source_type_t time_source_type, rcl_time_source_t * time_source
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
switch (time_source_type) {
|
switch (time_source_type) {
|
||||||
case RCL_TIME_SOURCE_UNINITIALIZED:
|
case RCL_TIME_SOURCE_UNINITIALIZED:
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(
|
||||||
|
time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
rcl_init_generic_time_source(time_source);
|
rcl_init_generic_time_source(time_source);
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
case RCL_ROS_TIME:
|
case RCL_ROS_TIME:
|
||||||
|
@ -110,7 +112,6 @@ rcl_init_time_source(
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_fini_time_source(rcl_time_source_t * time_source)
|
rcl_fini_time_source(rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
switch (time_source->type) {
|
switch (time_source->type) {
|
||||||
case RCL_ROS_TIME:
|
case RCL_ROS_TIME:
|
||||||
return rcl_fini_ros_time_source(time_source);
|
return rcl_fini_ros_time_source(time_source);
|
||||||
|
@ -128,7 +129,7 @@ rcl_fini_time_source(rcl_time_source_t * time_source)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_init_ros_time_source(rcl_time_source_t * time_source)
|
rcl_init_ros_time_source(rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
rcl_init_generic_time_source(time_source);
|
rcl_init_generic_time_source(time_source);
|
||||||
time_source->data = calloc(1, sizeof(rcl_ros_time_source_storage_t));
|
time_source->data = calloc(1, sizeof(rcl_ros_time_source_storage_t));
|
||||||
time_source->get_now = rcl_get_ros_time;
|
time_source->get_now = rcl_get_ros_time;
|
||||||
|
@ -139,9 +140,9 @@ rcl_init_ros_time_source(rcl_time_source_t * time_source)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_fini_ros_time_source(rcl_time_source_t * time_source)
|
rcl_fini_ros_time_source(rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (time_source->type != RCL_ROS_TIME) {
|
if (time_source->type != RCL_ROS_TIME) {
|
||||||
RCL_SET_ERROR_MSG("time_source not of type RCL_ROS_TIME");
|
RCL_SET_ERROR_MSG("time_source not of type RCL_ROS_TIME", rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
free((rcl_ros_time_source_storage_t *)time_source->data);
|
free((rcl_ros_time_source_storage_t *)time_source->data);
|
||||||
|
@ -151,7 +152,7 @@ rcl_fini_ros_time_source(rcl_time_source_t * time_source)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_init_steady_time_source(rcl_time_source_t * time_source)
|
rcl_init_steady_time_source(rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
rcl_init_generic_time_source(time_source);
|
rcl_init_generic_time_source(time_source);
|
||||||
time_source->get_now = rcl_get_steady_time;
|
time_source->get_now = rcl_get_steady_time;
|
||||||
time_source->type = RCL_STEADY_TIME;
|
time_source->type = RCL_STEADY_TIME;
|
||||||
|
@ -161,9 +162,9 @@ rcl_init_steady_time_source(rcl_time_source_t * time_source)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_fini_steady_time_source(rcl_time_source_t * time_source)
|
rcl_fini_steady_time_source(rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (time_source->type != RCL_STEADY_TIME) {
|
if (time_source->type != RCL_STEADY_TIME) {
|
||||||
RCL_SET_ERROR_MSG("time_source not of type RCL_STEADY_TIME");
|
RCL_SET_ERROR_MSG("time_source not of type RCL_STEADY_TIME", rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
|
@ -172,7 +173,7 @@ rcl_fini_steady_time_source(rcl_time_source_t * time_source)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_init_system_time_source(rcl_time_source_t * time_source)
|
rcl_init_system_time_source(rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
rcl_init_generic_time_source(time_source);
|
rcl_init_generic_time_source(time_source);
|
||||||
time_source->get_now = rcl_get_system_time;
|
time_source->get_now = rcl_get_system_time;
|
||||||
time_source->type = RCL_SYSTEM_TIME;
|
time_source->type = RCL_SYSTEM_TIME;
|
||||||
|
@ -182,9 +183,9 @@ rcl_init_system_time_source(rcl_time_source_t * time_source)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_fini_system_time_source(rcl_time_source_t * time_source)
|
rcl_fini_system_time_source(rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (time_source->type != RCL_SYSTEM_TIME) {
|
if (time_source->type != RCL_SYSTEM_TIME) {
|
||||||
RCL_SET_ERROR_MSG("time_source not of type RCL_SYSTEM_TIME");
|
RCL_SET_ERROR_MSG("time_source not of type RCL_SYSTEM_TIME", rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
|
@ -193,7 +194,7 @@ rcl_fini_system_time_source(rcl_time_source_t * time_source)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_init_time_point(rcl_time_point_t * time_point, rcl_time_source_t * time_source)
|
rcl_init_time_point(rcl_time_point_t * time_point, rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_point, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_point, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (!time_source) {
|
if (!time_source) {
|
||||||
time_point->time_source = rcl_get_default_ros_time_source();
|
time_point->time_source = rcl_get_default_ros_time_source();
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
|
@ -206,7 +207,7 @@ rcl_init_time_point(rcl_time_point_t * time_point, rcl_time_source_t * time_sour
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_fini_time_point(rcl_time_point_t * time_point)
|
rcl_fini_time_point(rcl_time_point_t * time_point)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_point, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_point, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
(void)time_point;
|
(void)time_point;
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +215,7 @@ rcl_fini_time_point(rcl_time_point_t * time_point)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_init_duration(rcl_duration_t * duration, rcl_time_source_t * time_source)
|
rcl_init_duration(rcl_duration_t * duration, rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(duration, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(duration, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (!time_source) {
|
if (!time_source) {
|
||||||
duration->time_source = rcl_get_default_ros_time_source();
|
duration->time_source = rcl_get_default_ros_time_source();
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
|
@ -227,7 +228,7 @@ rcl_init_duration(rcl_duration_t * duration, rcl_time_source_t * time_source)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_fini_duration(rcl_duration_t * duration)
|
rcl_fini_duration(rcl_duration_t * duration)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(duration, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(duration, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
(void)duration;
|
(void)duration;
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +275,8 @@ rcl_get_default_system_time_source(void)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_set_default_ros_time_source(rcl_time_source_t * process_time_source)
|
rcl_set_default_ros_time_source(rcl_time_source_t * process_time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(process_time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(
|
||||||
|
process_time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (rcl_default_ros_time_source) {
|
if (rcl_default_ros_time_source) {
|
||||||
free(rcl_default_ros_time_source);
|
free(rcl_default_ros_time_source);
|
||||||
}
|
}
|
||||||
|
@ -287,7 +289,9 @@ rcl_difference_times(rcl_time_point_t * start, rcl_time_point_t * finish,
|
||||||
rcl_duration_t * delta)
|
rcl_duration_t * delta)
|
||||||
{
|
{
|
||||||
if (start->time_source->type != finish->time_source->type) {
|
if (start->time_source->type != finish->time_source->type) {
|
||||||
RCL_SET_ERROR_MSG("Cannot difference between time points with time_sources types.");
|
RCL_SET_ERROR_MSG(
|
||||||
|
"Cannot difference between time points with time_sources types.",
|
||||||
|
rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
if (finish->nanoseconds < start->nanoseconds) {
|
if (finish->nanoseconds < start->nanoseconds) {
|
||||||
|
@ -301,27 +305,30 @@ rcl_difference_times(rcl_time_point_t * start, rcl_time_point_t * finish,
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_get_time_point_now(rcl_time_point_t * time_point)
|
rcl_get_time_point_now(rcl_time_point_t * time_point)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_point, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_point, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (time_point->time_source && time_point->time_source->get_now) {
|
if (time_point->time_source && time_point->time_source->get_now) {
|
||||||
return time_point->time_source->get_now(time_point->time_source->data,
|
return time_point->time_source->get_now(time_point->time_source->data,
|
||||||
&(time_point->nanoseconds));
|
&(time_point->nanoseconds));
|
||||||
}
|
}
|
||||||
RCL_SET_ERROR_MSG("time_source is not initialized or does not have get_now registered.");
|
RCL_SET_ERROR_MSG(
|
||||||
|
"time_source is not initialized or does not have get_now registered.",
|
||||||
|
rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_enable_ros_time_override(rcl_time_source_t * time_source)
|
rcl_enable_ros_time_override(rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (time_source->type != RCL_ROS_TIME) {
|
if (time_source->type != RCL_ROS_TIME) {
|
||||||
RCL_SET_ERROR_MSG("Time source is not RCL_ROS_TIME cannot enable override.")
|
RCL_SET_ERROR_MSG(
|
||||||
|
"Time source is not RCL_ROS_TIME cannot enable override.", rcl_get_default_allocator())
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
rcl_ros_time_source_storage_t * storage = \
|
rcl_ros_time_source_storage_t * storage = \
|
||||||
(rcl_ros_time_source_storage_t *)time_source->data;
|
(rcl_ros_time_source_storage_t *)time_source->data;
|
||||||
if (!storage) {
|
if (!storage) {
|
||||||
RCL_SET_ERROR_MSG("Storage not initialized, cannot enable.")
|
RCL_SET_ERROR_MSG("Storage not initialized, cannot enable.", rcl_get_default_allocator())
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
storage->active = true;
|
storage->active = true;
|
||||||
|
@ -331,14 +338,14 @@ rcl_enable_ros_time_override(rcl_time_source_t * time_source)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_disable_ros_time_override(rcl_time_source_t * time_source)
|
rcl_disable_ros_time_override(rcl_time_source_t * time_source)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (time_source->type != RCL_ROS_TIME) {
|
if (time_source->type != RCL_ROS_TIME) {
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
rcl_ros_time_source_storage_t * storage = \
|
rcl_ros_time_source_storage_t * storage = \
|
||||||
(rcl_ros_time_source_storage_t *)time_source->data;
|
(rcl_ros_time_source_storage_t *)time_source->data;
|
||||||
if (!storage) {
|
if (!storage) {
|
||||||
RCL_SET_ERROR_MSG("Storage not initialized, cannot disable.")
|
RCL_SET_ERROR_MSG("Storage not initialized, cannot disable.", rcl_get_default_allocator())
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
storage->active = false;
|
storage->active = false;
|
||||||
|
@ -350,15 +357,15 @@ rcl_is_enabled_ros_time_override(
|
||||||
rcl_time_source_t * time_source,
|
rcl_time_source_t * time_source,
|
||||||
bool * is_enabled)
|
bool * is_enabled)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(is_enabled, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(is_enabled, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (time_source->type != RCL_ROS_TIME) {
|
if (time_source->type != RCL_ROS_TIME) {
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
rcl_ros_time_source_storage_t * storage = \
|
rcl_ros_time_source_storage_t * storage = \
|
||||||
(rcl_ros_time_source_storage_t *)time_source->data;
|
(rcl_ros_time_source_storage_t *)time_source->data;
|
||||||
if (!storage) {
|
if (!storage) {
|
||||||
RCL_SET_ERROR_MSG("Storage not initialized, cannot query.")
|
RCL_SET_ERROR_MSG("Storage not initialized, cannot query.", rcl_get_default_allocator())
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
*is_enabled = storage->active;
|
*is_enabled = storage->active;
|
||||||
|
@ -370,7 +377,7 @@ rcl_set_ros_time_override(
|
||||||
rcl_time_source_t * time_source,
|
rcl_time_source_t * time_source,
|
||||||
rcl_time_point_value_t time_value)
|
rcl_time_point_value_t time_value)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_source, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (time_source->type != RCL_ROS_TIME) {
|
if (time_source->type != RCL_ROS_TIME) {
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ extern "C"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
|
#include "rcl/allocator.h"
|
||||||
#include "rcl/error_handling.h"
|
#include "rcl/error_handling.h"
|
||||||
|
|
||||||
#if !defined(__MACH__) // Assume clock_get_time is available on OS X.
|
#if !defined(__MACH__) // Assume clock_get_time is available on OS X.
|
||||||
|
@ -47,7 +48,7 @@ extern "C"
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_system_time_now(rcl_time_point_value_t * now)
|
rcl_system_time_now(rcl_time_point_value_t * now)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(now, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(now, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
struct timespec timespec_now;
|
struct timespec timespec_now;
|
||||||
#if defined(__MACH__)
|
#if defined(__MACH__)
|
||||||
// On OS X use clock_get_time.
|
// On OS X use clock_get_time.
|
||||||
|
@ -63,7 +64,7 @@ rcl_system_time_now(rcl_time_point_value_t * now)
|
||||||
clock_gettime(CLOCK_REALTIME, ×pec_now);
|
clock_gettime(CLOCK_REALTIME, ×pec_now);
|
||||||
#endif // defined(__MACH__)
|
#endif // defined(__MACH__)
|
||||||
if (__WOULD_BE_NEGATIVE(timespec_now.tv_sec, timespec_now.tv_nsec)) {
|
if (__WOULD_BE_NEGATIVE(timespec_now.tv_sec, timespec_now.tv_nsec)) {
|
||||||
RCL_SET_ERROR_MSG("unexpected negative time");
|
RCL_SET_ERROR_MSG("unexpected negative time", rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
*now = RCL_S_TO_NS((uint64_t)timespec_now.tv_sec) + timespec_now.tv_nsec;
|
*now = RCL_S_TO_NS((uint64_t)timespec_now.tv_sec) + timespec_now.tv_nsec;
|
||||||
|
@ -73,7 +74,7 @@ rcl_system_time_now(rcl_time_point_value_t * now)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_steady_time_now(rcl_time_point_value_t * now)
|
rcl_steady_time_now(rcl_time_point_value_t * now)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(now, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(now, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
// If clock_gettime is available or on OS X, use a timespec.
|
// If clock_gettime is available or on OS X, use a timespec.
|
||||||
struct timespec timespec_now;
|
struct timespec timespec_now;
|
||||||
#if defined(__MACH__)
|
#if defined(__MACH__)
|
||||||
|
@ -94,7 +95,7 @@ rcl_steady_time_now(rcl_time_point_value_t * now)
|
||||||
#endif // defined(CLOCK_MONOTONIC_RAW)
|
#endif // defined(CLOCK_MONOTONIC_RAW)
|
||||||
#endif // defined(__MACH__)
|
#endif // defined(__MACH__)
|
||||||
if (__WOULD_BE_NEGATIVE(timespec_now.tv_sec, timespec_now.tv_nsec)) {
|
if (__WOULD_BE_NEGATIVE(timespec_now.tv_sec, timespec_now.tv_nsec)) {
|
||||||
RCL_SET_ERROR_MSG("unexpected negative time");
|
RCL_SET_ERROR_MSG("unexpected negative time", rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
*now = RCL_S_TO_NS((uint64_t)timespec_now.tv_sec) + timespec_now.tv_nsec;
|
*now = RCL_S_TO_NS((uint64_t)timespec_now.tv_sec) + timespec_now.tv_nsec;
|
||||||
|
|
|
@ -27,12 +27,13 @@ extern "C"
|
||||||
|
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
#include "./stdatomic_helper.h"
|
#include "./stdatomic_helper.h"
|
||||||
|
#include "rcl/allocator.h"
|
||||||
#include "rcl/error_handling.h"
|
#include "rcl/error_handling.h"
|
||||||
|
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_system_time_now(rcl_time_point_value_t * now)
|
rcl_system_time_now(rcl_time_point_value_t * now)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(now, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(now, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
FILETIME ft;
|
FILETIME ft;
|
||||||
GetSystemTimeAsFileTime(&ft);
|
GetSystemTimeAsFileTime(&ft);
|
||||||
ULARGE_INTEGER uli;
|
ULARGE_INTEGER uli;
|
||||||
|
@ -49,7 +50,7 @@ rcl_system_time_now(rcl_time_point_value_t * now)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_steady_time_now(rcl_time_point_value_t * now)
|
rcl_steady_time_now(rcl_time_point_value_t * now)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(now, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(now, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
LARGE_INTEGER cpu_frequency, performance_count;
|
LARGE_INTEGER cpu_frequency, performance_count;
|
||||||
// These should not ever fail since XP is already end of life:
|
// These should not ever fail since XP is already end of life:
|
||||||
// From https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx and
|
// From https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx and
|
||||||
|
|
|
@ -50,9 +50,15 @@ rcl_timer_init(
|
||||||
const rcl_timer_callback_t callback,
|
const rcl_timer_callback_t callback,
|
||||||
rcl_allocator_t allocator)
|
rcl_allocator_t allocator)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
allocator.allocate, "allocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
allocator.deallocate, "deallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, allocator);
|
||||||
if (timer->impl) {
|
if (timer->impl) {
|
||||||
RCL_SET_ERROR_MSG("timer already initailized, or memory was uninitialized");
|
RCL_SET_ERROR_MSG("timer already initailized, or memory was uninitialized", allocator);
|
||||||
return RCL_RET_ALREADY_INIT;
|
return RCL_RET_ALREADY_INIT;
|
||||||
}
|
}
|
||||||
rcl_time_point_value_t now_steady;
|
rcl_time_point_value_t now_steady;
|
||||||
|
@ -66,12 +72,9 @@ rcl_timer_init(
|
||||||
atomic_init(&impl.last_call_time, now_steady);
|
atomic_init(&impl.last_call_time, now_steady);
|
||||||
atomic_init(&impl.canceled, false);
|
atomic_init(&impl.canceled, false);
|
||||||
impl.allocator = allocator;
|
impl.allocator = allocator;
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
allocator.allocate, "allocate not set", return RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
allocator.deallocate, "deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
|
||||||
timer->impl = (rcl_timer_impl_t *)allocator.allocate(sizeof(rcl_timer_impl_t), allocator.state);
|
timer->impl = (rcl_timer_impl_t *)allocator.allocate(sizeof(rcl_timer_impl_t), allocator.state);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
timer->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC, allocator);
|
||||||
*timer->impl = impl;
|
*timer->impl = impl;
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
@ -92,10 +95,13 @@ rcl_timer_fini(rcl_timer_t * timer)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_timer_call(rcl_timer_t * timer)
|
rcl_timer_call(rcl_timer_t * timer)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
|
const rcl_allocator_t * allocator = rcl_timer_get_allocator(timer);
|
||||||
|
if (!allocator) {
|
||||||
|
return RCL_RET_TIMER_INVALID;
|
||||||
|
}
|
||||||
if (rcl_atomic_load_bool(&timer->impl->canceled)) {
|
if (rcl_atomic_load_bool(&timer->impl->canceled)) {
|
||||||
RCL_SET_ERROR_MSG("timer is canceled");
|
RCL_SET_ERROR_MSG("timer is canceled", *allocator);
|
||||||
return RCL_RET_TIMER_CANCELED;
|
return RCL_RET_TIMER_CANCELED;
|
||||||
}
|
}
|
||||||
rcl_time_point_value_t now_steady;
|
rcl_time_point_value_t now_steady;
|
||||||
|
@ -118,9 +124,12 @@ rcl_timer_call(rcl_timer_t * timer)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_timer_is_ready(const rcl_timer_t * timer, bool * is_ready)
|
rcl_timer_is_ready(const rcl_timer_t * timer, bool * is_ready)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(is_ready, RCL_RET_INVALID_ARGUMENT);
|
const rcl_allocator_t * allocator = rcl_timer_get_allocator(timer);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
|
if (!allocator) {
|
||||||
|
return RCL_RET_TIMER_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(is_ready, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
int64_t time_until_next_call;
|
int64_t time_until_next_call;
|
||||||
rcl_ret_t ret = rcl_timer_get_time_until_next_call(timer, &time_until_next_call);
|
rcl_ret_t ret = rcl_timer_get_time_until_next_call(timer, &time_until_next_call);
|
||||||
if (ret != RCL_RET_OK) {
|
if (ret != RCL_RET_OK) {
|
||||||
|
@ -133,9 +142,12 @@ rcl_timer_is_ready(const rcl_timer_t * timer, bool * is_ready)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_timer_get_time_until_next_call(const rcl_timer_t * timer, int64_t * time_until_next_call)
|
rcl_timer_get_time_until_next_call(const rcl_timer_t * timer, int64_t * time_until_next_call)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_until_next_call, RCL_RET_INVALID_ARGUMENT);
|
const rcl_allocator_t * allocator = rcl_timer_get_allocator(timer);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
|
if (!allocator) {
|
||||||
|
return RCL_RET_TIMER_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_until_next_call, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
rcl_time_point_value_t now;
|
rcl_time_point_value_t now;
|
||||||
rcl_ret_t ret = rcl_steady_time_now(&now);
|
rcl_ret_t ret = rcl_steady_time_now(&now);
|
||||||
if (ret != RCL_RET_OK) {
|
if (ret != RCL_RET_OK) {
|
||||||
|
@ -152,9 +164,12 @@ rcl_timer_get_time_since_last_call(
|
||||||
const rcl_timer_t * timer,
|
const rcl_timer_t * timer,
|
||||||
rcl_time_point_value_t * time_since_last_call)
|
rcl_time_point_value_t * time_since_last_call)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(time_since_last_call, RCL_RET_INVALID_ARGUMENT);
|
const rcl_allocator_t * allocator = rcl_timer_get_allocator(timer);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
|
if (!allocator) {
|
||||||
|
return RCL_RET_TIMER_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(time_since_last_call, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
rcl_time_point_value_t now;
|
rcl_time_point_value_t now;
|
||||||
rcl_ret_t ret = rcl_steady_time_now(&now);
|
rcl_ret_t ret = rcl_steady_time_now(&now);
|
||||||
if (ret != RCL_RET_OK) {
|
if (ret != RCL_RET_OK) {
|
||||||
|
@ -168,9 +183,12 @@ rcl_timer_get_time_since_last_call(
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_timer_get_period(const rcl_timer_t * timer, uint64_t * period)
|
rcl_timer_get_period(const rcl_timer_t * timer, uint64_t * period)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(period, RCL_RET_INVALID_ARGUMENT);
|
const rcl_allocator_t * allocator = rcl_timer_get_allocator(timer);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
|
if (!allocator) {
|
||||||
|
return RCL_RET_TIMER_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(period, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
*period = rcl_atomic_load_uint64_t(&timer->impl->period);
|
*period = rcl_atomic_load_uint64_t(&timer->impl->period);
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
@ -178,9 +196,12 @@ rcl_timer_get_period(const rcl_timer_t * timer, uint64_t * period)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_timer_exchange_period(const rcl_timer_t * timer, uint64_t new_period, uint64_t * old_period)
|
rcl_timer_exchange_period(const rcl_timer_t * timer, uint64_t new_period, uint64_t * old_period)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(old_period, RCL_RET_INVALID_ARGUMENT);
|
const rcl_allocator_t * allocator = rcl_timer_get_allocator(timer);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
|
if (!allocator) {
|
||||||
|
return RCL_RET_TIMER_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(old_period, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
*old_period = rcl_atomic_exchange_uint64_t(&timer->impl->period, new_period);
|
*old_period = rcl_atomic_exchange_uint64_t(&timer->impl->period, new_period);
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
@ -188,16 +209,18 @@ rcl_timer_exchange_period(const rcl_timer_t * timer, uint64_t new_period, uint64
|
||||||
rcl_timer_callback_t
|
rcl_timer_callback_t
|
||||||
rcl_timer_get_callback(const rcl_timer_t * timer)
|
rcl_timer_get_callback(const rcl_timer_t * timer)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return NULL);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
timer->impl, "timer is invalid", return NULL, rcl_get_default_allocator());
|
||||||
return (rcl_timer_callback_t)rcl_atomic_load_uintptr_t(&timer->impl->callback);
|
return (rcl_timer_callback_t)rcl_atomic_load_uintptr_t(&timer->impl->callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
rcl_timer_callback_t
|
rcl_timer_callback_t
|
||||||
rcl_timer_exchange_callback(rcl_timer_t * timer, const rcl_timer_callback_t new_callback)
|
rcl_timer_exchange_callback(rcl_timer_t * timer, const rcl_timer_callback_t new_callback)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return NULL);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
timer->impl, "timer is invalid", return NULL, rcl_get_default_allocator());
|
||||||
return (rcl_timer_callback_t)rcl_atomic_exchange_uintptr_t(
|
return (rcl_timer_callback_t)rcl_atomic_exchange_uintptr_t(
|
||||||
&timer->impl->callback, (uintptr_t)new_callback);
|
&timer->impl->callback, (uintptr_t)new_callback);
|
||||||
}
|
}
|
||||||
|
@ -205,8 +228,9 @@ rcl_timer_exchange_callback(rcl_timer_t * timer, const rcl_timer_callback_t new_
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_timer_cancel(rcl_timer_t * timer)
|
rcl_timer_cancel(rcl_timer_t * timer)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID, rcl_get_default_allocator());
|
||||||
rcl_atomic_store(&timer->impl->canceled, true);
|
rcl_atomic_store(&timer->impl->canceled, true);
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
@ -214,9 +238,12 @@ rcl_timer_cancel(rcl_timer_t * timer)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_timer_is_canceled(const rcl_timer_t * timer, bool * is_canceled)
|
rcl_timer_is_canceled(const rcl_timer_t * timer, bool * is_canceled)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(is_canceled, RCL_RET_INVALID_ARGUMENT);
|
const rcl_allocator_t * allocator = rcl_timer_get_allocator(timer);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
|
if (!allocator) {
|
||||||
|
return RCL_RET_TIMER_INVALID;
|
||||||
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(is_canceled, RCL_RET_INVALID_ARGUMENT, *allocator);
|
||||||
*is_canceled = rcl_atomic_load_bool(&timer->impl->canceled);
|
*is_canceled = rcl_atomic_load_bool(&timer->impl->canceled);
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
@ -224,8 +251,9 @@ rcl_timer_is_canceled(const rcl_timer_t * timer, bool * is_canceled)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_timer_reset(rcl_timer_t * timer)
|
rcl_timer_reset(rcl_timer_t * timer)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID, rcl_get_default_allocator());
|
||||||
rcl_time_point_value_t now;
|
rcl_time_point_value_t now;
|
||||||
rcl_ret_t now_ret = rcl_steady_time_now(&now);
|
rcl_ret_t now_ret = rcl_steady_time_now(&now);
|
||||||
if (now_ret != RCL_RET_OK) {
|
if (now_ret != RCL_RET_OK) {
|
||||||
|
@ -236,6 +264,15 @@ rcl_timer_reset(rcl_timer_t * timer)
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rcl_allocator_t *
|
||||||
|
rcl_timer_get_allocator(const rcl_timer_t * timer)
|
||||||
|
{
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL, rcl_get_default_allocator());
|
||||||
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
timer->impl, "timer is invalid", return NULL, rcl_get_default_allocator());
|
||||||
|
return &timer->impl->allocator;
|
||||||
|
}
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern "C"
|
||||||
#include "./stdatomic_helper.h"
|
#include "./stdatomic_helper.h"
|
||||||
#include "rcl/error_handling.h"
|
#include "rcl/error_handling.h"
|
||||||
#include "rcl/time.h"
|
#include "rcl/time.h"
|
||||||
|
#include "rmw/error_handling.h"
|
||||||
#include "rmw/rmw.h"
|
#include "rmw/rmw.h"
|
||||||
|
|
||||||
typedef struct rcl_wait_set_impl_t
|
typedef struct rcl_wait_set_impl_t
|
||||||
|
@ -114,22 +115,27 @@ rcl_wait_set_init(
|
||||||
rcl_allocator_t allocator)
|
rcl_allocator_t allocator)
|
||||||
{
|
{
|
||||||
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
rcl_ret_t fail_ret = RCL_RET_ERROR;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
allocator.allocate, "allocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
allocator.deallocate, "deallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
|
allocator.reallocate, "reallocate not set",
|
||||||
|
return RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT, allocator);
|
||||||
if (__wait_set_is_valid(wait_set)) {
|
if (__wait_set_is_valid(wait_set)) {
|
||||||
RCL_SET_ERROR_MSG("wait_set already initialized, or memory was uninitialized.");
|
RCL_SET_ERROR_MSG("wait_set already initialized, or memory was uninitialized.", allocator);
|
||||||
return RCL_RET_ALREADY_INIT;
|
return RCL_RET_ALREADY_INIT;
|
||||||
}
|
}
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
allocator.allocate, "allocate not set", return RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
allocator.deallocate, "deallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
|
||||||
allocator.reallocate, "reallocate not set", return RCL_RET_INVALID_ARGUMENT);
|
|
||||||
// Allocate space for the implementation struct.
|
// Allocate space for the implementation struct.
|
||||||
wait_set->impl = (rcl_wait_set_impl_t *)allocator.allocate(
|
wait_set->impl = (rcl_wait_set_impl_t *)allocator.allocate(
|
||||||
sizeof(rcl_wait_set_impl_t), allocator.state);
|
sizeof(rcl_wait_set_impl_t), allocator.state);
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG(
|
RCL_CHECK_FOR_NULL_WITH_MSG(
|
||||||
wait_set->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
|
wait_set->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC, allocator);
|
||||||
memset(wait_set->impl, 0, sizeof(rcl_wait_set_impl_t));
|
memset(wait_set->impl, 0, sizeof(rcl_wait_set_impl_t));
|
||||||
wait_set->impl->rmw_subscriptions.subscribers = NULL;
|
wait_set->impl->rmw_subscriptions.subscribers = NULL;
|
||||||
wait_set->impl->rmw_subscriptions.subscriber_count = 0;
|
wait_set->impl->rmw_subscriptions.subscriber_count = 0;
|
||||||
|
@ -215,12 +221,12 @@ rcl_ret_t
|
||||||
rcl_wait_set_fini(rcl_wait_set_t * wait_set)
|
rcl_wait_set_fini(rcl_wait_set_t * wait_set)
|
||||||
{
|
{
|
||||||
rcl_ret_t result = RCL_RET_OK;
|
rcl_ret_t result = RCL_RET_OK;
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
|
|
||||||
if (__wait_set_is_valid(wait_set)) {
|
if (__wait_set_is_valid(wait_set)) {
|
||||||
rmw_ret_t ret = rmw_destroy_waitset(wait_set->impl->rmw_waitset);
|
rmw_ret_t ret = rmw_destroy_waitset(wait_set->impl->rmw_waitset);
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), wait_set->impl->allocator);
|
||||||
result = RCL_RET_WAIT_SET_INVALID;
|
result = RCL_RET_WAIT_SET_INVALID;
|
||||||
}
|
}
|
||||||
__wait_set_clean_up(wait_set, wait_set->impl->allocator);
|
__wait_set_clean_up(wait_set, wait_set->impl->allocator);
|
||||||
|
@ -231,25 +237,25 @@ rcl_wait_set_fini(rcl_wait_set_t * wait_set)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_wait_set_get_allocator(const rcl_wait_set_t * wait_set, rcl_allocator_t * allocator)
|
rcl_wait_set_get_allocator(const rcl_wait_set_t * wait_set, rcl_allocator_t * allocator)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(allocator, RCL_RET_INVALID_ARGUMENT);
|
|
||||||
if (!__wait_set_is_valid(wait_set)) {
|
if (!__wait_set_is_valid(wait_set)) {
|
||||||
RCL_SET_ERROR_MSG("wait set is invalid");
|
RCL_SET_ERROR_MSG("wait set is invalid", rcl_get_default_allocator());
|
||||||
return RCL_RET_WAIT_SET_INVALID;
|
return RCL_RET_WAIT_SET_INVALID;
|
||||||
}
|
}
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(allocator, RCL_RET_INVALID_ARGUMENT, wait_set->impl->allocator);
|
||||||
*allocator = wait_set->impl->allocator;
|
*allocator = wait_set->impl->allocator;
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SET_ADD(Type) \
|
#define SET_ADD(Type) \
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT); \
|
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); \
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(Type, RCL_RET_INVALID_ARGUMENT); \
|
|
||||||
if (!__wait_set_is_valid(wait_set)) { \
|
if (!__wait_set_is_valid(wait_set)) { \
|
||||||
RCL_SET_ERROR_MSG("wait set is invalid"); \
|
RCL_SET_ERROR_MSG("wait set is invalid", rcl_get_default_allocator()); \
|
||||||
return RCL_RET_WAIT_SET_INVALID; \
|
return RCL_RET_WAIT_SET_INVALID; \
|
||||||
} \
|
} \
|
||||||
|
RCL_CHECK_ARGUMENT_FOR_NULL(Type, RCL_RET_INVALID_ARGUMENT, wait_set->impl->allocator); \
|
||||||
if (!(wait_set->impl->Type ## _index < wait_set->size_of_ ## Type ## s)) { \
|
if (!(wait_set->impl->Type ## _index < wait_set->size_of_ ## Type ## s)) { \
|
||||||
RCL_SET_ERROR_MSG(#Type "s set is full"); \
|
RCL_SET_ERROR_MSG(#Type "s set is full", wait_set->impl->allocator); \
|
||||||
return RCL_RET_WAIT_SET_FULL; \
|
return RCL_RET_WAIT_SET_FULL; \
|
||||||
} \
|
} \
|
||||||
size_t current_index = wait_set->impl->Type ## _index++; \
|
size_t current_index = wait_set->impl->Type ## _index++; \
|
||||||
|
@ -259,14 +265,14 @@ rcl_wait_set_get_allocator(const rcl_wait_set_t * wait_set, rcl_allocator_t * al
|
||||||
/* Also place into rmw storage. */ \
|
/* Also place into rmw storage. */ \
|
||||||
rmw_ ## Type ## _t * rmw_handle = rcl_ ## Type ## _get_rmw_handle(Type); \
|
rmw_ ## Type ## _t * rmw_handle = rcl_ ## Type ## _get_rmw_handle(Type); \
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG( \
|
RCL_CHECK_FOR_NULL_WITH_MSG( \
|
||||||
rmw_handle, rcl_get_error_string_safe(), return RCL_RET_ERROR); \
|
rmw_handle, rcl_get_error_string_safe(), return RCL_RET_ERROR, wait_set->impl->allocator); \
|
||||||
wait_set->impl->RMWStorage[current_index] = rmw_handle->data; \
|
wait_set->impl->RMWStorage[current_index] = rmw_handle->data; \
|
||||||
wait_set->impl->RMWCount++;
|
wait_set->impl->RMWCount++;
|
||||||
|
|
||||||
#define SET_CLEAR(Type) \
|
#define SET_CLEAR(Type) \
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT); \
|
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); \
|
||||||
if (!__wait_set_is_valid(wait_set)) { \
|
if (!__wait_set_is_valid(wait_set)) { \
|
||||||
RCL_SET_ERROR_MSG("wait set is invalid"); \
|
RCL_SET_ERROR_MSG("wait set is invalid", rcl_get_default_allocator()); \
|
||||||
return RCL_RET_WAIT_SET_INVALID; \
|
return RCL_RET_WAIT_SET_INVALID; \
|
||||||
} \
|
} \
|
||||||
memset( \
|
memset( \
|
||||||
|
@ -284,9 +290,10 @@ rcl_wait_set_get_allocator(const rcl_wait_set_t * wait_set, rcl_allocator_t * al
|
||||||
wait_set->impl->RMWCount = 0;
|
wait_set->impl->RMWCount = 0;
|
||||||
|
|
||||||
#define SET_RESIZE(Type, ExtraDealloc, ExtraRealloc) \
|
#define SET_RESIZE(Type, ExtraDealloc, ExtraRealloc) \
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT); \
|
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); \
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG( \
|
RCL_CHECK_FOR_NULL_WITH_MSG( \
|
||||||
wait_set->impl, "wait set is invalid", return RCL_RET_WAIT_SET_INVALID); \
|
wait_set->impl, "wait set is invalid", \
|
||||||
|
return RCL_RET_WAIT_SET_INVALID, rcl_get_default_allocator()); \
|
||||||
if (size == wait_set->size_of_ ## Type ## s) { \
|
if (size == wait_set->size_of_ ## Type ## s) { \
|
||||||
return RCL_RET_OK; \
|
return RCL_RET_OK; \
|
||||||
} \
|
} \
|
||||||
|
@ -302,7 +309,8 @@ rcl_wait_set_get_allocator(const rcl_wait_set_t * wait_set, rcl_allocator_t * al
|
||||||
wait_set->Type ## s = (const rcl_ ## Type ## _t * *)allocator.reallocate( \
|
wait_set->Type ## s = (const rcl_ ## Type ## _t * *)allocator.reallocate( \
|
||||||
(void *)wait_set->Type ## s, sizeof(rcl_ ## Type ## _t *) * size, allocator.state); \
|
(void *)wait_set->Type ## s, sizeof(rcl_ ## Type ## _t *) * size, allocator.state); \
|
||||||
RCL_CHECK_FOR_NULL_WITH_MSG( \
|
RCL_CHECK_FOR_NULL_WITH_MSG( \
|
||||||
wait_set->Type ## s, "allocating memory failed", return RCL_RET_BAD_ALLOC); \
|
wait_set->Type ## s, "allocating memory failed", \
|
||||||
|
return RCL_RET_BAD_ALLOC, wait_set->impl->allocator); \
|
||||||
wait_set->size_of_ ## Type ## s = size; \
|
wait_set->size_of_ ## Type ## s = size; \
|
||||||
ExtraRealloc \
|
ExtraRealloc \
|
||||||
} \
|
} \
|
||||||
|
@ -323,7 +331,7 @@ rcl_wait_set_get_allocator(const rcl_wait_set_t * wait_set, rcl_allocator_t * al
|
||||||
if (!wait_set->impl->RMWStorage) { \
|
if (!wait_set->impl->RMWStorage) { \
|
||||||
allocator.deallocate((void *)wait_set->Type ## s, allocator.state); \
|
allocator.deallocate((void *)wait_set->Type ## s, allocator.state); \
|
||||||
wait_set->size_of_ ## Type ## s = 0; \
|
wait_set->size_of_ ## Type ## s = 0; \
|
||||||
RCL_SET_ERROR_MSG("allocating memory failed"); \
|
RCL_SET_ERROR_MSG("allocating memory failed", wait_set->impl->allocator); \
|
||||||
return RCL_RET_BAD_ALLOC; \
|
return RCL_RET_BAD_ALLOC; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,9 +508,9 @@ rcl_wait_set_resize_services(rcl_wait_set_t * wait_set, size_t size)
|
||||||
rcl_ret_t
|
rcl_ret_t
|
||||||
rcl_wait(rcl_wait_set_t * wait_set, int64_t timeout)
|
rcl_wait(rcl_wait_set_t * wait_set, int64_t timeout)
|
||||||
{
|
{
|
||||||
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT);
|
RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator());
|
||||||
if (!__wait_set_is_valid(wait_set)) {
|
if (!__wait_set_is_valid(wait_set)) {
|
||||||
RCL_SET_ERROR_MSG("wait set is invalid");
|
RCL_SET_ERROR_MSG("wait set is invalid", rcl_get_default_allocator());
|
||||||
return RCL_RET_WAIT_SET_INVALID;
|
return RCL_RET_WAIT_SET_INVALID;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
@ -512,7 +520,7 @@ rcl_wait(rcl_wait_set_t * wait_set, int64_t timeout)
|
||||||
wait_set->size_of_clients == 0 &&
|
wait_set->size_of_clients == 0 &&
|
||||||
wait_set->size_of_services == 0)
|
wait_set->size_of_services == 0)
|
||||||
{
|
{
|
||||||
RCL_SET_ERROR_MSG("wait set is empty");
|
RCL_SET_ERROR_MSG("wait set is empty", wait_set->impl->allocator);
|
||||||
return RCL_RET_WAIT_SET_EMPTY;
|
return RCL_RET_WAIT_SET_EMPTY;
|
||||||
}
|
}
|
||||||
// Calculate the timeout argument.
|
// Calculate the timeout argument.
|
||||||
|
@ -587,7 +595,7 @@ rcl_wait(rcl_wait_set_t * wait_set, int64_t timeout)
|
||||||
}
|
}
|
||||||
// Check for error.
|
// Check for error.
|
||||||
if (ret != RMW_RET_OK) {
|
if (ret != RMW_RET_OK) {
|
||||||
RCL_SET_ERROR_MSG(rmw_get_error_string_safe());
|
RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), wait_set->impl->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
// Check for ready timers next, and set not ready timers to NULL.
|
// Check for ready timers next, and set not ready timers to NULL.
|
||||||
|
|
|
@ -28,14 +28,6 @@ function(test_target_function)
|
||||||
|
|
||||||
# Gtests
|
# Gtests
|
||||||
|
|
||||||
rcl_add_custom_gtest(test_allocator${target_suffix}
|
|
||||||
SRCS rcl/test_allocator.cpp
|
|
||||||
ENV ${extra_test_env}
|
|
||||||
APPEND_LIBRARY_DIRS ${extra_lib_dirs}
|
|
||||||
LIBRARIES ${PROJECT_NAME} ${extra_test_libraries}
|
|
||||||
AMENT_DEPENDENCIES ${rmw_implementation}
|
|
||||||
)
|
|
||||||
|
|
||||||
rcl_add_custom_gtest(test_client${target_suffix}
|
rcl_add_custom_gtest(test_client${target_suffix}
|
||||||
SRCS rcl/test_client.cpp
|
SRCS rcl/test_client.cpp
|
||||||
ENV ${extra_test_env}
|
ENV ${extra_test_env}
|
||||||
|
@ -105,6 +97,14 @@ function(test_target_function)
|
||||||
AMENT_DEPENDENCIES ${rmw_implementation}
|
AMENT_DEPENDENCIES ${rmw_implementation}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rcl_add_custom_gtest(test_guard_condition${target_suffix}
|
||||||
|
SRCS rcl/test_guard_condition.cpp
|
||||||
|
ENV ${extra_test_env}
|
||||||
|
APPEND_LIBRARY_DIRS ${extra_lib_dirs}
|
||||||
|
LIBRARIES ${PROJECT_NAME} ${extra_test_libraries}
|
||||||
|
AMENT_DEPENDENCIES ${rmw_implementation}
|
||||||
|
)
|
||||||
|
|
||||||
rcl_add_custom_gtest(test_publisher${target_suffix}
|
rcl_add_custom_gtest(test_publisher${target_suffix}
|
||||||
SRCS rcl/test_publisher.cpp
|
SRCS rcl/test_publisher.cpp
|
||||||
ENV ${extra_test_env}
|
ENV ${extra_test_env}
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
// Copyright 2015 Open Source Robotics Foundation, Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#include "rcl/allocator.h"
|
|
||||||
|
|
||||||
#include "../memory_tools/memory_tools.hpp"
|
|
||||||
|
|
||||||
#ifdef RMW_IMPLEMENTATION
|
|
||||||
# define CLASSNAME_(NAME, SUFFIX) NAME ## __ ## SUFFIX
|
|
||||||
# define CLASSNAME(NAME, SUFFIX) CLASSNAME_(NAME, SUFFIX)
|
|
||||||
#else
|
|
||||||
# define CLASSNAME(NAME, SUFFIX) NAME
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class CLASSNAME (TestAllocatorFixture, RMW_IMPLEMENTATION) : public ::testing::Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CLASSNAME(TestAllocatorFixture, RMW_IMPLEMENTATION)() {
|
|
||||||
start_memory_checking();
|
|
||||||
stop_memory_checking();
|
|
||||||
}
|
|
||||||
void SetUp()
|
|
||||||
{
|
|
||||||
set_on_unexpected_malloc_callback([]() {EXPECT_FALSE(true) << "UNEXPECTED MALLOC";});
|
|
||||||
set_on_unexpected_realloc_callback([]() {EXPECT_FALSE(true) << "UNEXPECTED REALLOC";});
|
|
||||||
set_on_unexpected_free_callback([]() {EXPECT_FALSE(true) << "UNEXPECTED FREE";});
|
|
||||||
start_memory_checking();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TearDown()
|
|
||||||
{
|
|
||||||
assert_no_malloc_end();
|
|
||||||
assert_no_realloc_end();
|
|
||||||
assert_no_free_end();
|
|
||||||
stop_memory_checking();
|
|
||||||
set_on_unexpected_malloc_callback(nullptr);
|
|
||||||
set_on_unexpected_realloc_callback(nullptr);
|
|
||||||
set_on_unexpected_free_callback(nullptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Tests the default allocator.
|
|
||||||
*/
|
|
||||||
TEST_F(CLASSNAME(TestAllocatorFixture, RMW_IMPLEMENTATION), test_default_allocator_normal) {
|
|
||||||
#if defined(WIN32)
|
|
||||||
printf("Allocator tests disabled on Windows.\n");
|
|
||||||
return;
|
|
||||||
#endif // defined(WIN32)
|
|
||||||
ASSERT_NO_MALLOC(
|
|
||||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
|
||||||
)
|
|
||||||
size_t mallocs = 0;
|
|
||||||
size_t reallocs = 0;
|
|
||||||
size_t frees = 0;
|
|
||||||
set_on_unexpected_malloc_callback([&mallocs]() {
|
|
||||||
mallocs++;
|
|
||||||
});
|
|
||||||
set_on_unexpected_realloc_callback([&reallocs]() {
|
|
||||||
reallocs++;
|
|
||||||
});
|
|
||||||
set_on_unexpected_free_callback([&frees]() {
|
|
||||||
frees++;
|
|
||||||
});
|
|
||||||
assert_no_malloc_begin();
|
|
||||||
assert_no_realloc_begin();
|
|
||||||
assert_no_free_begin();
|
|
||||||
void * allocated_memory = allocator.allocate(1024, allocator.state);
|
|
||||||
EXPECT_EQ(mallocs, 1u);
|
|
||||||
EXPECT_NE(allocated_memory, nullptr);
|
|
||||||
allocated_memory = allocator.reallocate(allocated_memory, 2048, allocator.state);
|
|
||||||
EXPECT_EQ(reallocs, 1u);
|
|
||||||
EXPECT_NE(allocated_memory, nullptr);
|
|
||||||
allocator.deallocate(allocated_memory, allocator.state);
|
|
||||||
EXPECT_EQ(mallocs, 1u);
|
|
||||||
EXPECT_EQ(reallocs, 1u);
|
|
||||||
EXPECT_EQ(frees, 1u);
|
|
||||||
}
|
|
|
@ -78,7 +78,7 @@ TEST_F(CLASSNAME(TestGetNodeNames, RMW_IMPLEMENTATION), test_rcl_get_node_names)
|
||||||
std::this_thread::sleep_for(1s);
|
std::this_thread::sleep_for(1s);
|
||||||
|
|
||||||
utilities_string_array_t node_names = utilities_get_zero_initialized_string_array();
|
utilities_string_array_t node_names = utilities_get_zero_initialized_string_array();
|
||||||
ret = rcl_get_node_names(node1_ptr, &node_names);
|
ret = rcl_get_node_names(node1_ptr, node1_options.allocator, &node_names);
|
||||||
ASSERT_EQ(UTILITIES_RET_OK, ret) << rcl_get_error_string_safe();
|
ASSERT_EQ(UTILITIES_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
|
||||||
EXPECT_EQ(size_t(2), node_names.size);
|
EXPECT_EQ(size_t(2), node_names.size);
|
||||||
|
|
|
@ -126,17 +126,17 @@ TEST_F(
|
||||||
rcl_topic_names_and_types_t tnat {};
|
rcl_topic_names_and_types_t tnat {};
|
||||||
rcl_node_t zero_node = rcl_get_zero_initialized_node();
|
rcl_node_t zero_node = rcl_get_zero_initialized_node();
|
||||||
// invalid node
|
// invalid node
|
||||||
ret = rcl_get_topic_names_and_types(nullptr, &tnat);
|
ret = rcl_get_topic_names_and_types(nullptr, rcl_get_default_allocator(), &tnat);
|
||||||
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string_safe();
|
||||||
rcl_reset_error();
|
rcl_reset_error();
|
||||||
ret = rcl_get_topic_names_and_types(&zero_node, &tnat);
|
ret = rcl_get_topic_names_and_types(&zero_node, rcl_get_default_allocator(), &tnat);
|
||||||
EXPECT_EQ(RCL_RET_NODE_INVALID, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_NODE_INVALID, ret) << rcl_get_error_string_safe();
|
||||||
rcl_reset_error();
|
rcl_reset_error();
|
||||||
ret = rcl_get_topic_names_and_types(this->old_node_ptr, &tnat);
|
ret = rcl_get_topic_names_and_types(this->old_node_ptr, rcl_get_default_allocator(), &tnat);
|
||||||
EXPECT_EQ(RCL_RET_NODE_INVALID, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_NODE_INVALID, ret) << rcl_get_error_string_safe();
|
||||||
rcl_reset_error();
|
rcl_reset_error();
|
||||||
// invalid topic_names_and_types
|
// invalid topic_names_and_types
|
||||||
ret = rcl_get_topic_names_and_types(this->node_ptr, nullptr);
|
ret = rcl_get_topic_names_and_types(this->node_ptr, rcl_get_default_allocator(), nullptr);
|
||||||
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string_safe();
|
||||||
rcl_reset_error();
|
rcl_reset_error();
|
||||||
// invalid argument to rcl_destroy_topic_names_and_types
|
// invalid argument to rcl_destroy_topic_names_and_types
|
||||||
|
@ -144,7 +144,7 @@ TEST_F(
|
||||||
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string_safe();
|
||||||
rcl_reset_error();
|
rcl_reset_error();
|
||||||
// valid calls
|
// valid calls
|
||||||
ret = rcl_get_topic_names_and_types(this->node_ptr, &tnat);
|
ret = rcl_get_topic_names_and_types(this->node_ptr, rcl_get_default_allocator(), &tnat);
|
||||||
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
ret = rcl_destroy_topic_names_and_types(&tnat);
|
ret = rcl_destroy_topic_names_and_types(&tnat);
|
||||||
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
@ -258,7 +258,7 @@ check_graph_state(
|
||||||
rcl_reset_error();
|
rcl_reset_error();
|
||||||
|
|
||||||
tnat = rcl_get_zero_initialized_topic_names_and_types();
|
tnat = rcl_get_zero_initialized_topic_names_and_types();
|
||||||
ret = rcl_get_topic_names_and_types(node_ptr, &tnat);
|
ret = rcl_get_topic_names_and_types(node_ptr, rcl_get_default_allocator(), &tnat);
|
||||||
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
rcl_reset_error();
|
rcl_reset_error();
|
||||||
is_in_tnat = false;
|
is_in_tnat = false;
|
||||||
|
|
201
rcl/test/rcl/test_guard_condition.cpp
Normal file
201
rcl/test/rcl/test_guard_condition.cpp
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "rcl/rcl.h"
|
||||||
|
#include "rcl/guard_condition.h"
|
||||||
|
|
||||||
|
#include "../memory_tools/memory_tools.hpp"
|
||||||
|
#include "../scope_exit.hpp"
|
||||||
|
#include "rcl/error_handling.h"
|
||||||
|
|
||||||
|
#ifdef RMW_IMPLEMENTATION
|
||||||
|
# define CLASSNAME_(NAME, SUFFIX) NAME ## __ ## SUFFIX
|
||||||
|
# define CLASSNAME(NAME, SUFFIX) CLASSNAME_(NAME, SUFFIX)
|
||||||
|
#else
|
||||||
|
# define CLASSNAME(NAME, SUFFIX) NAME
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CLASSNAME (TestGuardConditionFixture, RMW_IMPLEMENTATION) : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void SetUp()
|
||||||
|
{
|
||||||
|
set_on_unexpected_malloc_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED MALLOC";});
|
||||||
|
set_on_unexpected_realloc_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED REALLOC";});
|
||||||
|
set_on_unexpected_free_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED FREE";});
|
||||||
|
start_memory_checking();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown()
|
||||||
|
{
|
||||||
|
assert_no_malloc_end();
|
||||||
|
assert_no_realloc_end();
|
||||||
|
assert_no_free_end();
|
||||||
|
stop_memory_checking();
|
||||||
|
set_on_unexpected_malloc_callback(nullptr);
|
||||||
|
set_on_unexpected_realloc_callback(nullptr);
|
||||||
|
set_on_unexpected_free_callback(nullptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Tests the guard condition accessors, i.e. rcl_guard_condition_get_* functions.
|
||||||
|
*/
|
||||||
|
TEST_F(
|
||||||
|
CLASSNAME(TestGuardConditionFixture, RMW_IMPLEMENTATION), test_rcl_guard_condition_accessors) {
|
||||||
|
stop_memory_checking();
|
||||||
|
rcl_ret_t ret;
|
||||||
|
|
||||||
|
// Initialize rcl with rcl_init().
|
||||||
|
ret = rcl_init(0, nullptr, rcl_get_default_allocator());
|
||||||
|
ASSERT_EQ(RCL_RET_OK, ret);
|
||||||
|
// Setup automatic rcl_shutdown()
|
||||||
|
auto rcl_shutdown_exit = make_scope_exit([]() {
|
||||||
|
stop_memory_checking();
|
||||||
|
rcl_ret_t ret = rcl_shutdown();
|
||||||
|
ASSERT_EQ(RCL_RET_OK, ret);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a zero initialized guard_condition (but not initialized).
|
||||||
|
rcl_guard_condition_t zero_guard_condition = rcl_get_zero_initialized_guard_condition();
|
||||||
|
|
||||||
|
// Create a normal guard_condition.
|
||||||
|
rcl_guard_condition_options_t default_options = rcl_guard_condition_get_default_options();
|
||||||
|
rcl_guard_condition_t guard_condition = rcl_get_zero_initialized_guard_condition();
|
||||||
|
ret = rcl_guard_condition_init(&guard_condition, default_options);
|
||||||
|
ASSERT_EQ(RCL_RET_OK, ret);
|
||||||
|
// Setup automatic finalization of guard condition.
|
||||||
|
auto rcl_guard_condition_exit = make_scope_exit([&guard_condition]() {
|
||||||
|
stop_memory_checking();
|
||||||
|
rcl_ret_t ret = rcl_guard_condition_fini(&guard_condition);
|
||||||
|
EXPECT_EQ(RCL_RET_OK, ret);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test rcl_guard_condition_get_options().
|
||||||
|
const rcl_guard_condition_options_t * actual_options;
|
||||||
|
actual_options = rcl_guard_condition_get_options(nullptr);
|
||||||
|
EXPECT_EQ(nullptr, actual_options);
|
||||||
|
rcl_reset_error();
|
||||||
|
actual_options = rcl_guard_condition_get_options(&zero_guard_condition);
|
||||||
|
EXPECT_EQ(nullptr, actual_options);
|
||||||
|
rcl_reset_error();
|
||||||
|
start_memory_checking();
|
||||||
|
assert_no_malloc_begin();
|
||||||
|
assert_no_realloc_begin();
|
||||||
|
assert_no_free_begin();
|
||||||
|
actual_options = rcl_guard_condition_get_options(&guard_condition);
|
||||||
|
assert_no_malloc_end();
|
||||||
|
assert_no_realloc_end();
|
||||||
|
assert_no_free_end();
|
||||||
|
stop_memory_checking();
|
||||||
|
EXPECT_NE(nullptr, actual_options);
|
||||||
|
if (actual_options) {
|
||||||
|
EXPECT_EQ(default_options.allocator.allocate, actual_options->allocator.allocate);
|
||||||
|
}
|
||||||
|
// Test rcl_guard_condition_get_rmw_handle().
|
||||||
|
rmw_guard_condition_t * gc_handle;
|
||||||
|
gc_handle = rcl_guard_condition_get_rmw_handle(nullptr);
|
||||||
|
EXPECT_EQ(nullptr, gc_handle);
|
||||||
|
rcl_reset_error();
|
||||||
|
gc_handle = rcl_guard_condition_get_rmw_handle(&zero_guard_condition);
|
||||||
|
EXPECT_EQ(nullptr, gc_handle);
|
||||||
|
rcl_reset_error();
|
||||||
|
start_memory_checking();
|
||||||
|
assert_no_malloc_begin();
|
||||||
|
assert_no_realloc_begin();
|
||||||
|
assert_no_free_begin();
|
||||||
|
gc_handle = rcl_guard_condition_get_rmw_handle(&guard_condition);
|
||||||
|
assert_no_malloc_end();
|
||||||
|
assert_no_realloc_end();
|
||||||
|
assert_no_free_end();
|
||||||
|
stop_memory_checking();
|
||||||
|
EXPECT_NE(nullptr, gc_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tests the guard condition life cycle, including rcl_guard_condition_init/fini().
|
||||||
|
*/
|
||||||
|
TEST_F(
|
||||||
|
CLASSNAME(TestGuardConditionFixture, RMW_IMPLEMENTATION), test_rcl_guard_condition_life_cycle) {
|
||||||
|
stop_memory_checking();
|
||||||
|
rcl_ret_t ret;
|
||||||
|
rcl_guard_condition_t guard_condition = rcl_get_zero_initialized_guard_condition();
|
||||||
|
rcl_guard_condition_options_t default_options = rcl_guard_condition_get_default_options();
|
||||||
|
// Trying to init before rcl_init() should fail.
|
||||||
|
ret = rcl_guard_condition_init(&guard_condition, default_options);
|
||||||
|
ASSERT_EQ(RCL_RET_NOT_INIT, ret) << "Expected RCL_RET_NOT_INIT";
|
||||||
|
ASSERT_TRUE(rcl_error_is_set());
|
||||||
|
rcl_reset_error();
|
||||||
|
// Initialize rcl with rcl_init().
|
||||||
|
ret = rcl_init(0, nullptr, rcl_get_default_allocator());
|
||||||
|
ASSERT_EQ(RCL_RET_OK, ret);
|
||||||
|
auto rcl_shutdown_exit = make_scope_exit([]() {
|
||||||
|
rcl_ret_t ret = rcl_shutdown();
|
||||||
|
ASSERT_EQ(RCL_RET_OK, ret);
|
||||||
|
});
|
||||||
|
// Try invalid arguments.
|
||||||
|
ret = rcl_guard_condition_init(nullptr, default_options);
|
||||||
|
ASSERT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << "Expected RCL_RET_INVALID_ARGUMENT";
|
||||||
|
ASSERT_TRUE(rcl_error_is_set());
|
||||||
|
rcl_reset_error();
|
||||||
|
// Try with invalid allocator.
|
||||||
|
rcl_guard_condition_options_t options_with_invalid_allocator =
|
||||||
|
rcl_guard_condition_get_default_options();
|
||||||
|
options_with_invalid_allocator.allocator.allocate = nullptr;
|
||||||
|
options_with_invalid_allocator.allocator.deallocate = nullptr;
|
||||||
|
options_with_invalid_allocator.allocator.reallocate = nullptr;
|
||||||
|
ret = rcl_guard_condition_init(&guard_condition, options_with_invalid_allocator);
|
||||||
|
ASSERT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << "Expected RCL_RET_INVALID_ARGUMENT";
|
||||||
|
ASSERT_TRUE(rcl_error_is_set());
|
||||||
|
rcl_reset_error();
|
||||||
|
// Try with failing allocator.
|
||||||
|
rcl_guard_condition_options_t options_with_failing_allocator =
|
||||||
|
rcl_guard_condition_get_default_options();
|
||||||
|
options_with_failing_allocator.allocator.allocate = failing_malloc;
|
||||||
|
options_with_failing_allocator.allocator.deallocate = failing_free;
|
||||||
|
options_with_failing_allocator.allocator.reallocate = failing_realloc;
|
||||||
|
ret = rcl_guard_condition_init(&guard_condition, options_with_failing_allocator);
|
||||||
|
ASSERT_EQ(RCL_RET_BAD_ALLOC, ret) << "Expected RCL_RET_BAD_ALLOC";
|
||||||
|
// The error will not be set because the allocator will not work.
|
||||||
|
// It should, however, print a message to the screen and get the bad alloc ret code.
|
||||||
|
// ASSERT_TRUE(rcl_error_is_set());
|
||||||
|
// rcl_reset_error();
|
||||||
|
|
||||||
|
// Try fini with invalid arguments.
|
||||||
|
ret = rcl_guard_condition_fini(nullptr);
|
||||||
|
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << "Expected RCL_RET_INVALID_ARGUMENT";
|
||||||
|
ASSERT_TRUE(rcl_error_is_set());
|
||||||
|
rcl_reset_error();
|
||||||
|
// Try fini with an uninitialized guard_condition.
|
||||||
|
ret = rcl_guard_condition_fini(&guard_condition);
|
||||||
|
EXPECT_EQ(RCL_RET_OK, ret);
|
||||||
|
// Try a normal init and fini.
|
||||||
|
ret = rcl_guard_condition_init(&guard_condition, default_options);
|
||||||
|
EXPECT_EQ(RCL_RET_OK, ret);
|
||||||
|
ret = rcl_guard_condition_fini(&guard_condition);
|
||||||
|
EXPECT_EQ(RCL_RET_OK, ret);
|
||||||
|
// Try repeated init and fini calls.
|
||||||
|
ret = rcl_guard_condition_init(&guard_condition, default_options);
|
||||||
|
EXPECT_EQ(RCL_RET_OK, ret);
|
||||||
|
ret = rcl_guard_condition_init(&guard_condition, default_options);
|
||||||
|
EXPECT_EQ(RCL_RET_ALREADY_INIT, ret) << "Expected RCL_RET_ALREADY_INIT";
|
||||||
|
ASSERT_TRUE(rcl_error_is_set());
|
||||||
|
rcl_reset_error();
|
||||||
|
ret = rcl_guard_condition_fini(&guard_condition);
|
||||||
|
EXPECT_EQ(RCL_RET_OK, ret);
|
||||||
|
ret = rcl_guard_condition_fini(&guard_condition);
|
||||||
|
EXPECT_EQ(RCL_RET_OK, ret);
|
||||||
|
}
|
|
@ -353,8 +353,11 @@ TEST_F(CLASSNAME(TestNodeFixture, RMW_IMPLEMENTATION), test_rcl_node_life_cycle)
|
||||||
options_with_failing_allocator.allocator.reallocate = failing_realloc;
|
options_with_failing_allocator.allocator.reallocate = failing_realloc;
|
||||||
ret = rcl_node_init(&node, name, namespace_, &options_with_failing_allocator);
|
ret = rcl_node_init(&node, name, namespace_, &options_with_failing_allocator);
|
||||||
EXPECT_EQ(RCL_RET_BAD_ALLOC, ret) << "Expected RCL_RET_BAD_ALLOC";
|
EXPECT_EQ(RCL_RET_BAD_ALLOC, ret) << "Expected RCL_RET_BAD_ALLOC";
|
||||||
ASSERT_TRUE(rcl_error_is_set());
|
// The error will not be set because the allocator will not work.
|
||||||
rcl_reset_error();
|
// It should, however, print a message to the screen and get the bad alloc ret code.
|
||||||
|
// ASSERT_TRUE(rcl_error_is_set());
|
||||||
|
// rcl_reset_error();
|
||||||
|
|
||||||
// Try fini with invalid arguments.
|
// Try fini with invalid arguments.
|
||||||
ret = rcl_node_fini(nullptr);
|
ret = rcl_node_fini(nullptr);
|
||||||
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << "Expected RCL_RET_INVALID_ARGUMENT";
|
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << "Expected RCL_RET_INVALID_ARGUMENT";
|
||||||
|
|
|
@ -34,10 +34,27 @@
|
||||||
# define CLASSNAME(NAME, SUFFIX) NAME
|
# define CLASSNAME(NAME, SUFFIX) NAME
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define TOLERANCE RCL_MS_TO_NS(6)
|
#define TOLERANCE RCL_MS_TO_NS(6)
|
||||||
|
|
||||||
TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), test_resize_to_zero) {
|
class CLASSNAME (WaitSetTestFixture, RMW_IMPLEMENTATION) : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void SetUp()
|
||||||
|
{
|
||||||
|
rcl_ret_t ret;
|
||||||
|
ret = rcl_init(0, nullptr, rcl_get_default_allocator());
|
||||||
|
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown()
|
||||||
|
{
|
||||||
|
rcl_ret_t ret;
|
||||||
|
ret = rcl_shutdown();
|
||||||
|
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), test_resize_to_zero) {
|
||||||
// Initialize a waitset with a subscription and then resize it to zero.
|
// Initialize a waitset with a subscription and then resize it to zero.
|
||||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||||
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 1, 0, 0, 0, 0, rcl_get_default_allocator());
|
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 1, 0, 0, 0, 0, rcl_get_default_allocator());
|
||||||
|
@ -53,7 +70,7 @@ TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), test_resize_to_zero) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test rcl_wait with a positive finite timeout value (1ms)
|
// Test rcl_wait with a positive finite timeout value (1ms)
|
||||||
TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), finite_timeout) {
|
TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), finite_timeout) {
|
||||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||||
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 0, 1, 0, 0, rcl_get_default_allocator());
|
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 0, 1, 0, 0, rcl_get_default_allocator());
|
||||||
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
@ -72,7 +89,7 @@ TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), finite_timeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that a timer overrides a negative timeout value (blocking forever)
|
// Check that a timer overrides a negative timeout value (blocking forever)
|
||||||
TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), negative_timeout) {
|
TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), negative_timeout) {
|
||||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||||
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, rcl_get_default_allocator());
|
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, rcl_get_default_allocator());
|
||||||
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
@ -111,7 +128,7 @@ TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), negative_timeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test rcl_wait with a timeout value of 0 (non-blocking)
|
// Test rcl_wait with a timeout value of 0 (non-blocking)
|
||||||
TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), zero_timeout) {
|
TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), zero_timeout) {
|
||||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||||
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, rcl_get_default_allocator());
|
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, rcl_get_default_allocator());
|
||||||
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
@ -142,7 +159,7 @@ TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), zero_timeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that a canceled timer doesn't wake up rcl_wait
|
// Check that a canceled timer doesn't wake up rcl_wait
|
||||||
TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), canceled_timer) {
|
TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), canceled_timer) {
|
||||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||||
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, rcl_get_default_allocator());
|
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, rcl_get_default_allocator());
|
||||||
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
@ -183,7 +200,7 @@ TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), canceled_timer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test rcl_wait_set_t with excess capacity works.
|
// Test rcl_wait_set_t with excess capacity works.
|
||||||
TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), excess_capacity) {
|
TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), excess_capacity) {
|
||||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||||
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 42, 42, 42, 42, 42, rcl_get_default_allocator());
|
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 42, 42, 42, 42, 42, rcl_get_default_allocator());
|
||||||
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
@ -194,7 +211,7 @@ TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), excess_capacity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check rcl_wait can be called in many threads, each with unique wait sets and resources.
|
// Check rcl_wait can be called in many threads, each with unique wait sets and resources.
|
||||||
TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), multi_wait_set_threaded) {
|
TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), multi_wait_set_threaded) {
|
||||||
rcl_ret_t ret;
|
rcl_ret_t ret;
|
||||||
const size_t number_of_threads = 20; // concurrent waits
|
const size_t number_of_threads = 20; // concurrent waits
|
||||||
const size_t count_target = 10; // number of times each wait should wake up before being "done"
|
const size_t count_target = 10; // number of times each wait should wake up before being "done"
|
||||||
|
@ -303,7 +320,7 @@ TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), multi_wait_set_threaded)
|
||||||
loop_count++;
|
loop_count++;
|
||||||
for (auto & test_set : test_sets) {
|
for (auto & test_set : test_sets) {
|
||||||
ret = rcl_trigger_guard_condition(&test_set.guard_condition);
|
ret = rcl_trigger_guard_condition(&test_set.guard_condition);
|
||||||
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(trigger_period);
|
std::this_thread::sleep_for(trigger_period);
|
||||||
}
|
}
|
||||||
|
@ -319,7 +336,7 @@ TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), multi_wait_set_threaded)
|
||||||
|
|
||||||
// Check the interaction of a guard condition and a negative timeout by
|
// Check the interaction of a guard condition and a negative timeout by
|
||||||
// triggering a guard condition in a separate thread
|
// triggering a guard condition in a separate thread
|
||||||
TEST(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), guard_condition) {
|
TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), guard_condition) {
|
||||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||||
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 1, 0, 0, 0, rcl_get_default_allocator());
|
rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 1, 0, 0, 0, rcl_get_default_allocator());
|
||||||
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
|
||||||
|
|
|
@ -84,6 +84,8 @@ typedef struct rcl_lifecycle_state_machine_t
|
||||||
rcl_lifecycle_transition_map_t transition_map;
|
rcl_lifecycle_transition_map_t transition_map;
|
||||||
// Communication interface into a ROS world
|
// Communication interface into a ROS world
|
||||||
rcl_lifecycle_com_interface_t com_interface;
|
rcl_lifecycle_com_interface_t com_interface;
|
||||||
|
// Allocator used.
|
||||||
|
rcl_allocator_t allocator;
|
||||||
} rcl_lifecycle_state_machine_t;
|
} rcl_lifecycle_state_machine_t;
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
|
|
|
@ -67,24 +67,32 @@ rcl_lifecycle_com_interface_init(rcl_lifecycle_com_interface_t * com_interface,
|
||||||
const rosidl_service_type_support_t * ts_srv_get_available_states,
|
const rosidl_service_type_support_t * ts_srv_get_available_states,
|
||||||
const rosidl_service_type_support_t * ts_srv_get_available_transitions)
|
const rosidl_service_type_support_t * ts_srv_get_available_transitions)
|
||||||
{
|
{
|
||||||
|
if (!node_handle) {
|
||||||
|
RCL_SET_ERROR_MSG("node_handle is null", rcl_get_default_allocator());
|
||||||
|
return RCL_RET_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
const rcl_node_options_t * node_options = rcl_node_get_options(node_handle);
|
||||||
|
if (!node_options) {
|
||||||
|
return RCL_RET_NODE_INVALID;
|
||||||
|
}
|
||||||
if (!ts_pub_notify) {
|
if (!ts_pub_notify) {
|
||||||
RCL_SET_ERROR_MSG("ts_pub_notify is NULL");
|
RCL_SET_ERROR_MSG("ts_pub_notify is NULL", node_options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
if (!ts_srv_change_state) {
|
if (!ts_srv_change_state) {
|
||||||
RCL_SET_ERROR_MSG("ts_srv_change_state is NULL");
|
RCL_SET_ERROR_MSG("ts_srv_change_state is NULL", node_options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
if (!ts_srv_get_state) {
|
if (!ts_srv_get_state) {
|
||||||
RCL_SET_ERROR_MSG("ts_srv_get_state is NULL");
|
RCL_SET_ERROR_MSG("ts_srv_get_state is NULL", node_options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
if (!ts_srv_get_available_states) {
|
if (!ts_srv_get_available_states) {
|
||||||
RCL_SET_ERROR_MSG("ts_srv_get_available_states is NULL");
|
RCL_SET_ERROR_MSG("ts_srv_get_available_states is NULL", node_options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
if (!ts_srv_get_available_states) {
|
if (!ts_srv_get_available_states) {
|
||||||
RCL_SET_ERROR_MSG("ts_srv_get_available_transitions is NULL");
|
RCL_SET_ERROR_MSG("ts_srv_get_available_transitions is NULL", node_options->allocator);
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +105,7 @@ rcl_lifecycle_com_interface_init(rcl_lifecycle_com_interface_t * com_interface,
|
||||||
const char * topic_prefix = "__transition_event";
|
const char * topic_prefix = "__transition_event";
|
||||||
char * topic_name;
|
char * topic_name;
|
||||||
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
||||||
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255");
|
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255", node_options->allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +130,7 @@ rcl_lifecycle_com_interface_init(rcl_lifecycle_com_interface_t * com_interface,
|
||||||
const char * topic_prefix = "__change_state";
|
const char * topic_prefix = "__change_state";
|
||||||
char * topic_name;
|
char * topic_name;
|
||||||
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
||||||
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255");
|
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255", node_options->allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +152,7 @@ rcl_lifecycle_com_interface_init(rcl_lifecycle_com_interface_t * com_interface,
|
||||||
const char * topic_prefix = "__get_state";
|
const char * topic_prefix = "__get_state";
|
||||||
char * topic_name;
|
char * topic_name;
|
||||||
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
||||||
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255");
|
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255", node_options->allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +174,7 @@ rcl_lifecycle_com_interface_init(rcl_lifecycle_com_interface_t * com_interface,
|
||||||
const char * topic_prefix = "__get_available_states";
|
const char * topic_prefix = "__get_available_states";
|
||||||
char * topic_name;
|
char * topic_name;
|
||||||
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
||||||
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255");
|
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255", node_options->allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +196,7 @@ rcl_lifecycle_com_interface_init(rcl_lifecycle_com_interface_t * com_interface,
|
||||||
const char * topic_prefix = "__get_available_transitions";
|
const char * topic_prefix = "__get_available_transitions";
|
||||||
char * topic_name;
|
char * topic_name;
|
||||||
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
if (!concatenate(&node_name, &topic_prefix, &topic_name)) {
|
||||||
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255");
|
RCL_SET_ERROR_MSG("Topic name exceeds maximum size of 255", node_options->allocator);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,10 @@ rcl_lifecycle_get_zero_initialized_state_machine()
|
||||||
state_machine.transition_map.transitions = NULL;
|
state_machine.transition_map.transitions = NULL;
|
||||||
state_machine.transition_map.transitions_size = 0;
|
state_machine.transition_map.transitions_size = 0;
|
||||||
state_machine.com_interface = rcl_lifecycle_get_zero_initialized_com_interface();
|
state_machine.com_interface = rcl_lifecycle_get_zero_initialized_com_interface();
|
||||||
|
state_machine.allocator.allocate = NULL;
|
||||||
|
state_machine.allocator.deallocate = NULL;
|
||||||
|
state_machine.allocator.reallocate = NULL;
|
||||||
|
state_machine.allocator.state = NULL;
|
||||||
return state_machine;
|
return state_machine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,8 +69,19 @@ rcl_lifecycle_state_machine_init(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (default_states) {
|
if (default_states) {
|
||||||
rcl_lifecycle_init_default_state_machine(state_machine);
|
rcl_ret_t ret = rcl_lifecycle_init_default_state_machine(state_machine);
|
||||||
|
if (ret != RCL_RET_OK) {
|
||||||
|
// error should already be set
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rcl_node_options_t * node_options = rcl_node_get_options(node_handle);
|
||||||
|
if (!node_options) {
|
||||||
|
RCL_SET_ERROR_MSG("node does not have valid options", rcl_get_default_allocator());
|
||||||
|
return RCL_RET_NODE_INVALID;
|
||||||
|
}
|
||||||
|
state_machine->allocator = node_options->allocator;
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,11 +115,11 @@ rcl_ret_t
|
||||||
rcl_lifecycle_state_machine_is_initialized(const rcl_lifecycle_state_machine_t * state_machine)
|
rcl_lifecycle_state_machine_is_initialized(const rcl_lifecycle_state_machine_t * state_machine)
|
||||||
{
|
{
|
||||||
if (!state_machine->com_interface.srv_get_state.impl) {
|
if (!state_machine->com_interface.srv_get_state.impl) {
|
||||||
RCL_SET_ERROR_MSG("get_state service is null");
|
RCL_SET_ERROR_MSG("get_state service is null", rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
if (!state_machine->com_interface.srv_change_state.impl) {
|
if (!state_machine->com_interface.srv_change_state.impl) {
|
||||||
RCL_SET_ERROR_MSG("change_state service is null");
|
RCL_SET_ERROR_MSG("change_state service is null", rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
return RCL_RET_OK;
|
return RCL_RET_OK;
|
||||||
|
@ -141,7 +156,7 @@ rcl_lifecycle_trigger_transition(
|
||||||
if (!transition) {
|
if (!transition) {
|
||||||
fprintf(stderr, "No transition found for node %s with key %d\n",
|
fprintf(stderr, "No transition found for node %s with key %d\n",
|
||||||
state_machine->current_state->label, key);
|
state_machine->current_state->label, key);
|
||||||
RCL_SET_ERROR_MSG("Transition is not registered.");
|
RCL_SET_ERROR_MSG("Transition is not registered.", rcl_get_default_allocator());
|
||||||
return RCL_RET_ERROR;
|
return RCL_RET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue