15 #ifndef RCLCPP__STRATEGIES__ALLOCATOR_MEMORY_STRATEGY_HPP_
16 #define RCLCPP__STRATEGIES__ALLOCATOR_MEMORY_STRATEGY_HPP_
23 #include "rclcpp/allocator/allocator_common.hpp"
24 #include "rclcpp/detail/add_guard_condition_to_rcl_wait_set.hpp"
25 #include "rclcpp/memory_strategy.hpp"
26 #include "rclcpp/node.hpp"
27 #include "rclcpp/visibility_control.hpp"
29 #include "rcutils/logging_macros.h"
31 #include "rmw/types.h"
35 namespace memory_strategies
37 namespace allocator_memory_strategy
48 template<
typename Alloc = std::allocator<
void>>
55 using VoidAllocTraits =
typename allocator::AllocRebind<void *, Alloc>;
56 using VoidAlloc =
typename VoidAllocTraits::allocator_type;
60 allocator_ = std::make_shared<VoidAlloc>(*allocator.get());
65 allocator_ = std::make_shared<VoidAlloc>();
70 for (
const auto & existing_guard_condition : guard_conditions_) {
71 if (existing_guard_condition == &guard_condition) {
75 guard_conditions_.push_back(&guard_condition);
80 for (
auto it = guard_conditions_.begin(); it != guard_conditions_.end(); ++it) {
81 if (*it == guard_condition) {
82 guard_conditions_.erase(it);
88 void clear_handles()
override
90 subscription_handles_.clear();
91 service_handles_.clear();
92 client_handles_.clear();
93 timer_handles_.clear();
94 waitable_handles_.clear();
107 size_t valid_subscription_count = 0;
108 for (
size_t i = 0; i < subscription_handles_.size(); ++i) {
109 if (valid_subscription_count < wait_set->size_of_subscriptions &&
112 subscription_handles_[i] = std::weak_ptr<const rcl_subscription_t>{};
114 if (subscription_handles_[i].lock()) {
115 ++valid_subscription_count;
119 size_t valid_service_count = 0;
120 for (
size_t i = 0; i < service_handles_.size(); ++i) {
121 if (valid_service_count < wait_set->size_of_services &&
122 !wait_set->
services[valid_service_count])
124 service_handles_[i] = std::weak_ptr<const rcl_service_t>{};
126 if (service_handles_[i].lock()) {
127 ++valid_service_count;
131 size_t valid_client_count = 0;
132 for (
size_t i = 0; i < client_handles_.size(); ++i) {
133 if (valid_client_count < wait_set->size_of_clients &&
134 !wait_set->
clients[valid_client_count])
136 client_handles_[i] = std::weak_ptr<const rcl_client_t>{};
138 if (client_handles_[i].lock()) {
139 ++valid_client_count;
143 size_t valid_timer_count = 0;
144 for (
size_t i = 0; i < timer_handles_.size(); ++i) {
145 if (valid_timer_count < wait_set->size_of_timers &&
146 !wait_set->
timers[valid_timer_count])
148 timer_handles_[i] = std::weak_ptr<const rcl_timer_t>{};
150 if (timer_handles_[i].lock()) {
155 for (
size_t i = 0; i < waitable_handles_.size(); ++i) {
156 if (!waitable_handles_[i]->is_ready(*wait_set)) {
157 waitable_handles_[i].reset();
162 subscription_handles_.erase(
163 std::remove_if(subscription_handles_.begin(), subscription_handles_.end(),
164 [](
const std::weak_ptr<const rcl_subscription_t> & weak_ptr) {
165 return weak_ptr.expired();
167 subscription_handles_.end()
170 service_handles_.erase(
171 std::remove_if(service_handles_.begin(), service_handles_.end(),
172 [](
const std::weak_ptr<const rcl_service_t> & weak_ptr) {
173 return weak_ptr.expired();
175 service_handles_.end()
178 client_handles_.erase(
179 std::remove_if(client_handles_.begin(), client_handles_.end(),
180 [](
const std::weak_ptr<const rcl_client_t> & weak_ptr) {
181 return weak_ptr.expired();
183 client_handles_.end()
186 timer_handles_.erase(
187 std::remove_if(timer_handles_.begin(), timer_handles_.end(),
188 [](
const std::weak_ptr<const rcl_timer_t> & weak_ptr) {
189 return weak_ptr.expired();
194 waitable_handles_.erase(
195 std::remove(waitable_handles_.begin(), waitable_handles_.end(),
nullptr),
196 waitable_handles_.end()
200 bool collect_entities(
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes)
override
202 bool has_invalid_weak_groups_or_nodes =
false;
203 for (
const auto & pair : weak_groups_to_nodes) {
204 auto group = pair.first.lock();
205 auto node = pair.second.lock();
206 if (group ==
nullptr || node ==
nullptr) {
207 has_invalid_weak_groups_or_nodes =
true;
210 if (!group || !group->can_be_taken_from().load()) {
214 group->collect_all_ptrs(
215 [
this](
const rclcpp::SubscriptionBase::SharedPtr & subscription) {
216 subscription_handles_.push_back(subscription->get_subscription_handle());
218 [
this](
const rclcpp::ServiceBase::SharedPtr & service) {
219 service_handles_.push_back(service->get_service_handle());
221 [
this](
const rclcpp::ClientBase::SharedPtr & client) {
222 client_handles_.push_back(client->get_client_handle());
224 [
this](
const rclcpp::TimerBase::SharedPtr & timer) {
225 timer_handles_.push_back(timer->get_timer_handle());
227 [
this](
const rclcpp::Waitable::SharedPtr & waitable) {
228 waitable_handles_.push_back(waitable);
232 return has_invalid_weak_groups_or_nodes;
235 void add_waitable_handle(
const rclcpp::Waitable::SharedPtr & waitable)
override
237 if (
nullptr == waitable) {
238 throw std::runtime_error(
"waitable object unexpectedly nullptr");
240 waitable_handles_.push_back(waitable);
245 for (
const std::weak_ptr<const rcl_subscription_t> & weak_subscription :
246 subscription_handles_)
248 auto subscription = weak_subscription.lock();
253 RCUTILS_LOG_ERROR_NAMED(
255 "Couldn't add subscription to wait set: %s", rcl_get_error_string().str);
261 for (
const std::weak_ptr<const rcl_client_t> & weak_client : client_handles_) {
262 auto client = weak_client.lock();
267 RCUTILS_LOG_ERROR_NAMED(
269 "Couldn't add client to wait set: %s", rcl_get_error_string().str);
275 for (
const std::weak_ptr<const rcl_service_t> & weak_service : service_handles_) {
276 auto service = weak_service.lock();
281 RCUTILS_LOG_ERROR_NAMED(
283 "Couldn't add service to wait set: %s", rcl_get_error_string().str);
289 for (
const std::weak_ptr<const rcl_timer_t> & weak_timer : timer_handles_) {
290 auto timer = weak_timer.lock();
295 RCUTILS_LOG_ERROR_NAMED(
297 "Couldn't add timer to wait set: %s", rcl_get_error_string().str);
303 for (
auto guard_condition : guard_conditions_) {
304 detail::add_guard_condition_to_rcl_wait_set(*wait_set, *guard_condition);
307 for (
const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
308 waitable->add_to_wait_set(*wait_set);
314 get_next_subscription(
316 const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes)
override
318 auto it = subscription_handles_.begin();
319 while (it != subscription_handles_.end()) {
320 auto subscription_handle = it->lock();
321 if (!subscription_handle) {
323 it = subscription_handles_.erase(it);
326 auto subscription = get_subscription_by_handle(subscription_handle, weak_groups_to_nodes);
329 auto group = get_group_by_subscription(subscription, weak_groups_to_nodes);
333 it = subscription_handles_.erase(it);
336 if (!group->can_be_taken_from().load()) {
343 any_exec.subscription = subscription;
344 any_exec.callback_group = group;
345 any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
346 subscription_handles_.erase(it);
350 it = subscription_handles_.erase(it);
357 const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes)
override
359 auto it = service_handles_.begin();
360 while (it != service_handles_.end()) {
361 auto service_handle = it->lock();
362 if (!service_handle) {
364 it = service_handles_.erase(it);
367 auto service = get_service_by_handle(service_handle, weak_groups_to_nodes);
370 auto group = get_group_by_service(service, weak_groups_to_nodes);
374 it = service_handles_.erase(it);
377 if (!group->can_be_taken_from().load()) {
384 any_exec.service = service;
385 any_exec.callback_group = group;
386 any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
387 service_handles_.erase(it);
391 it = service_handles_.erase(it);
398 const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes)
override
400 auto it = client_handles_.begin();
401 while (it != client_handles_.end()) {
402 auto client_handle = it->lock();
403 if (!client_handle) {
405 it = client_handles_.erase(it);
408 auto client = get_client_by_handle(client_handle, weak_groups_to_nodes);
411 auto group = get_group_by_client(client, weak_groups_to_nodes);
415 it = client_handles_.erase(it);
418 if (!group->can_be_taken_from().load()) {
425 any_exec.client = client;
426 any_exec.callback_group = group;
427 any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
428 client_handles_.erase(it);
432 it = client_handles_.erase(it);
439 const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes)
override
441 auto it = timer_handles_.begin();
442 while (it != timer_handles_.end()) {
443 auto timer_handle = it->lock();
446 it = timer_handles_.erase(it);
449 auto timer = get_timer_by_handle(timer_handle, weak_groups_to_nodes);
452 auto group = get_group_by_timer(timer, weak_groups_to_nodes);
456 it = timer_handles_.erase(it);
459 if (!group->can_be_taken_from().load()) {
465 auto data = timer->call();
472 any_exec.timer = timer;
473 any_exec.callback_group = group;
474 any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
475 any_exec.data = data;
476 timer_handles_.erase(it);
480 it = timer_handles_.erase(it);
487 const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes)
override
489 auto it = waitable_handles_.begin();
490 while (it != waitable_handles_.end()) {
491 std::shared_ptr<Waitable> & waitable = *it;
494 auto group = get_group_by_waitable(waitable, weak_groups_to_nodes);
498 it = waitable_handles_.erase(it);
501 if (!group->can_be_taken_from().load()) {
508 any_exec.waitable = waitable;
509 any_exec.callback_group = group;
510 any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
511 waitable_handles_.erase(it);
515 it = waitable_handles_.erase(it);
521 if constexpr (std::is_same_v<Alloc, std::allocator<void>>) {
524 return rclcpp::allocator::get_rcl_allocator<void *, VoidAlloc>(*allocator_.get());
528 size_t number_of_ready_subscriptions()
const override
530 size_t number_of_subscriptions = 0;
532 for (
const auto & weak_subscription : subscription_handles_) {
533 if (!weak_subscription.expired()) {
534 ++number_of_subscriptions;
537 for (
const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
538 number_of_subscriptions += waitable->get_number_of_ready_subscriptions();
540 return number_of_subscriptions;
543 size_t number_of_ready_services()
const override
545 size_t number_of_services = 0;
547 for (
const auto & weak_service : service_handles_) {
548 if (!weak_service.expired()) {
549 ++number_of_services;
552 for (
const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
553 number_of_services += waitable->get_number_of_ready_services();
555 return number_of_services;
558 size_t number_of_ready_events()
const override
560 size_t number_of_events = 0;
561 for (
const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
562 number_of_events += waitable->get_number_of_ready_events();
564 return number_of_events;
567 size_t number_of_ready_clients()
const override
569 size_t number_of_clients = 0;
571 for (
const auto & weak_client : client_handles_) {
572 if (!weak_client.expired()) {
576 for (
const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
577 number_of_clients += waitable->get_number_of_ready_clients();
579 return number_of_clients;
582 size_t number_of_guard_conditions()
const override
584 size_t number_of_guard_conditions = guard_conditions_.size();
585 for (
const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
586 number_of_guard_conditions += waitable->get_number_of_ready_guard_conditions();
588 return number_of_guard_conditions;
591 size_t number_of_ready_timers()
const override
593 size_t number_of_timers = 0;
595 for (
const auto & weak_timer : timer_handles_) {
596 if (!weak_timer.expired()) {
600 for (
const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
601 number_of_timers += waitable->get_number_of_ready_timers();
603 return number_of_timers;
606 size_t number_of_waitables()
const override
608 return waitable_handles_.size();
614 std::vector<T, typename std::allocator_traits<Alloc>::template rebind_alloc<T>>;
616 VectorRebind<const rclcpp::GuardCondition *> guard_conditions_;
618 VectorRebind<std::weak_ptr<const rcl_subscription_t>> subscription_handles_;
619 VectorRebind<std::weak_ptr<const rcl_service_t>> service_handles_;
620 VectorRebind<std::weak_ptr<const rcl_client_t>> client_handles_;
621 VectorRebind<std::weak_ptr<const rcl_timer_t>> timer_handles_;
622 VectorRebind<std::shared_ptr<Waitable>> waitable_handles_;
624 std::shared_ptr<VoidAlloc> allocator_;
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
A condition that can be waited on in a single wait set and asynchronously triggered.
Delegate for handling memory allocations while the Executor is executing.
Delegate for handling memory allocations while the Executor is executing.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
Container for subscription's, guard condition's, etc to be waited on.
const rcl_timer_t ** timers
Storage for timer pointers.
const rcl_service_t ** services
Storage for service pointers.
const rcl_client_t ** clients
Storage for client pointers.
const rcl_subscription_t ** subscriptions
Storage for subscription pointers.
#define RCL_RET_OK
Success return code.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_add_subscription(rcl_wait_set_t *wait_set, const rcl_subscription_t *subscription, size_t *index)
Store a pointer to the given subscription in the next empty spot in the set.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_add_service(rcl_wait_set_t *wait_set, const rcl_service_t *service, size_t *index)
Store a pointer to the service in the next empty spot in the set.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_add_timer(rcl_wait_set_t *wait_set, const rcl_timer_t *timer, size_t *index)
Store a pointer to the timer in the next empty spot in the set.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_add_client(rcl_wait_set_t *wait_set, const rcl_client_t *client, size_t *index)
Store a pointer to the client in the next empty spot in the set.