15 #ifndef RCLCPP__WAIT_SET_POLICIES__DETAIL__STORAGE_POLICY_COMMON_HPP_
16 #define RCLCPP__WAIT_SET_POLICIES__DETAIL__STORAGE_POLICY_COMMON_HPP_
24 #include "rclcpp/exceptions.hpp"
25 #include "rclcpp/logging.hpp"
26 #include "rclcpp/macros.hpp"
27 #include "rclcpp/visibility_control.hpp"
28 #include "rclcpp/waitable.hpp"
32 namespace wait_set_policies
38 template<
bool HasStrongOwnership>
43 class SubscriptionsIterable,
44 class GuardConditionsIterable,
45 class ExtraGuardConditionsIterable,
47 class ClientsIterable,
48 class ServicesIterable,
49 class WaitablesIterable
53 const SubscriptionsIterable & subscriptions,
54 const GuardConditionsIterable & guard_conditions,
55 const ExtraGuardConditionsIterable & extra_guard_conditions,
56 const TimersIterable & timers,
57 const ClientsIterable & clients,
58 const ServicesIterable & services,
59 const WaitablesIterable & waitables,
60 rclcpp::Context::SharedPtr context
65 if (
nullptr == context) {
66 throw std::invalid_argument(
"context is nullptr");
69 size_t subscriptions_from_waitables = 0;
70 size_t guard_conditions_from_waitables = 0;
71 size_t timers_from_waitables = 0;
72 size_t clients_from_waitables = 0;
73 size_t services_from_waitables = 0;
74 size_t events_from_waitables = 0;
75 for (
const auto & waitable_entry : waitables) {
76 auto waitable_ptr_pair = get_raw_pointer_from_smart_pointer(waitable_entry.waitable);
77 if (
nullptr == waitable_ptr_pair.second) {
78 if (HasStrongOwnership) {
79 throw std::runtime_error(
"unexpected condition, fixed storage policy needs pruning");
82 needs_pruning_ =
true;
97 subscriptions.size() + subscriptions_from_waitables,
98 guard_conditions.size() + extra_guard_conditions.size() + guard_conditions_from_waitables,
99 timers.size() + timers_from_waitables,
100 clients.size() + clients_from_waitables,
101 services.size() + services_from_waitables,
102 events_from_waitables,
103 context_->get_rcl_context().get(),
107 rclcpp::exceptions::throw_from_rcl_error(ret,
"Failed to create wait set");
114 extra_guard_conditions,
126 rclcpp::exceptions::throw_from_rcl_error(ret);
127 }
catch (
const std::exception & exception) {
130 "Error in destruction of rcl wait set: %s", exception.what());
135 template<
class EntityT>
136 std::pair<void *, EntityT *>
137 get_raw_pointer_from_smart_pointer(
const std::shared_ptr<EntityT> & shared_pointer)
139 return {
nullptr, shared_pointer.get()};
142 template<
class EntityT>
143 std::pair<std::shared_ptr<EntityT>, EntityT *>
144 get_raw_pointer_from_smart_pointer(
const std::weak_ptr<EntityT> & weak_pointer)
146 auto shared_pointer = weak_pointer.lock();
147 return {shared_pointer, shared_pointer.get()};
159 class SubscriptionsIterable,
160 class GuardConditionsIterable,
161 class ExtraGuardConditionsIterable,
162 class TimersIterable,
163 class ClientsIterable,
164 class ServicesIterable,
165 class WaitablesIterable
169 const SubscriptionsIterable & subscriptions,
170 const GuardConditionsIterable & guard_conditions,
171 const ExtraGuardConditionsIterable & extra_guard_conditions,
172 const TimersIterable & timers,
173 const ClientsIterable & clients,
174 const ServicesIterable & services,
175 const WaitablesIterable & waitables
178 bool was_resized =
false;
188 size_t subscriptions_from_waitables = 0;
189 size_t guard_conditions_from_waitables = 0;
190 size_t timers_from_waitables = 0;
191 size_t clients_from_waitables = 0;
192 size_t services_from_waitables = 0;
193 size_t events_from_waitables = 0;
194 for (
const auto & waitable_entry : waitables) {
195 if (!waitable_entry.waitable) {
197 if (HasStrongOwnership) {
200 throw std::runtime_error(
"unexpected condition, fixed storage policy needs pruning");
203 needs_pruning_ =
true;
206 auto & waitable = *waitable_entry.waitable;
207 subscriptions_from_waitables += waitable.get_number_of_ready_subscriptions();
208 guard_conditions_from_waitables += waitable.get_number_of_ready_guard_conditions();
209 timers_from_waitables += waitable.get_number_of_ready_timers();
210 clients_from_waitables += waitable.get_number_of_ready_clients();
211 services_from_waitables += waitable.get_number_of_ready_services();
212 events_from_waitables += waitable.get_number_of_ready_events();
216 subscriptions.size() + subscriptions_from_waitables,
217 guard_conditions.size() + extra_guard_conditions.size() + guard_conditions_from_waitables,
218 timers.size() + timers_from_waitables,
219 clients.size() + clients_from_waitables,
220 services.size() + services_from_waitables,
221 events_from_waitables
224 rclcpp::exceptions::throw_from_rcl_error(ret,
"Couldn't resize the wait set");
232 needs_resize_ =
false;
240 rclcpp::exceptions::throw_from_rcl_error(ret,
"Couldn't clear the wait set");
245 for (
const auto & subscription_entry : subscriptions) {
246 if (!subscription_entry.subscription) {
248 if (HasStrongOwnership) {
251 throw std::runtime_error(
"unexpected condition, fixed storage policy needs pruning");
254 needs_pruning_ =
true;
260 subscription_entry.subscription->get_subscription_handle().get(),
263 rclcpp::exceptions::throw_from_rcl_error(ret,
"Couldn't fill wait set");
268 auto add_guard_conditions =
269 [
this](
const auto & inner_guard_conditions)
271 for (
const auto & guard_condition : inner_guard_conditions) {
272 if (!guard_condition) {
274 if (HasStrongOwnership) {
277 throw std::runtime_error(
"unexpected condition, fixed storage policy needs pruning");
280 needs_pruning_ =
true;
285 &guard_condition->get_rcl_guard_condition(),
288 rclcpp::exceptions::throw_from_rcl_error(ret,
"Couldn't fill wait set");
294 add_guard_conditions(guard_conditions);
297 add_guard_conditions(extra_guard_conditions);
300 for (
const auto & timer : timers) {
303 if (HasStrongOwnership) {
306 throw std::runtime_error(
"unexpected condition, fixed storage policy needs pruning");
309 needs_pruning_ =
true;
314 timer->get_timer_handle().get(),
317 rclcpp::exceptions::throw_from_rcl_error(ret,
"Couldn't fill wait set");
322 for (
const auto & client : clients) {
325 if (HasStrongOwnership) {
328 throw std::runtime_error(
"unexpected condition, fixed storage policy needs pruning");
331 needs_pruning_ =
true;
336 client->get_client_handle().get(),
339 rclcpp::exceptions::throw_from_rcl_error(ret);
344 for (
const auto & service : services) {
347 if (HasStrongOwnership) {
350 throw std::runtime_error(
"unexpected condition, fixed storage policy needs pruning");
353 needs_pruning_ =
true;
358 service->get_service_handle().get(),
361 rclcpp::exceptions::throw_from_rcl_error(ret,
"Couldn't fill wait set");
366 for (
auto & waitable_entry : waitables) {
367 if (!waitable_entry.waitable) {
369 if (HasStrongOwnership) {
372 throw std::runtime_error(
"unexpected condition, fixed storage policy needs pruning");
375 needs_pruning_ =
true;
378 waitable_entry.waitable->add_to_wait_set(rcl_wait_set_);
383 storage_get_rcl_wait_set()
const
385 return rcl_wait_set_;
389 storage_get_rcl_wait_set()
391 return rcl_wait_set_;
395 storage_flag_for_resize()
397 needs_resize_ =
true;
400 size_t size_of_subscriptions()
const {
return 0;}
401 size_t size_of_timers()
const {
return 0;}
402 size_t size_of_clients()
const {
return 0;}
403 size_t size_of_services()
const {
return 0;}
404 size_t size_of_waitables()
const {
return 0;}
406 template<
class SubscriptionsIterable>
407 typename SubscriptionsIterable::value_type
408 subscriptions(
size_t)
const {
return nullptr;}
410 template<
class TimersIterable>
411 typename TimersIterable::value_type
412 timers(
size_t)
const {
return nullptr;}
414 template<
class ClientsIterable>
415 typename ClientsIterable::value_type
416 clients(
size_t)
const {
return nullptr;}
418 template<
class ServicesIterable>
419 typename ServicesIterable::value_type
420 services(
size_t)
const {
return nullptr;}
422 template<
class WaitablesIterable>
423 typename WaitablesIterable::value_type
424 waitables(
size_t)
const {
return nullptr;}
427 rclcpp::Context::SharedPtr context_;
429 bool needs_pruning_ =
false;
430 bool needs_resize_ =
false;
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
virtual RCLCPP_PUBLIC size_t get_number_of_ready_guard_conditions()
Get the number of ready guard_conditions.
virtual RCLCPP_PUBLIC size_t get_number_of_ready_timers()
Get the number of ready timers.
virtual RCLCPP_PUBLIC size_t get_number_of_ready_clients()
Get the number of ready clients.
virtual RCLCPP_PUBLIC size_t get_number_of_ready_events()
Get the number of ready events.
virtual RCLCPP_PUBLIC size_t get_number_of_ready_subscriptions()
Get the number of ready subscriptions.
virtual RCLCPP_PUBLIC size_t get_number_of_ready_services()
Get the number of ready services.
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.
RCLCPP_PUBLIC Logger get_logger(const std::string &name)
Return a named logger.
Container for subscription's, guard condition's, etc to be waited on.
#define RCL_RET_OK
Success return code.
rmw_ret_t rcl_ret_t
The type that holds an rcl 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_init(rcl_wait_set_t *wait_set, size_t number_of_subscriptions, size_t number_of_guard_conditions, size_t number_of_timers, size_t number_of_clients, size_t number_of_services, size_t number_of_events, rcl_context_t *context, rcl_allocator_t allocator)
Initialize a rcl wait set with space for items to be waited on.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_clear(rcl_wait_set_t *wait_set)
Remove (sets to NULL) all entities in the wait 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.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_fini(rcl_wait_set_t *wait_set)
Finalize a rcl wait set.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_resize(rcl_wait_set_t *wait_set, size_t subscriptions_size, size_t guard_conditions_size, size_t timers_size, size_t clients_size, size_t services_size, size_t events_size)
Reallocate space for entities in the wait set.
RCL_PUBLIC RCL_WARN_UNUSED rcl_wait_set_t rcl_get_zero_initialized_wait_set(void)
Return a rcl_wait_set_t struct with members set to NULL.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_add_guard_condition(rcl_wait_set_t *wait_set, const rcl_guard_condition_t *guard_condition, size_t *index)
Store a pointer to the guard condition in the next empty spot in the set.