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)
210 extra_guard_conditions,
218 template<
class EntityT,
class SequenceOfEntitiesT>
221 storage_has_entity(
const EntityT & entity,
const SequenceOfEntitiesT & entities)
226 [&entity](
const auto & inner) {return &entity == inner.lock().get();});
229 template<
class EntityT,
class SequenceOfEntitiesT>
232 storage_find_entity(
const EntityT & entity,
const SequenceOfEntitiesT & entities)
237 [&entity](
const auto & inner) {return &entity == inner.lock().get();});
241 storage_add_subscription(std::shared_ptr<rclcpp::SubscriptionBase> && subscription)
243 if (this->storage_has_entity(*subscription, subscriptions_)) {
244 throw std::runtime_error(
"subscription already in wait set");
246 WeakSubscriptionEntry weak_entry{std::move(subscription), {}};
247 subscriptions_.push_back(std::move(weak_entry));
248 this->storage_flag_for_resize();
252 storage_remove_subscription(std::shared_ptr<rclcpp::SubscriptionBase> && subscription)
254 auto it = this->storage_find_entity(*subscription, subscriptions_);
255 if (subscriptions_.cend() == it) {
256 throw std::runtime_error(
"subscription not in wait set");
258 subscriptions_.erase(it);
259 this->storage_flag_for_resize();
263 storage_add_guard_condition(std::shared_ptr<rclcpp::GuardCondition> && guard_condition)
265 if (this->storage_has_entity(*guard_condition, guard_conditions_)) {
266 throw std::runtime_error(
"guard_condition already in wait set");
268 guard_conditions_.push_back(std::move(guard_condition));
269 this->storage_flag_for_resize();
273 storage_remove_guard_condition(std::shared_ptr<rclcpp::GuardCondition> && guard_condition)
275 auto it = this->storage_find_entity(*guard_condition, guard_conditions_);
276 if (guard_conditions_.cend() == it) {
277 throw std::runtime_error(
"guard_condition not in wait set");
279 guard_conditions_.erase(it);
280 this->storage_flag_for_resize();
284 storage_add_timer(std::shared_ptr<rclcpp::TimerBase> && timer)
286 if (this->storage_has_entity(*timer, timers_)) {
287 throw std::runtime_error(
"timer already in wait set");
289 timers_.push_back(std::move(timer));
290 this->storage_flag_for_resize();
294 storage_remove_timer(std::shared_ptr<rclcpp::TimerBase> && timer)
296 auto it = this->storage_find_entity(*timer, timers_);
297 if (timers_.cend() == it) {
298 throw std::runtime_error(
"timer not in wait set");
301 this->storage_flag_for_resize();
305 storage_add_client(std::shared_ptr<rclcpp::ClientBase> && client)
307 if (this->storage_has_entity(*client, clients_)) {
308 throw std::runtime_error(
"client already in wait set");
310 clients_.push_back(std::move(client));
311 this->storage_flag_for_resize();
315 storage_remove_client(std::shared_ptr<rclcpp::ClientBase> && client)
317 auto it = this->storage_find_entity(*client, clients_);
318 if (clients_.cend() == it) {
319 throw std::runtime_error(
"client not in wait set");
322 this->storage_flag_for_resize();
326 storage_add_service(std::shared_ptr<rclcpp::ServiceBase> && service)
328 if (this->storage_has_entity(*service, services_)) {
329 throw std::runtime_error(
"service already in wait set");
331 services_.push_back(std::move(service));
332 this->storage_flag_for_resize();
336 storage_remove_service(std::shared_ptr<rclcpp::ServiceBase> && service)
338 auto it = this->storage_find_entity(*service, services_);
339 if (services_.cend() == it) {
340 throw std::runtime_error(
"service not in wait set");
343 this->storage_flag_for_resize();
347 storage_add_waitable(
348 std::shared_ptr<rclcpp::Waitable> && waitable,
349 std::shared_ptr<void> && associated_entity)
351 if (this->storage_has_entity(*waitable, waitables_)) {
352 throw std::runtime_error(
"waitable already in wait set");
354 WeakWaitableEntry weak_entry(std::move(waitable), std::move(associated_entity));
355 waitables_.push_back(std::move(weak_entry));
356 this->storage_flag_for_resize();
360 storage_remove_waitable(std::shared_ptr<rclcpp::Waitable> && waitable)
362 auto it = this->storage_find_entity(*waitable, waitables_);
363 if (waitables_.cend() == it) {
364 throw std::runtime_error(
"waitable not in wait set");
366 waitables_.erase(it);
367 this->storage_flag_for_resize();
376 storage_prune_deleted_entities() noexcept
380 [](
const auto & weak_ptr) {
382 return weak_ptr.expired();
385 guard_conditions_.erase(
386 std::remove_if(guard_conditions_.begin(), guard_conditions_.end(), p),
387 guard_conditions_.end());
388 timers_.erase(std::remove_if(timers_.begin(), timers_.end(), p), timers_.end());
389 clients_.erase(std::remove_if(clients_.begin(), clients_.end(), p), clients_.end());
390 services_.erase(std::remove_if(services_.begin(), services_.end(), p), services_.end());
391 waitables_.erase(std::remove_if(waitables_.begin(), waitables_.end(), p), waitables_.end());
395 storage_acquire_ownerships()
397 if (++ownership_reference_counter_ > 1) {
402 auto lock_all = [](
const auto & weak_ptrs,
auto & shared_ptrs) {
403 shared_ptrs.resize(weak_ptrs.size());
405 for (
const auto & weak_ptr : weak_ptrs) {
406 shared_ptrs[index++] = weak_ptr.lock();
410 lock_all(guard_conditions_, shared_guard_conditions_);
411 lock_all(timers_, shared_timers_);
412 lock_all(clients_, shared_clients_);
413 lock_all(services_, shared_services_);
416 auto lock_all_waitables = [](
const auto & weak_ptrs,
auto & shared_ptrs) {
417 shared_ptrs.resize(weak_ptrs.size());
419 for (
const auto & weak_ptr : weak_ptrs) {
420 shared_ptrs[index++] = WaitableEntry{
421 weak_ptr.waitable.lock(),
422 weak_ptr.associated_entity.lock()};
425 lock_all_waitables(waitables_, shared_waitables_);
429 storage_release_ownerships()
431 if (--ownership_reference_counter_ > 0) {
436 auto reset_all = [](
auto & shared_ptrs) {
437 for (
auto & shared_ptr : shared_ptrs) {
441 reset_all(shared_guard_conditions_);
442 reset_all(shared_timers_);
443 reset_all(shared_clients_);
444 reset_all(shared_services_);
445 reset_all(shared_waitables_);
448 size_t ownership_reference_counter_ = 0;
450 SequenceOfWeakSubscriptions subscriptions_;
451 SubscriptionsIterable shared_subscriptions_;
453 SequenceOfWeakGuardConditions guard_conditions_;
454 GuardConditionsIterable shared_guard_conditions_;
456 SequenceOfWeakTimers timers_;
457 TimersIterable shared_timers_;
459 SequenceOfWeakClients clients_;
460 ClientsIterable shared_clients_;
462 SequenceOfWeakServices services_;
463 ServicesIterable shared_services_;
465 SequenceOfWeakWaitables waitables_;
466 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.