15 #ifndef RCLCPP__WAIT_SET_POLICIES__DYNAMIC_STORAGE_HPP_
16 #define RCLCPP__WAIT_SET_POLICIES__DYNAMIC_STORAGE_HPP_
23 #include "rclcpp/client.hpp"
24 #include "rclcpp/guard_condition.hpp"
25 #include "rclcpp/macros.hpp"
26 #include "rclcpp/service.hpp"
27 #include "rclcpp/subscription_base.hpp"
28 #include "rclcpp/subscription_wait_set_mask.hpp"
29 #include "rclcpp/timer.hpp"
30 #include "rclcpp/visibility_control.hpp"
31 #include "rclcpp/wait_set_policies/detail/storage_policy_common.hpp"
32 #include "rclcpp/waitable.hpp"
36 namespace wait_set_policies
43 using is_mutable = std::true_type;
50 std::shared_ptr<rclcpp::SubscriptionBase> subscription;
55 std::shared_ptr<rclcpp::SubscriptionBase> subscription_in =
nullptr,
57 : subscription(std::move(subscription_in)),
70 std::weak_ptr<rclcpp::SubscriptionBase> subscription;
74 const std::shared_ptr<rclcpp::SubscriptionBase> & subscription_in,
76 : subscription(subscription_in),
81 : subscription(other.subscription),
85 std::shared_ptr<rclcpp::SubscriptionBase>
88 return subscription.lock();
92 expired()
const noexcept
94 return subscription.expired();
97 using SequenceOfWeakSubscriptions = std::vector<WeakSubscriptionEntry>;
98 using SubscriptionsIterable = std::vector<SubscriptionEntry>;
100 using SequenceOfWeakGuardConditions = std::vector<std::weak_ptr<rclcpp::GuardCondition>>;
101 using GuardConditionsIterable = std::vector<std::shared_ptr<rclcpp::GuardCondition>>;
103 using SequenceOfWeakTimers = std::vector<std::weak_ptr<rclcpp::TimerBase>>;
104 using TimersIterable = std::vector<std::shared_ptr<rclcpp::TimerBase>>;
106 using SequenceOfWeakClients = std::vector<std::weak_ptr<rclcpp::ClientBase>>;
107 using ClientsIterable = std::vector<std::shared_ptr<rclcpp::ClientBase>>;
109 using SequenceOfWeakServices = std::vector<std::weak_ptr<rclcpp::ServiceBase>>;
110 using ServicesIterable = std::vector<std::shared_ptr<rclcpp::ServiceBase>>;
115 std::shared_ptr<rclcpp::Waitable> waitable;
116 std::shared_ptr<void> associated_entity;
120 std::shared_ptr<rclcpp::Waitable> waitable_in =
nullptr,
121 std::shared_ptr<void> associated_entity_in =
nullptr) noexcept
122 : waitable(std::move(waitable_in)),
123 associated_entity(std::move(associated_entity_in))
130 associated_entity.reset();
136 std::weak_ptr<rclcpp::Waitable> waitable;
137 std::weak_ptr<void> associated_entity;
140 const std::shared_ptr<rclcpp::Waitable> & waitable_in,
141 const std::shared_ptr<void> & associated_entity_in) noexcept
142 : waitable(waitable_in),
143 associated_entity(associated_entity_in)
147 : waitable(other.waitable),
148 associated_entity(other.associated_entity)
151 std::shared_ptr<rclcpp::Waitable>
154 return waitable.lock();
158 expired()
const noexcept
160 return waitable.expired();
163 using SequenceOfWeakWaitables = std::vector<WeakWaitableEntry>;
164 using WaitablesIterable = std::vector<WaitableEntry>;
166 template<
class ArrayOfExtraGuardConditions>
169 const SubscriptionsIterable & subscriptions,
170 const GuardConditionsIterable & guard_conditions,
171 const ArrayOfExtraGuardConditions & extra_guard_conditions,
172 const TimersIterable & timers,
173 const ClientsIterable & clients,
174 const ServicesIterable & services,
175 const WaitablesIterable & waitables,
176 rclcpp::Context::SharedPtr context
178 : StoragePolicyCommon(
181 extra_guard_conditions,
187 subscriptions_(subscriptions.cbegin(), subscriptions.cend()),
188 shared_subscriptions_(subscriptions_.size()),
189 guard_conditions_(guard_conditions.cbegin(), guard_conditions.cend()),
190 shared_guard_conditions_(guard_conditions_.size()),
191 timers_(timers.cbegin(), timers.cend()),
192 shared_timers_(timers_.size()),
193 clients_(clients.cbegin(), clients.cend()),
194 shared_clients_(clients_.size()),
195 services_(services.cbegin(), services.cend()),
196 shared_services_(services_.size()),
197 waitables_(waitables.cbegin(), waitables.cend()),
198 shared_waitables_(waitables_.size())
203 template<
class ArrayOfExtraGuardConditions>
205 storage_rebuild_rcl_wait_set(
const ArrayOfExtraGuardConditions & extra_guard_conditions)
207 this->storage_acquire_ownerships();
210 shared_subscriptions_,
211 shared_guard_conditions_,
212 extra_guard_conditions,
219 if (this->needs_pruning_) {
220 this->storage_prune_deleted_entities();
221 this->needs_pruning_ =
false;
224 this->storage_release_ownerships();
227 template<
class EntityT,
class SequenceOfEntitiesT>
230 storage_has_entity(
const EntityT & entity,
const SequenceOfEntitiesT & entities)
235 [&entity](
const auto & inner) {return &entity == inner.lock().get();});
238 template<
class EntityT,
class SequenceOfEntitiesT>
241 storage_find_entity(
const EntityT & entity,
const SequenceOfEntitiesT & entities)
246 [&entity](
const auto & inner) {return &entity == inner.lock().get();});
250 storage_add_subscription(std::shared_ptr<rclcpp::SubscriptionBase> && subscription)
252 if (this->storage_has_entity(*subscription, subscriptions_)) {
253 throw std::runtime_error(
"subscription already in wait set");
255 WeakSubscriptionEntry weak_entry{std::move(subscription), {}};
256 subscriptions_.push_back(std::move(weak_entry));
257 this->storage_flag_for_resize();
261 storage_remove_subscription(std::shared_ptr<rclcpp::SubscriptionBase> && subscription)
263 auto it = this->storage_find_entity(*subscription, subscriptions_);
264 if (subscriptions_.cend() == it) {
265 throw std::runtime_error(
"subscription not in wait set");
267 subscriptions_.erase(it);
268 this->storage_flag_for_resize();
272 storage_add_guard_condition(std::shared_ptr<rclcpp::GuardCondition> && guard_condition)
274 if (this->storage_has_entity(*guard_condition, guard_conditions_)) {
275 throw std::runtime_error(
"guard_condition already in wait set");
277 guard_conditions_.push_back(std::move(guard_condition));
278 this->storage_flag_for_resize();
282 storage_remove_guard_condition(std::shared_ptr<rclcpp::GuardCondition> && guard_condition)
284 auto it = this->storage_find_entity(*guard_condition, guard_conditions_);
285 if (guard_conditions_.cend() == it) {
286 throw std::runtime_error(
"guard_condition not in wait set");
288 guard_conditions_.erase(it);
289 this->storage_flag_for_resize();
293 storage_add_timer(std::shared_ptr<rclcpp::TimerBase> && timer)
295 if (this->storage_has_entity(*timer, timers_)) {
296 throw std::runtime_error(
"timer already in wait set");
298 timers_.push_back(std::move(timer));
299 this->storage_flag_for_resize();
303 storage_remove_timer(std::shared_ptr<rclcpp::TimerBase> && timer)
305 auto it = this->storage_find_entity(*timer, timers_);
306 if (timers_.cend() == it) {
307 throw std::runtime_error(
"timer not in wait set");
310 this->storage_flag_for_resize();
314 storage_add_client(std::shared_ptr<rclcpp::ClientBase> && client)
316 if (this->storage_has_entity(*client, clients_)) {
317 throw std::runtime_error(
"client already in wait set");
319 clients_.push_back(std::move(client));
320 this->storage_flag_for_resize();
324 storage_remove_client(std::shared_ptr<rclcpp::ClientBase> && client)
326 auto it = this->storage_find_entity(*client, clients_);
327 if (clients_.cend() == it) {
328 throw std::runtime_error(
"client not in wait set");
331 this->storage_flag_for_resize();
335 storage_add_service(std::shared_ptr<rclcpp::ServiceBase> && service)
337 if (this->storage_has_entity(*service, services_)) {
338 throw std::runtime_error(
"service already in wait set");
340 services_.push_back(std::move(service));
341 this->storage_flag_for_resize();
345 storage_remove_service(std::shared_ptr<rclcpp::ServiceBase> && service)
347 auto it = this->storage_find_entity(*service, services_);
348 if (services_.cend() == it) {
349 throw std::runtime_error(
"service not in wait set");
352 this->storage_flag_for_resize();
356 storage_add_waitable(
357 std::shared_ptr<rclcpp::Waitable> && waitable,
358 std::shared_ptr<void> && associated_entity)
360 if (this->storage_has_entity(*waitable, waitables_)) {
361 throw std::runtime_error(
"waitable already in wait set");
363 WeakWaitableEntry weak_entry(std::move(waitable), std::move(associated_entity));
364 waitables_.push_back(std::move(weak_entry));
365 this->storage_flag_for_resize();
369 storage_remove_waitable(std::shared_ptr<rclcpp::Waitable> && waitable)
371 auto it = this->storage_find_entity(*waitable, waitables_);
372 if (waitables_.cend() == it) {
373 throw std::runtime_error(
"waitable not in wait set");
375 waitables_.erase(it);
376 this->storage_flag_for_resize();
385 storage_prune_deleted_entities() noexcept
389 [](
const auto & weak_ptr) {
391 return weak_ptr.expired();
394 subscriptions_.erase(
395 std::remove_if(subscriptions_.begin(), subscriptions_.end(), p), subscriptions_.end());
396 guard_conditions_.erase(
397 std::remove_if(guard_conditions_.begin(), guard_conditions_.end(), p),
398 guard_conditions_.end());
399 timers_.erase(std::remove_if(timers_.begin(), timers_.end(), p), timers_.end());
400 clients_.erase(std::remove_if(clients_.begin(), clients_.end(), p), clients_.end());
401 services_.erase(std::remove_if(services_.begin(), services_.end(), p), services_.end());
402 waitables_.erase(std::remove_if(waitables_.begin(), waitables_.end(), p), waitables_.end());
406 storage_acquire_ownerships()
408 if (++ownership_reference_counter_ > 1) {
413 auto lock_all = [](
const auto & weak_ptrs,
auto & shared_ptrs) {
414 shared_ptrs.resize(weak_ptrs.size());
416 for (
const auto & weak_ptr : weak_ptrs) {
417 shared_ptrs[index++] = weak_ptr.lock();
421 lock_all(subscriptions_, shared_subscriptions_);
422 lock_all(guard_conditions_, shared_guard_conditions_);
423 lock_all(timers_, shared_timers_);
424 lock_all(clients_, shared_clients_);
425 lock_all(services_, shared_services_);
428 auto lock_all_waitables = [](
const auto & weak_ptrs,
auto & shared_ptrs) {
429 shared_ptrs.resize(weak_ptrs.size());
431 for (
const auto & weak_ptr : weak_ptrs) {
432 shared_ptrs[index++] = WaitableEntry{
433 weak_ptr.waitable.lock(),
434 weak_ptr.associated_entity.lock()};
437 lock_all_waitables(waitables_, shared_waitables_);
441 storage_release_ownerships()
443 if (--ownership_reference_counter_ > 0) {
448 auto reset_all = [](
auto & shared_ptrs) {
449 for (
auto & shared_ptr : shared_ptrs) {
453 reset_all(shared_subscriptions_);
454 reset_all(shared_guard_conditions_);
455 reset_all(shared_timers_);
456 reset_all(shared_clients_);
457 reset_all(shared_services_);
458 reset_all(shared_waitables_);
461 size_t size_of_subscriptions()
const
463 return subscriptions_.size();
466 size_t size_of_timers()
const
468 return timers_.size();
471 size_t size_of_clients()
const
473 return clients_.size();
476 size_t size_of_services()
const
478 return services_.size();
481 size_t size_of_waitables()
const
483 return waitables_.size();
486 std::shared_ptr<rclcpp::SubscriptionBase>
487 subscriptions(
size_t ii)
const
489 return subscriptions_[ii].lock();
492 std::shared_ptr<rclcpp::TimerBase>
493 timers(
size_t ii)
const
495 return timers_[ii].lock();
498 std::shared_ptr<rclcpp::ClientBase>
499 clients(
size_t ii)
const
501 return clients_[ii].lock();
504 std::shared_ptr<rclcpp::ServiceBase>
505 services(
size_t ii)
const
507 return services_[ii].lock();
510 std::shared_ptr<rclcpp::Waitable>
511 waitables(
size_t ii)
const
513 return waitables_[ii].lock();
517 size_t ownership_reference_counter_ = 0;
519 SequenceOfWeakSubscriptions subscriptions_;
520 SubscriptionsIterable shared_subscriptions_;
522 SequenceOfWeakGuardConditions guard_conditions_;
523 GuardConditionsIterable shared_guard_conditions_;
525 SequenceOfWeakTimers timers_;
526 TimersIterable shared_timers_;
528 SequenceOfWeakClients clients_;
529 ClientsIterable shared_clients_;
531 SequenceOfWeakServices services_;
532 ServicesIterable shared_services_;
534 SequenceOfWeakWaitables waitables_;
535 WaitablesIterable shared_waitables_;
Options used to determine what parts of a subscription get added to or removed from a wait set.
SubscriptionEntry(std::shared_ptr< rclcpp::SubscriptionBase > subscription_in=nullptr, const rclcpp::SubscriptionWaitSetMask &mask_in={})
Conversion constructor, which is intentionally not marked explicit.
WaitableEntry(std::shared_ptr< rclcpp::Waitable > waitable_in=nullptr, std::shared_ptr< void > associated_entity_in=nullptr) noexcept
Conversion constructor, which is intentionally not marked explicit.
WaitSet policy that provides dynamically sized storage.
Common structure for storage policies, which provides rcl wait set access.
void storage_rebuild_rcl_wait_set_with_sets(const SubscriptionsIterable &subscriptions, const GuardConditionsIterable &guard_conditions, const ExtraGuardConditionsIterable &extra_guard_conditions, const TimersIterable &timers, const ClientsIterable &clients, const ServicesIterable &services, const WaitablesIterable &waitables)
Rebuild the wait set, preparing it for the next wait call.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.