2323
2424#include " rcl/allocator.h"
2525#include " rcl/error_handling.h"
26+ #include " rclcpp/executors/executor_notify_waitable.hpp"
2627#include " rclcpp/subscription_wait_set_mask.hpp"
2728#include " rcpputils/scope_exit.hpp"
2829
@@ -46,6 +47,11 @@ Executor::Executor(const rclcpp::ExecutorOptions & options)
4647: spinning(false ),
4748 interrupt_guard_condition_(options.context),
4849 shutdown_guard_condition_(std::make_shared<rclcpp::GuardCondition>(options.context)),
50+ notify_waitable_(std::make_shared<rclcpp::executors::ExecutorNotifyWaitable>(
51+ [this ]() {
52+ this ->collect_entities ();
53+ })),
54+ collector_ (notify_waitable_),
4955 wait_set_(std::make_shared<rclcpp::WaitSet>())
5056{
5157 // Store the context for later use.
@@ -59,39 +65,45 @@ Executor::Executor(const rclcpp::ExecutorOptions & options)
5965 }
6066 });
6167
62- this ->collector_ .get_executor_notify_waitable ()->add_guard_condition (
63- &interrupt_guard_condition_);
64- this ->collector_ .get_executor_notify_waitable ()->add_guard_condition (
65- shutdown_guard_condition_.get ());
68+ notify_waitable_->add_guard_condition (&interrupt_guard_condition_);
69+ notify_waitable_->add_guard_condition (shutdown_guard_condition_.get ());
6670}
6771
6872Executor::~Executor ()
6973{
70- current_collection_.update_timers ({},
71- [this ](auto timer){wait_set_->add_timer (timer);},
72- [this ](auto timer){wait_set_->remove_timer (timer);});
73-
74- current_collection_.update_subscriptions ({},
75- [this ](auto subscription){
76- wait_set_->add_subscription (subscription, kDefaultSubscriptionMask );},
77- [this ](auto subscription){
78- wait_set_->remove_subscription (subscription, kDefaultSubscriptionMask );});
74+ current_collection_.timers .update (
75+ {},
76+ [this ](auto timer) {wait_set_->add_timer (timer);},
77+ [this ](auto timer) {wait_set_->remove_timer (timer);});
78+
79+ current_collection_.subscriptions .update (
80+ {},
81+ [this ](auto subscription) {
82+ wait_set_->add_subscription (subscription, kDefaultSubscriptionMask );
83+ },
84+ [this ](auto subscription) {
85+ wait_set_->remove_subscription (subscription, kDefaultSubscriptionMask );
86+ });
7987
80- current_collection_.update_clients ({},
81- [this ](auto client){wait_set_->add_client (client);},
82- [this ](auto client){wait_set_->remove_client (client);});
88+ current_collection_.clients .update (
89+ {},
90+ [this ](auto client) {wait_set_->add_client (client);},
91+ [this ](auto client) {wait_set_->remove_client (client);});
8392
84- current_collection_.update_services ({},
85- [this ](auto service){wait_set_->add_service (service);},
86- [this ](auto service){wait_set_->remove_service (service);});
93+ current_collection_.services .update (
94+ {},
95+ [this ](auto service) {wait_set_->add_service (service);},
96+ [this ](auto service) {wait_set_->remove_service (service);});
8797
88- current_collection_.update_guard_conditions ({},
89- [this ](auto guard_condition){wait_set_->add_guard_condition (guard_condition);},
90- [this ](auto guard_condition){wait_set_->remove_guard_condition (guard_condition);});
98+ current_collection_.guard_conditions .update (
99+ {},
100+ [this ](auto guard_condition) {wait_set_->add_guard_condition (guard_condition);},
101+ [this ](auto guard_condition) {wait_set_->remove_guard_condition (guard_condition);});
91102
92- current_collection_.update_waitables ({},
93- [this ](auto waitable){wait_set_->add_waitable (waitable);},
94- [this ](auto waitable){wait_set_->remove_waitable (waitable);});
103+ current_collection_.waitables .update (
104+ {},
105+ [this ](auto waitable) {wait_set_->add_waitable (waitable);},
106+ [this ](auto waitable) {wait_set_->remove_waitable (waitable);});
95107
96108 // Remove shutdown callback handle registered to Context
97109 if (!context_->remove_on_shutdown_callback (shutdown_callback_handle_)) {
@@ -129,15 +141,14 @@ Executor::add_callback_group(
129141 (void ) node_ptr;
130142 this ->collector_ .add_callback_group (group_ptr);
131143
132- if (notify)
133- {
144+ if (notify) {
134145 // Interrupt waiting to handle removed callback group
135146 try {
136147 interrupt_guard_condition_.trigger ();
137148 } catch (const rclcpp::exceptions::RCLError & ex) {
138149 throw std::runtime_error (
139- std::string (
140- " Failed to trigger guard condition on callback group add: " ) + ex.what ());
150+ std::string (
151+ " Failed to trigger guard condition on callback group add: " ) + ex.what ());
141152 }
142153 }
143154}
@@ -146,15 +157,14 @@ void
146157Executor::add_node (rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify)
147158{
148159 this ->collector_ .add_node (node_ptr);
149- if (notify)
150- {
160+ if (notify) {
151161 // Interrupt waiting to handle removed callback group
152162 try {
153163 interrupt_guard_condition_.trigger ();
154164 } catch (const rclcpp::exceptions::RCLError & ex) {
155165 throw std::runtime_error (
156- std::string (
157- " Failed to trigger guard condition on callback group remove: " ) + ex.what ());
166+ std::string (
167+ " Failed to trigger guard condition on callback group remove: " ) + ex.what ());
158168 }
159169 }
160170}
@@ -166,15 +176,14 @@ Executor::remove_callback_group(
166176{
167177 this ->collector_ .remove_callback_group (group_ptr);
168178
169- if (notify)
170- {
179+ if (notify) {
171180 // Interrupt waiting to handle removed callback group
172181 try {
173182 interrupt_guard_condition_.trigger ();
174183 } catch (const rclcpp::exceptions::RCLError & ex) {
175184 throw std::runtime_error (
176- std::string (
177- " Failed to trigger guard condition on callback group remove: " ) + ex.what ());
185+ std::string (
186+ " Failed to trigger guard condition on callback group remove: " ) + ex.what ());
178187 }
179188 }
180189}
@@ -183,34 +192,21 @@ void
183192Executor::add_node (std::shared_ptr<rclcpp::Node> node_ptr, bool notify)
184193{
185194 this ->add_node (node_ptr->get_node_base_interface (), notify);
186-
187- if (notify)
188- {
189- // Interrupt waiting to handle removed callback group
190- try {
191- interrupt_guard_condition_.trigger ();
192- } catch (const rclcpp::exceptions::RCLError & ex) {
193- throw std::runtime_error (
194- std::string (
195- " Failed to trigger guard condition on node add: " ) + ex.what ());
196- }
197- }
198195}
199196
200197void
201198Executor::remove_node (rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify)
202199{
203200 this ->collector_ .remove_node (node_ptr);
204201
205- if (notify)
206- {
202+ if (notify) {
207203 // Interrupt waiting to handle removed callback group
208204 try {
209205 interrupt_guard_condition_.trigger ();
210206 } catch (const rclcpp::exceptions::RCLError & ex) {
211207 throw std::runtime_error (
212- std::string (
213- " Failed to trigger guard condition on callback group add: " ) + ex.what ());
208+ std::string (
209+ " Failed to trigger guard condition on callback group add: " ) + ex.what ());
214210 }
215211 }
216212}
@@ -356,16 +352,10 @@ Executor::execute_any_executable(AnyExecutable & any_exec)
356352 if (any_exec.waitable ) {
357353 any_exec.waitable ->execute (any_exec.data );
358354 }
355+
359356 // Reset the callback_group, regardless of type
360- any_exec.callback_group ->can_be_taken_from ().store (true );
361- // Wake the wait, because it may need to be recalculated or work that
362- // was previously blocked is now available.
363- try {
364- interrupt_guard_condition_.trigger ();
365- } catch (const rclcpp::exceptions::RCLError & ex) {
366- throw std::runtime_error (
367- std::string (
368- " Failed to trigger guard condition from execute_any_executable: " ) + ex.what ());
357+ if (any_exec.callback_group ) {
358+ any_exec.callback_group ->can_be_taken_from ().store (true );
369359 }
370360}
371361
@@ -506,47 +496,65 @@ Executor::execute_client(
506496}
507497
508498void
509- Executor::wait_for_work (std::chrono::nanoseconds timeout )
499+ Executor::collect_entities ( )
510500{
511- TRACEPOINT (rclcpp_executor_wait_for_work, timeout.count ());
512- {
513- std::lock_guard<std::mutex> guard (mutex_);
514-
515- rclcpp::executors::ExecutorEntitiesCollection collection;
516- auto callback_groups = this ->collector_ .get_all_callback_groups ();
517- rclcpp::executors::build_entities_collection (callback_groups, collection);
518-
519- current_collection_.update_timers (collection.timers ,
520- [this ](auto timer){wait_set_->add_timer (timer);},
521- [this ](auto timer){wait_set_->remove_timer (timer);});
522-
523- current_collection_.update_subscriptions (collection.subscriptions ,
524- [this ](auto subscription){
525- wait_set_->add_subscription (subscription, kDefaultSubscriptionMask );},
526- [this ](auto subscription){
527- wait_set_->remove_subscription (subscription, kDefaultSubscriptionMask );});
528-
529- current_collection_.update_clients (collection.clients ,
530- [this ](auto client){wait_set_->add_client (client);},
531- [this ](auto client){wait_set_->remove_client (client);});
501+ std::lock_guard<std::mutex> guard (mutex_);
502+
503+ rclcpp::executors::ExecutorEntitiesCollection collection;
504+ this ->collector_ .update_collections ();
505+ auto callback_groups = this ->collector_ .get_all_callback_groups ();
506+ rclcpp::executors::build_entities_collection (callback_groups, collection);
507+
508+ auto notify_waitable = std::static_pointer_cast<rclcpp::Waitable>(notify_waitable_);
509+ collection.waitables .insert ({notify_waitable.get (), {notify_waitable, {}}});
510+
511+ current_collection_.timers .update (
512+ collection.timers ,
513+ [this ](auto timer) {wait_set_->add_timer (timer);},
514+ [this ](auto timer) {wait_set_->remove_timer (timer);});
515+
516+ current_collection_.subscriptions .update (
517+ collection.subscriptions ,
518+ [this ](auto subscription) {
519+ wait_set_->add_subscription (subscription, kDefaultSubscriptionMask );
520+ },
521+ [this ](auto subscription) {
522+ wait_set_->remove_subscription (subscription, kDefaultSubscriptionMask );
523+ });
532524
533- current_collection_.update_services (collection.services ,
534- [this ](auto service){wait_set_->add_service (service);},
535- [this ](auto service){wait_set_->remove_service (service);});
525+ current_collection_.clients .update (
526+ collection.clients ,
527+ [this ](auto client) {wait_set_->add_client (client);},
528+ [this ](auto client) {wait_set_->remove_client (client);});
529+
530+ current_collection_.services .update (
531+ collection.services ,
532+ [this ](auto service) {wait_set_->add_service (service);},
533+ [this ](auto service) {wait_set_->remove_service (service);});
534+
535+ current_collection_.guard_conditions .update (
536+ collection.guard_conditions ,
537+ [this ](auto guard_condition) {wait_set_->add_guard_condition (guard_condition);},
538+ [this ](auto guard_condition) {wait_set_->remove_guard_condition (guard_condition);});
539+
540+ current_collection_.waitables .update (
541+ collection.waitables ,
542+ [this ](auto waitable) {wait_set_->add_waitable (waitable);},
543+ [this ](auto waitable) {wait_set_->remove_waitable (waitable);});
544+ }
536545
537- current_collection_.update_guard_conditions (collection.guard_conditions ,
538- [this ](auto guard_condition){wait_set_->add_guard_condition (guard_condition);},
539- [this ](auto guard_condition){wait_set_->remove_guard_condition (guard_condition);});
546+ void
547+ Executor::wait_for_work (std::chrono::nanoseconds timeout)
548+ {
549+ TRACEPOINT (rclcpp_executor_wait_for_work, timeout.count ());
540550
541- current_collection_.update_waitables (collection.waitables ,
542- [this ](auto waitable){wait_set_->add_waitable (waitable);},
543- [this ](auto waitable){wait_set_->remove_waitable (waitable);});
551+ if (current_collection_.empty ()) {
552+ this ->collect_entities ();
544553 }
545554
546555 auto wait_result = wait_set_->wait (timeout);
547556
548- if (wait_result.kind () == WaitResultKind::Empty)
549- {
557+ if (wait_result.kind () == WaitResultKind::Empty) {
550558 RCUTILS_LOG_WARN_NAMED (
551559 " rclcpp" ,
552560 " empty wait set received in wait(). This should never happen." );
@@ -562,8 +570,7 @@ Executor::get_next_ready_executable(AnyExecutable & any_executable)
562570 TRACEPOINT (rclcpp_executor_get_next_ready);
563571 std::lock_guard<std::mutex> guard{mutex_};
564572
565- if (ready_executables_.size () == 0 )
566- {
573+ if (ready_executables_.size () == 0 ) {
567574 return false ;
568575 }
569576
0 commit comments