move a lot to memory strategy
This commit is contained in:
parent
c663d892a4
commit
06818ee78c
4 changed files with 478 additions and 245 deletions
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include <rclcpp/any_executable.hpp>
|
#include <rclcpp/any_executable.hpp>
|
||||||
#include <rclcpp/macros.hpp>
|
#include <rclcpp/macros.hpp>
|
||||||
#include <rclcpp/memory_strategy.hpp>
|
#include <rclcpp/memory_strategies.hpp>
|
||||||
#include <rclcpp/node.hpp>
|
#include <rclcpp/node.hpp>
|
||||||
#include <rclcpp/utilities.hpp>
|
#include <rclcpp/utilities.hpp>
|
||||||
|
|
||||||
|
@ -343,10 +343,17 @@ protected:
|
||||||
void
|
void
|
||||||
wait_for_work(std::chrono::duration<int64_t, T> timeout = std::chrono::duration<int64_t, T>(-1))
|
wait_for_work(std::chrono::duration<int64_t, T> timeout = std::chrono::duration<int64_t, T>(-1))
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
memory_strategy_->subs.clear();
|
memory_strategy_->subs.clear();
|
||||||
memory_strategy_->services.clear();
|
memory_strategy_->services.clear();
|
||||||
memory_strategy_->clients.clear();
|
memory_strategy_->clients.clear();
|
||||||
|
*/
|
||||||
|
memory_strategy_->clear_active_entities();
|
||||||
|
|
||||||
// Collect the subscriptions and timers to be waited on
|
// Collect the subscriptions and timers to be waited on
|
||||||
|
bool has_invalid_weak_nodes = memory_strategy_->collect_entities(weak_nodes_);
|
||||||
|
|
||||||
|
/*
|
||||||
bool has_invalid_weak_nodes = false;
|
bool has_invalid_weak_nodes = false;
|
||||||
for (auto & weak_node : weak_nodes_) {
|
for (auto & weak_node : weak_nodes_) {
|
||||||
auto node = weak_node.lock();
|
auto node = weak_node.lock();
|
||||||
|
@ -373,6 +380,8 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Clean up any invalid nodes, if they were detected
|
// Clean up any invalid nodes, if they were detected
|
||||||
if (has_invalid_weak_nodes) {
|
if (has_invalid_weak_nodes) {
|
||||||
weak_nodes_.erase(
|
weak_nodes_.erase(
|
||||||
|
@ -382,7 +391,22 @@ protected:
|
||||||
return i.expired();
|
return i.expired();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Use the number of subscriptions to allocate memory in the handles
|
// Use the number of subscriptions to allocate memory in the handles
|
||||||
|
rmw_subscriptions_t subscriber_handles;
|
||||||
|
subscriber_handles.subscriber_count =
|
||||||
|
memory_strategy_->fill_subscriber_handles(subscriber_handles.subscribers);
|
||||||
|
|
||||||
|
rmw_services_t service_handles;
|
||||||
|
service_handles.service_count =
|
||||||
|
memory_strategy_->fill_service_handles(service_handles.services);
|
||||||
|
|
||||||
|
rmw_clients_t client_handles;
|
||||||
|
client_handles.client_count =
|
||||||
|
memory_strategy_->fill_client_handles(client_handles.clients);
|
||||||
|
|
||||||
|
/*
|
||||||
size_t max_number_of_subscriptions = memory_strategy_->subs.size() * 2; // Times two for intra-process.
|
size_t max_number_of_subscriptions = memory_strategy_->subs.size() * 2; // Times two for intra-process.
|
||||||
rmw_subscriptions_t subscriber_handles;
|
rmw_subscriptions_t subscriber_handles;
|
||||||
subscriber_handles.subscriber_count = 0;
|
subscriber_handles.subscriber_count = 0;
|
||||||
|
@ -442,14 +466,16 @@ protected:
|
||||||
client->get_client_handle()->data;
|
client->get_client_handle()->data;
|
||||||
client_handle_index += 1;
|
client_handle_index += 1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// The number of guard conditions is fixed at 2: 1 for the ctrl-c guard cond,
|
// The number of guard conditions is fixed at 2: 1 for the ctrl-c guard cond,
|
||||||
// and one for the executor's guard cond (interrupt_guard_condition_)
|
// and one for the executor's guard cond (interrupt_guard_condition_)
|
||||||
size_t number_of_guard_conds = 2;
|
size_t number_of_guard_conds = 2;
|
||||||
rmw_guard_conditions_t guard_condition_handles;
|
rmw_guard_conditions_t guard_condition_handles;
|
||||||
guard_condition_handles.guard_condition_count = number_of_guard_conds;
|
guard_condition_handles.guard_condition_count = number_of_guard_conds;
|
||||||
guard_condition_handles.guard_conditions =
|
/*guard_condition_handles.guard_conditions =
|
||||||
memory_strategy_->borrow_handles(HandleType::guard_condition_handle, number_of_guard_conds);
|
memory_strategy_->borrow_handles(HandleType::guard_condition_handle, number_of_guard_conds);*/
|
||||||
|
guard_condition_handles.guard_conditions = static_cast<void**>(guard_cond_handles_.data());
|
||||||
if (guard_condition_handles.guard_conditions == NULL &&
|
if (guard_condition_handles.guard_conditions == NULL &&
|
||||||
number_of_guard_conds > 0)
|
number_of_guard_conds > 0)
|
||||||
{
|
{
|
||||||
|
@ -500,6 +526,7 @@ protected:
|
||||||
// If ctrl-c guard condition, return directly
|
// If ctrl-c guard condition, return directly
|
||||||
if (guard_condition_handles.guard_conditions[0] != 0) {
|
if (guard_condition_handles.guard_conditions[0] != 0) {
|
||||||
// Make sure to free or clean memory
|
// Make sure to free or clean memory
|
||||||
|
/*
|
||||||
memory_strategy_->return_handles(HandleType::subscription_handle,
|
memory_strategy_->return_handles(HandleType::subscription_handle,
|
||||||
subscriber_handles.subscribers);
|
subscriber_handles.subscribers);
|
||||||
memory_strategy_->return_handles(HandleType::service_handle,
|
memory_strategy_->return_handles(HandleType::service_handle,
|
||||||
|
@ -508,10 +535,13 @@ protected:
|
||||||
client_handles.clients);
|
client_handles.clients);
|
||||||
memory_strategy_->return_handles(HandleType::guard_condition_handle,
|
memory_strategy_->return_handles(HandleType::guard_condition_handle,
|
||||||
guard_condition_handles.guard_conditions);
|
guard_condition_handles.guard_conditions);
|
||||||
|
*/
|
||||||
|
memory_strategy_->clear_handles();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Add the new work to the class's list of things waiting to be executed
|
// Add the new work to the class's list of things waiting to be executed
|
||||||
// Starting with the subscribers
|
// Starting with the subscribers
|
||||||
|
/*
|
||||||
for (size_t i = 0; i < subscriber_handles.subscriber_count; ++i) {
|
for (size_t i = 0; i < subscriber_handles.subscriber_count; ++i) {
|
||||||
void * handle = subscriber_handles.subscribers[i];
|
void * handle = subscriber_handles.subscribers[i];
|
||||||
if (handle) {
|
if (handle) {
|
||||||
|
@ -545,10 +575,13 @@ protected:
|
||||||
memory_strategy_->subs.clear();
|
memory_strategy_->subs.clear();
|
||||||
memory_strategy_->services.clear();
|
memory_strategy_->services.clear();
|
||||||
memory_strategy_->clients.clear();
|
memory_strategy_->clients.clear();
|
||||||
|
*/
|
||||||
|
memory_strategy_->clear_active_entities();
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************/
|
/******************************/
|
||||||
|
|
||||||
|
/*
|
||||||
rclcpp::subscription::SubscriptionBase::SharedPtr
|
rclcpp::subscription::SubscriptionBase::SharedPtr
|
||||||
get_subscription_by_handle(void * subscriber_handle)
|
get_subscription_by_handle(void * subscriber_handle)
|
||||||
{
|
{
|
||||||
|
@ -579,6 +612,7 @@ protected:
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
rclcpp::service::ServiceBase::SharedPtr
|
rclcpp::service::ServiceBase::SharedPtr
|
||||||
get_service_by_handle(void * service_handle)
|
get_service_by_handle(void * service_handle)
|
||||||
|
@ -729,6 +763,7 @@ protected:
|
||||||
return latest;
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||||
get_group_by_subscription(
|
get_group_by_subscription(
|
||||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription)
|
rclcpp::subscription::SubscriptionBase::SharedPtr subscription)
|
||||||
|
@ -909,28 +944,29 @@ protected:
|
||||||
client_handles_.erase(it++);
|
client_handles_.erase(it++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
AnyExecutable::SharedPtr
|
AnyExecutable::SharedPtr
|
||||||
get_next_ready_executable()
|
get_next_ready_executable()
|
||||||
{
|
{
|
||||||
auto any_exec = this->memory_strategy_->instantiate_next_executable();
|
auto any_exec = memory_strategy_->instantiate_next_executable();
|
||||||
// Check the timers to see if there are any that are ready, if so return
|
// Check the timers to see if there are any that are ready, if so return
|
||||||
get_next_timer(any_exec);
|
get_next_timer(any_exec);
|
||||||
if (any_exec->timer) {
|
if (any_exec->timer) {
|
||||||
return any_exec;
|
return any_exec;
|
||||||
}
|
}
|
||||||
// Check the subscriptions to see if there are any that are ready
|
// Check the subscriptions to see if there are any that are ready
|
||||||
get_next_subscription(any_exec);
|
memory_strategy_->get_next_subscription(any_exec, weak_nodes_);
|
||||||
if (any_exec->subscription || any_exec->subscription_intra_process) {
|
if (any_exec->subscription || any_exec->subscription_intra_process) {
|
||||||
return any_exec;
|
return any_exec;
|
||||||
}
|
}
|
||||||
// Check the services to see if there are any that are ready
|
// Check the services to see if there are any that are ready
|
||||||
get_next_service(any_exec);
|
memory_strategy_->get_next_service(any_exec, weak_nodes_);
|
||||||
if (any_exec->service) {
|
if (any_exec->service) {
|
||||||
return any_exec;
|
return any_exec;
|
||||||
}
|
}
|
||||||
// Check the clients to see if there are any that are ready
|
// Check the clients to see if there are any that are ready
|
||||||
get_next_client(any_exec);
|
memory_strategy_->get_next_client(any_exec, weak_nodes_);
|
||||||
if (any_exec->client) {
|
if (any_exec->client) {
|
||||||
return any_exec;
|
return any_exec;
|
||||||
}
|
}
|
||||||
|
@ -980,12 +1016,15 @@ private:
|
||||||
RCLCPP_DISABLE_COPY(Executor);
|
RCLCPP_DISABLE_COPY(Executor);
|
||||||
|
|
||||||
std::vector<std::weak_ptr<rclcpp::node::Node>> weak_nodes_;
|
std::vector<std::weak_ptr<rclcpp::node::Node>> weak_nodes_;
|
||||||
|
std::array<void*, 2> guard_cond_handles_;
|
||||||
|
/*
|
||||||
using SubscriberHandles = std::list<void *>;
|
using SubscriberHandles = std::list<void *>;
|
||||||
SubscriberHandles subscriber_handles_;
|
SubscriberHandles subscriber_handles_;
|
||||||
using ServiceHandles = std::list<void *>;
|
using ServiceHandles = std::list<void *>;
|
||||||
ServiceHandles service_handles_;
|
ServiceHandles service_handles_;
|
||||||
using ClientHandles = std::list<void *>;
|
using ClientHandles = std::list<void *>;
|
||||||
ClientHandles client_handles_;
|
ClientHandles client_handles_;
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* executor */
|
} /* executor */
|
||||||
|
|
|
@ -15,18 +15,27 @@
|
||||||
#ifndef RCLCPP_RCLCPP_MEMORY_STRATEGIES_HPP_
|
#ifndef RCLCPP_RCLCPP_MEMORY_STRATEGIES_HPP_
|
||||||
#define RCLCPP_RCLCPP_MEMORY_STRATEGIES_HPP_
|
#define RCLCPP_RCLCPP_MEMORY_STRATEGIES_HPP_
|
||||||
|
|
||||||
#include <rclcpp/strategies/heap_pool_memory_strategy.hpp>
|
//#include <rclcpp/strategies/heap_pool_memory_strategy.hpp>
|
||||||
#include <rclcpp/strategies/stack_pool_memory_strategy.hpp>
|
//#include <rclcpp/strategies/stack_pool_memory_strategy.hpp>
|
||||||
|
#include <rclcpp/strategies/allocator_memory_strategy.hpp>
|
||||||
|
|
||||||
namespace rclcpp
|
namespace rclcpp
|
||||||
{
|
{
|
||||||
namespace memory_strategies
|
namespace memory_strategies
|
||||||
{
|
{
|
||||||
|
|
||||||
using rclcpp::memory_strategies::heap_pool_memory_strategy::HeapPoolMemoryStrategy;
|
using rclcpp::memory_strategies::allocator_memory_strategy::AllocatorMemoryStrategy;
|
||||||
using rclcpp::memory_strategies::stack_pool_memory_strategy::StackPoolMemoryStrategy;
|
//using rclcpp::memory_strategies::heap_pool_memory_strategy::HeapPoolMemoryStrategy;
|
||||||
|
//using rclcpp::memory_strategies::stack_pool_memory_strategy::StackPoolMemoryStrategy;
|
||||||
|
|
||||||
} /* memory_strategies */
|
} /* memory_strategies */
|
||||||
|
|
||||||
|
namespace memory_strategy {
|
||||||
|
MemoryStrategy::SharedPtr create_default_strategy() {
|
||||||
|
return std::make_shared<memory_strategies::allocator_memory_strategy::AllocatorMemoryStrategy<>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* rclcpp */
|
} /* rclcpp */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,19 +14,17 @@
|
||||||
|
|
||||||
#ifndef RCLCPP_RCLCPP_MEMORY_STRATEGY_HPP_
|
#ifndef RCLCPP_RCLCPP_MEMORY_STRATEGY_HPP_
|
||||||
#define RCLCPP_RCLCPP_MEMORY_STRATEGY_HPP_
|
#define RCLCPP_RCLCPP_MEMORY_STRATEGY_HPP_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <rclcpp/any_executable.hpp>
|
#include <rclcpp/any_executable.hpp>
|
||||||
|
#include <rclcpp/macros.hpp>
|
||||||
|
#include <rclcpp/node.hpp>
|
||||||
|
|
||||||
namespace rclcpp
|
namespace rclcpp
|
||||||
{
|
{
|
||||||
|
|
||||||
// TODO move HandleType somewhere where it makes sense
|
|
||||||
enum class HandleType {subscription_handle, service_handle, client_handle, guard_condition_handle};
|
|
||||||
|
|
||||||
namespace executor
|
|
||||||
{
|
|
||||||
class Executor;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace memory_strategy
|
namespace memory_strategy
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -38,137 +36,43 @@ namespace memory_strategy
|
||||||
*/
|
*/
|
||||||
class MemoryStrategy
|
class MemoryStrategy
|
||||||
{
|
{
|
||||||
|
|
||||||
friend class executor::Executor;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RCLCPP_SMART_PTR_DEFINITIONS(MemoryStrategy);
|
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(MemoryStrategy);
|
||||||
|
using WeakNodeVector = std::vector<std::weak_ptr<rclcpp::node::Node>>>;
|
||||||
|
|
||||||
/// Borrow memory for storing data for subscriptions, services, clients, or guard conditions.
|
// return the new number of subscribers
|
||||||
/**
|
virtual size_t fill_subscriber_handles(void ** ptr) = 0;
|
||||||
* The default implementation stores std::vectors for each handle type and resizes the vectors
|
|
||||||
* as necessary based on the requested number of handles.
|
|
||||||
* \param[in] The type of entity that this function is requesting for.
|
|
||||||
* \param[in] The number of handles to borrow.
|
|
||||||
* \return Pointer to the allocated handles.
|
|
||||||
*/
|
|
||||||
virtual void ** borrow_handles(HandleType type, size_t number_of_handles)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case HandleType::subscription_handle:
|
|
||||||
if (subscription_handles.size() < number_of_handles) {
|
|
||||||
subscription_handles.resize(number_of_handles, 0);
|
|
||||||
}
|
|
||||||
return static_cast<void **>(subscription_handles.data());
|
|
||||||
case HandleType::service_handle:
|
|
||||||
if (service_handles.size() < number_of_handles) {
|
|
||||||
service_handles.resize(number_of_handles, 0);
|
|
||||||
}
|
|
||||||
return static_cast<void **>(service_handles.data());
|
|
||||||
case HandleType::client_handle:
|
|
||||||
if (client_handles.size() < number_of_handles) {
|
|
||||||
client_handles.resize(number_of_handles, 0);
|
|
||||||
}
|
|
||||||
return static_cast<void **>(client_handles.data());
|
|
||||||
case HandleType::guard_condition_handle:
|
|
||||||
if (number_of_handles > 2) {
|
|
||||||
throw std::runtime_error("Too many guard condition handles requested!");
|
|
||||||
}
|
|
||||||
return guard_cond_handles.data();
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Unknown HandleType " + std::to_string(static_cast<int>(type)) +
|
|
||||||
", could not borrow handle memory.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the memory borrowed in borrow_handles.
|
// return the new number of services
|
||||||
/**
|
virtual size_t fill_service_handles(void ** ptr) = 0;
|
||||||
* return_handles should always mirror the way memory was borrowed in borrow_handles.
|
|
||||||
* \param[in] The type of entity that this function is returning.
|
// return the new number of clients
|
||||||
* \param[in] Pointer to the handles returned.
|
virtual size_t fill_client_handles(void ** ptr) = 0;
|
||||||
*/
|
|
||||||
virtual void return_handles(HandleType type, void ** handles)
|
virtual void clear_active_entities() = 0;
|
||||||
{
|
|
||||||
switch (type) {
|
virtual void clear_handles() = 0;
|
||||||
case HandleType::subscription_handle:
|
virtual bool collect_entities(const WeakNodeVector & weak_nodes) = 0;
|
||||||
if (handles != subscription_handles.data()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"tried to return memory that isn't handled by this MemoryStrategy");
|
|
||||||
}
|
|
||||||
memset(handles, 0, subscription_handles.size());
|
|
||||||
break;
|
|
||||||
case HandleType::service_handle:
|
|
||||||
if (handles != service_handles.data()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"tried to return memory that isn't handled by this MemoryStrategy");
|
|
||||||
}
|
|
||||||
memset(handles, 0, service_handles.size());
|
|
||||||
break;
|
|
||||||
case HandleType::client_handle:
|
|
||||||
if (handles != client_handles.data()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"tried to return memory that isn't handled by this MemoryStrategy");
|
|
||||||
}
|
|
||||||
memset(handles, 0, client_handles.size());
|
|
||||||
break;
|
|
||||||
case HandleType::guard_condition_handle:
|
|
||||||
if (handles != guard_cond_handles.data()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"tried to return memory that isn't handled by this MemoryStrategy");
|
|
||||||
}
|
|
||||||
guard_cond_handles.fill(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Unknown HandleType " + std::to_string(static_cast<int>(type)) +
|
|
||||||
", could not borrow handle memory.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Provide a newly initialized AnyExecutable object.
|
/// Provide a newly initialized AnyExecutable object.
|
||||||
// \return Shared pointer to the fresh executable.
|
// \return Shared pointer to the fresh executable.
|
||||||
virtual executor::AnyExecutable::SharedPtr instantiate_next_executable()
|
virtual executor::AnyExecutable::SharedPtr instantiate_next_executable() = 0;
|
||||||
{
|
|
||||||
return std::make_shared<executor::AnyExecutable>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of a general-purpose allocation function.
|
virtual void
|
||||||
/**
|
get_next_subscription(executor::AnyExecutable::SharedPtr any_exec,
|
||||||
* \param[in] size Number of bytes to allocate.
|
const WeakNodeVector & weak_nodes) = 0;
|
||||||
* \return Pointer to the allocated chunk of memory.
|
|
||||||
*/
|
|
||||||
virtual void * alloc(size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return std::malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of a general-purpose free.
|
virtual void
|
||||||
/**
|
get_next_service(executor::AnyExecutable::SharedPtr any_exec,
|
||||||
* \param[in] Pointer to deallocate.
|
const WeakNodeVector & weak_nodes) = 0;
|
||||||
*/
|
|
||||||
virtual void free(void * ptr)
|
virtual void
|
||||||
{
|
get_next_client(executor::AnyExecutable::SharedPtr any_exec,
|
||||||
return std::free(ptr);
|
const WeakNodeVector & weak_nodes) = 0;
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<rclcpp::subscription::SubscriptionBase::SharedPtr> subs;
|
|
||||||
std::vector<rclcpp::service::ServiceBase::SharedPtr> services;
|
|
||||||
std::vector<rclcpp::client::ClientBase::SharedPtr> clients;
|
|
||||||
|
|
||||||
std::vector<void *> subscription_handles;
|
|
||||||
std::vector<void *> service_handles;
|
|
||||||
std::vector<void *> client_handles;
|
|
||||||
std::array<void *, 2> guard_cond_handles;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MemoryStrategy::SharedPtr create_default_strategy()
|
|
||||||
{
|
|
||||||
return std::make_shared<MemoryStrategy>(MemoryStrategy());
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* memory_strategy */
|
} /* memory_strategy */
|
||||||
|
|
||||||
} /* rclcpp */
|
} /* rclcpp */
|
||||||
|
|
|
@ -15,13 +15,15 @@
|
||||||
#ifndef RCLCPP_RCLCPP_ALLOCATOR_MEMORY_STRATEGY_HPP_
|
#ifndef RCLCPP_RCLCPP_ALLOCATOR_MEMORY_STRATEGY_HPP_
|
||||||
#define RCLCPP_RCLCPP_ALLOCATOR_MEMORY_STRATEGY_HPP_
|
#define RCLCPP_RCLCPP_ALLOCATOR_MEMORY_STRATEGY_HPP_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <rclcpp/allocator/allocator_common.hpp>
|
#include <rclcpp/allocator/allocator_common.hpp>
|
||||||
#include <rclcpp/memory_strategy.hpp>
|
#include <rclcpp/memory_strategy.hpp>
|
||||||
|
|
||||||
namespace rclcpp
|
namespace rclcpp
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
namespace memory_strategies
|
namespace memory_strategies
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -34,13 +36,16 @@ namespace allocator_memory_strategy
|
||||||
* the rmw implementation after the executor waits for work, based on the number of entities that
|
* the rmw implementation after the executor waits for work, based on the number of entities that
|
||||||
* come through.
|
* come through.
|
||||||
*/
|
*/
|
||||||
template<typename Alloc>
|
template<typename Alloc = std::allocator<void>>
|
||||||
class AllocatorMemoryStrategy : public memory_strategy::MemoryStrategy
|
class AllocatorMemoryStrategy : public memory_strategy::MemoryStrategy
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RCLCPP_SMART_PTR_DEFINITIONS(AllocatorMemoryStrategy<Alloc>);
|
RCLCPP_SMART_PTR_DEFINITIONS(AllocatorMemoryStrategy<Alloc>);
|
||||||
|
|
||||||
|
using WeakNode = std::weak_ptr<rclcpp::node::Node>>;
|
||||||
|
using NodeVector = std::vector<WeakNode>;
|
||||||
|
|
||||||
using ExecAllocTraits = allocator::AllocRebind<executor::AnyExecutable, Alloc>;
|
using ExecAllocTraits = allocator::AllocRebind<executor::AnyExecutable, Alloc>;
|
||||||
using ExecAlloc = typename ExecAllocTraits::allocator_type;
|
using ExecAlloc = typename ExecAllocTraits::allocator_type;
|
||||||
using ExecDeleter = allocator::Deleter<ExecAlloc, executor::AnyExecutable>;
|
using ExecDeleter = allocator::Deleter<ExecAlloc, executor::AnyExecutable>;
|
||||||
|
@ -53,139 +58,415 @@ public:
|
||||||
allocator_ = std::make_shared<VoidAlloc>(*allocator.get());
|
allocator_ = std::make_shared<VoidAlloc>(*allocator.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow memory for storing data for subscriptions, services, clients, or guard conditions.
|
AllocatorMemoryStrategy()
|
||||||
/**
|
|
||||||
* The default implementation stores std::vectors for each handle type and resizes the vectors
|
|
||||||
* as necessary based on the requested number of handles.
|
|
||||||
* \param[in] The type of entity that this function is requesting for.
|
|
||||||
* \param[in] The number of handles to borrow.
|
|
||||||
* \return Pointer to the allocated handles.
|
|
||||||
*/
|
|
||||||
virtual void ** borrow_handles(HandleType type, size_t number_of_handles)
|
|
||||||
{
|
{
|
||||||
switch (type) {
|
executable_allocator_ = std::make_shared<ExecAlloc>();
|
||||||
case HandleType::subscription_handle:
|
allocator_ = std::make_shared<VoidAlloc>();
|
||||||
if (subscription_handles.size() < number_of_handles) {
|
|
||||||
subscription_handles.resize(number_of_handles, 0);
|
|
||||||
}
|
|
||||||
return static_cast<void **>(subscription_handles.data());
|
|
||||||
case HandleType::service_handle:
|
|
||||||
if (service_handles.size() < number_of_handles) {
|
|
||||||
service_handles.resize(number_of_handles, 0);
|
|
||||||
}
|
|
||||||
return static_cast<void **>(service_handles.data());
|
|
||||||
case HandleType::client_handle:
|
|
||||||
if (client_handles.size() < number_of_handles) {
|
|
||||||
client_handles.resize(number_of_handles, 0);
|
|
||||||
}
|
|
||||||
return static_cast<void **>(client_handles.data());
|
|
||||||
case HandleType::guard_condition_handle:
|
|
||||||
if (number_of_handles > 2) {
|
|
||||||
throw std::runtime_error("Too many guard condition handles requested!");
|
|
||||||
}
|
|
||||||
return guard_cond_handles.data();
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Unknown HandleType " + std::to_string(static_cast<int>(type)) +
|
|
||||||
", could not borrow handle memory.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the memory borrowed in borrow_handles.
|
size_t fill_subscriber_handles(void ** ptr) {
|
||||||
/**
|
size_t max_size = subscriptions_.size();
|
||||||
* return_handles should always mirror the way memory was borrowed in borrow_handles.
|
if (subscriber_handles_.size() < max_size) {
|
||||||
* \param[in] The type of entity that this function is returning.
|
subscriber_handles_.resize(max_size);
|
||||||
* \param[in] Pointer to the handles returned.
|
|
||||||
*/
|
|
||||||
virtual void return_handles(HandleType type, void ** handles)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case HandleType::subscription_handle:
|
|
||||||
if (handles != subscription_handles.data()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"tried to return memory that isn't handled by this AllocatorMemoryStrategy");
|
|
||||||
}
|
|
||||||
memset(handles, 0, subscription_handles.size());
|
|
||||||
break;
|
|
||||||
case HandleType::service_handle:
|
|
||||||
if (handles != service_handles.data()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"tried to return memory that isn't handled by this AllocatorMemoryStrategy");
|
|
||||||
}
|
|
||||||
memset(handles, 0, service_handles.size());
|
|
||||||
break;
|
|
||||||
case HandleType::client_handle:
|
|
||||||
if (handles != client_handles.data()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"tried to return memory that isn't handled by this AllocatorMemoryStrategy");
|
|
||||||
}
|
|
||||||
memset(handles, 0, client_handles.size());
|
|
||||||
break;
|
|
||||||
case HandleType::guard_condition_handle:
|
|
||||||
if (handles != guard_cond_handles.data()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"tried to return memory that isn't handled by this AllocatorMemoryStrategy");
|
|
||||||
}
|
|
||||||
guard_cond_handles.fill(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Unknown HandleType " + std::to_string(static_cast<int>(type)) +
|
|
||||||
", could not borrow handle memory.");
|
|
||||||
}
|
}
|
||||||
|
size_t count = 0;
|
||||||
|
for (auto & subscription : subscriptions_) {
|
||||||
|
subscriber_handles_[count++] = subscription->get_subscription_handle()->data;
|
||||||
|
if (subscription->get_intra_process_subscription_handle()) {
|
||||||
|
subscriber_handles_[count++] =
|
||||||
|
subscription->get_intra_process_subscription_handle()->data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr = static_cast<void**>(subscriber_handles_.data());
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return the new number of services
|
||||||
|
size_t fill_service_handles(void ** ptr) {
|
||||||
|
size_t max_size = services_.size();
|
||||||
|
if (service_handles_.size() < max_size) {
|
||||||
|
service_handles_.resize(max_size);
|
||||||
|
}
|
||||||
|
size_t count = 0;
|
||||||
|
for (auto & service : services_) {
|
||||||
|
service_handles_[count++] = service->get_service_handle()->data;
|
||||||
|
}
|
||||||
|
ptr = static_cast<void**>(service_handles_.data());
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the new number of clients
|
||||||
|
size_t fill_client_handles(void ** ptr) {
|
||||||
|
size_t max_size = clients_.size();
|
||||||
|
if (client_handles_.size() < max_size) {
|
||||||
|
client_handles_.resize(max_size);
|
||||||
|
}
|
||||||
|
size_t count = 0;
|
||||||
|
for (auto & client : clients_) {
|
||||||
|
client_handles_[count++] = client->get_client_handle()->data;
|
||||||
|
}
|
||||||
|
ptr = static_cast<void**>(client_handles_.data());
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_active_entities() {
|
||||||
|
subscriptions_.clear();
|
||||||
|
services_.clear();
|
||||||
|
clients_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_handles() {
|
||||||
|
subscriber_handles_.clear();
|
||||||
|
service_handles_.clear();
|
||||||
|
client_handles_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool collect_entities(const NodeVector & weak_nodes) {
|
||||||
|
bool has_invalid_weak_nodes = false;
|
||||||
|
for (auto & weak_node : weak_nodes) {
|
||||||
|
auto node = weak_node.lock();
|
||||||
|
if (!node) {
|
||||||
|
has_invalid_weak_nodes = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_group : node->get_callback_groups()) {
|
||||||
|
auto group = weak_group.lock();
|
||||||
|
if (!group || !group->can_be_taken_from().load()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_subscription : group->get_subscription_ptrs()) {
|
||||||
|
auto subscription = weak_subscription.lock();
|
||||||
|
if (subscription) {
|
||||||
|
subscriptions_.push_back(subscription);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto & service : group->get_service_ptrs()) {
|
||||||
|
services_.push_back(service);
|
||||||
|
}
|
||||||
|
for (auto & client : group->get_client_ptrs()) {
|
||||||
|
clients_.push_back(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return has_invalid_weak_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Provide a newly initialized AnyExecutable object.
|
/// Provide a newly initialized AnyExecutable object.
|
||||||
// \return Shared pointer to the fresh executable.
|
// \return Shared pointer to the fresh executable.
|
||||||
virtual executor::AnyExecutable::SharedPtr instantiate_next_executable()
|
executor::AnyExecutable::SharedPtr instantiate_next_executable()
|
||||||
{
|
{
|
||||||
return std::allocate_shared<executor::AnyExecutable>(*executable_allocator_.get());
|
return std::allocate_shared<executor::AnyExecutable>(*executable_allocator_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of a general-purpose allocation function.
|
static rclcpp::subscription::SubscriptionBase::SharedPtr
|
||||||
/**
|
get_subscription_by_handle(void * subscriber_handle,
|
||||||
* \param[in] size Number of bytes to allocate.
|
const NodeVector & weak_nodes)
|
||||||
* \return Pointer to the allocated chunk of memory.
|
|
||||||
*/
|
|
||||||
virtual void * alloc(size_t size)
|
|
||||||
{
|
{
|
||||||
if (size == 0) {
|
for (auto & weak_node : weak_nodes) {
|
||||||
return NULL;
|
auto node = weak_node.lock();
|
||||||
|
if (!node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_group : node->get_callback_groups()) {
|
||||||
|
auto group = weak_group.lock();
|
||||||
|
if (!group) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_subscription : group->get_subscription_ptrs()) {
|
||||||
|
auto subscription = weak_subscription.lock();
|
||||||
|
if (subscription) {
|
||||||
|
if (subscription->get_subscription_handle()->data == subscriber_handle) {
|
||||||
|
return subscription;
|
||||||
|
}
|
||||||
|
if (subscription->get_intra_process_subscription_handle() &&
|
||||||
|
subscription->get_intra_process_subscription_handle()->data == subscriber_handle)
|
||||||
|
{
|
||||||
|
return subscription;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto ptr = VoidAllocTraits::allocate(*allocator_.get(), size);
|
return nullptr;
|
||||||
alloc_map[ptr] = size;
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of a general-purpose free.
|
static rclcpp::service::ServiceBase::SharedPtr
|
||||||
/**
|
get_service_by_handle(void * service_handle,
|
||||||
* \param[in] Pointer to deallocate.
|
const NodeVector & weak_nodes)
|
||||||
*/
|
|
||||||
virtual void free(void * ptr)
|
|
||||||
{
|
{
|
||||||
if (alloc_map.count(ptr) == 0) {
|
for (auto & weak_node : weak_nodes) {
|
||||||
// do nothing, the pointer is not in the alloc'd map
|
auto node = weak_node.lock();
|
||||||
return;
|
if (!node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_group : node->get_callback_groups()) {
|
||||||
|
auto group = weak_group.lock();
|
||||||
|
if (!group) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & service : group->get_service_ptrs()) {
|
||||||
|
if (service->get_service_handle()->data == service_handle) {
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
VoidAllocTraits::deallocate(*allocator_.get(), &ptr, alloc_map[ptr]);
|
return rclcpp::service::ServiceBase::SharedPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rclcpp::client::ClientBase::SharedPtr
|
||||||
|
get_client_by_handle(void * client_handle,
|
||||||
|
const NodeVector & weak_nodes)
|
||||||
|
{
|
||||||
|
for (auto & weak_node : weak_nodes) {
|
||||||
|
auto node = weak_node.lock();
|
||||||
|
if (!node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_group : node->get_callback_groups()) {
|
||||||
|
auto group = weak_group.lock();
|
||||||
|
if (!group) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & client : group->get_client_ptrs()) {
|
||||||
|
if (client->get_client_handle()->data == client_handle) {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rclcpp::client::ClientBase::SharedPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
static rclcpp::node::Node::SharedPtr
|
||||||
|
get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||||
|
const NodeVector & weak_nodes)
|
||||||
|
{
|
||||||
|
if (!group) {
|
||||||
|
return rclcpp::node::Node::SharedPtr();
|
||||||
|
}
|
||||||
|
for (auto & weak_node : weak_nodes) {
|
||||||
|
auto node = weak_node.lock();
|
||||||
|
if (!node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_group : node->get_callback_groups()) {
|
||||||
|
auto callback_group = weak_group.lock();
|
||||||
|
if (callback_group == group) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rclcpp::node::Node::SharedPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||||
|
get_group_by_subscription(
|
||||||
|
rclcpp::subscription::SubscriptionBase::SharedPtr subscription,
|
||||||
|
const NodeVector & weak_nodes)
|
||||||
|
{
|
||||||
|
for (auto & weak_node : weak_nodes) {
|
||||||
|
auto node = weak_node.lock();
|
||||||
|
if (!node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_group : node->get_callback_groups()) {
|
||||||
|
auto group = weak_group.lock();
|
||||||
|
if (!group) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_sub : group->get_subscription_ptrs()) {
|
||||||
|
auto sub = weak_sub.lock();
|
||||||
|
if (sub == subscription) {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rclcpp::callback_group::CallbackGroup::SharedPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
get_next_subscription(executor::AnyExecutable::SharedPtr any_exec,
|
||||||
|
const NodeVector & weak_nodes)
|
||||||
|
{
|
||||||
|
auto it = subscriber_handles_.begin();
|
||||||
|
while (it != subscriber_handles_.end()) {
|
||||||
|
auto subscription = get_subscription_by_handle(*it, weak_nodes);
|
||||||
|
if (subscription) {
|
||||||
|
// Figure out if this is for intra-process or not.
|
||||||
|
bool is_intra_process = false;
|
||||||
|
if (subscription->get_intra_process_subscription_handle()) {
|
||||||
|
is_intra_process = subscription->get_intra_process_subscription_handle()->data == *it;
|
||||||
|
}
|
||||||
|
// Find the group for this handle and see if it can be serviced
|
||||||
|
auto group = get_group_by_subscription(subscription, weak_nodes);
|
||||||
|
if (!group) {
|
||||||
|
// Group was not found, meaning the subscription is not valid...
|
||||||
|
// Remove it from the ready list and continue looking
|
||||||
|
subscriber_handles_.erase(it++);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!group->can_be_taken_from().load()) {
|
||||||
|
// Group is mutually exclusive and is being used, so skip it for now
|
||||||
|
// Leave it to be checked next time, but continue searching
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Otherwise it is safe to set and return the any_exec
|
||||||
|
if (is_intra_process) {
|
||||||
|
any_exec->subscription_intra_process = subscription;
|
||||||
|
} else {
|
||||||
|
any_exec->subscription = subscription;
|
||||||
|
}
|
||||||
|
any_exec->callback_group = group;
|
||||||
|
any_exec->node = get_node_by_group(group, weak_nodes);
|
||||||
|
subscriber_handles_.erase(it++);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Else, the subscription is no longer valid, remove it and continue
|
||||||
|
subscriber_handles_.erase(it++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||||
|
get_group_by_service(
|
||||||
|
rclcpp::service::ServiceBase::SharedPtr service,
|
||||||
|
const NodeVector & weak_nodes)
|
||||||
|
{
|
||||||
|
for (auto & weak_node : weak_nodes) {
|
||||||
|
auto node = weak_node.lock();
|
||||||
|
if (!node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_group : node->get_callback_groups()) {
|
||||||
|
auto group = weak_group.lock();
|
||||||
|
if (!group) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & serv : group->get_service_ptrs()) {
|
||||||
|
if (serv == service) {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rclcpp::callback_group::CallbackGroup::SharedPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
get_next_service(executor::AnyExecutable::SharedPtr any_exec,
|
||||||
|
const NodeVector & weak_nodes)
|
||||||
|
{
|
||||||
|
auto it = service_handles_.begin();
|
||||||
|
while (it != service_handles_.end()) {
|
||||||
|
auto service = get_service_by_handle(*it, weak_nodes);
|
||||||
|
if (service) {
|
||||||
|
// Find the group for this handle and see if it can be serviced
|
||||||
|
auto group = get_group_by_service(service, weak_nodes);
|
||||||
|
if (!group) {
|
||||||
|
// Group was not found, meaning the service is not valid...
|
||||||
|
// Remove it from the ready list and continue looking
|
||||||
|
service_handles_.erase(it++);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!group->can_be_taken_from().load()) {
|
||||||
|
// Group is mutually exclusive and is being used, so skip it for now
|
||||||
|
// Leave it to be checked next time, but continue searching
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Otherwise it is safe to set and return the any_exec
|
||||||
|
any_exec->service = service;
|
||||||
|
any_exec->callback_group = group;
|
||||||
|
any_exec->node = get_node_by_group(group, weak_nodes);
|
||||||
|
service_handles_.erase(it++);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Else, the service is no longer valid, remove it and continue
|
||||||
|
service_handles_.erase(it++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||||
|
get_group_by_client(
|
||||||
|
rclcpp::client::ClientBase::SharedPtr client,
|
||||||
|
const NodeVector & weak_nodes)
|
||||||
|
{
|
||||||
|
for (auto & weak_node : weak_nodes) {
|
||||||
|
auto node = weak_node.lock();
|
||||||
|
if (!node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & weak_group : node->get_callback_groups()) {
|
||||||
|
auto group = weak_group.lock();
|
||||||
|
if (!group) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto & cli : group->get_client_ptrs()) {
|
||||||
|
if (cli == client) {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rclcpp::callback_group::CallbackGroup::SharedPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
get_next_client(executor::AnyExecutable::SharedPtr any_exec,
|
||||||
|
const NodeVector & weak_nodes)
|
||||||
|
{
|
||||||
|
auto it = client_handles_.begin();
|
||||||
|
while (it != client_handles_.end()) {
|
||||||
|
auto client = get_client_by_handle(*it, weak_nodes);
|
||||||
|
if (client) {
|
||||||
|
// Find the group for this handle and see if it can be serviced
|
||||||
|
auto group = get_group_by_client(client, weak_nodes);
|
||||||
|
if (!group) {
|
||||||
|
// Group was not found, meaning the service is not valid...
|
||||||
|
// Remove it from the ready list and continue looking
|
||||||
|
client_handles_.erase(it++);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!group->can_be_taken_from().load()) {
|
||||||
|
// Group is mutually exclusive and is being used, so skip it for now
|
||||||
|
// Leave it to be checked next time, but continue searching
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Otherwise it is safe to set and return the any_exec
|
||||||
|
any_exec->client = client;
|
||||||
|
any_exec->callback_group = group;
|
||||||
|
any_exec->node = get_node_by_group(group, weak_nodes);
|
||||||
|
client_handles_.erase(it++);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Else, the service is no longer valid, remove it and continue
|
||||||
|
client_handles_.erase(it++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
template<typename U>
|
template<typename U>
|
||||||
using VectorRebind = typename std::allocator_traits<Alloc>::template rebind_alloc<U>;
|
using VectorRebind = typename std::allocator_traits<Alloc>::template rebind_alloc<U>;
|
||||||
|
|
||||||
std::vector<rclcpp::subscription::SubscriptionBase::SharedPtr,
|
std::vector<rclcpp::subscription::SubscriptionBase::SharedPtr,
|
||||||
VectorRebind<rclcpp::subscription::SubscriptionBase::SharedPtr>> subs;
|
VectorRebind<rclcpp::subscription::SubscriptionBase::SharedPtr>> subscriptions_;
|
||||||
std::vector<rclcpp::service::ServiceBase::SharedPtr,
|
std::vector<rclcpp::service::ServiceBase::SharedPtr,
|
||||||
VectorRebind<rclcpp::service::ServiceBase::SharedPtr>> services;
|
VectorRebind<rclcpp::service::ServiceBase::SharedPtr>> services_;
|
||||||
std::vector<rclcpp::client::ClientBase::SharedPtr,
|
std::vector<rclcpp::client::ClientBase::SharedPtr,
|
||||||
VectorRebind<rclcpp::client::ClientBase::SharedPtr>> clients;
|
VectorRebind<rclcpp::client::ClientBase::SharedPtr>> clients_;
|
||||||
|
|
||||||
std::vector<void *, VoidAlloc> subscription_handles;
|
std::vector<void *, VoidAlloc> subscriber_handles_;
|
||||||
std::vector<void *, VoidAlloc> service_handles;
|
std::vector<void *, VoidAlloc> service_handles_;
|
||||||
std::vector<void *, VoidAlloc> client_handles;
|
std::vector<void *, VoidAlloc> client_handles_;
|
||||||
std::array<void *, 2> guard_cond_handles;
|
|
||||||
|
|
||||||
std::unordered_map<void *, size_t> alloc_map;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<ExecAlloc> executable_allocator_;
|
std::shared_ptr<ExecAlloc> executable_allocator_;
|
||||||
std::shared_ptr<VoidAlloc> allocator_;
|
std::shared_ptr<VoidAlloc> allocator_;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue