1313// limitations under the License.
1414
1515#include < algorithm>
16+ #include < cassert>
1617#include < chrono>
1718#include < iterator>
1819#include < memory>
@@ -72,13 +73,10 @@ Executor::Executor(const rclcpp::ExecutorOptions & options)
7273 }
7374 });
7475
75- notify_waitable_->set_on_ready_callback (
76- [this ](auto , auto ) {
77- this ->entities_need_rebuild_ .store (true );
78- });
79-
8076 notify_waitable_->add_guard_condition (interrupt_guard_condition_);
8177 notify_waitable_->add_guard_condition (shutdown_guard_condition_);
78+
79+ wait_set_.add_waitable (notify_waitable_);
8280}
8381
8482Executor::~Executor ()
@@ -122,6 +120,20 @@ Executor::~Executor()
122120 }
123121}
124122
123+ void Executor::trigger_entity_recollect (bool notify)
124+ {
125+ this ->entities_need_rebuild_ .store (true );
126+
127+ if (!spinning.load () && entities_need_rebuild_.exchange (false )) {
128+ std::lock_guard<std::mutex> guard (mutex_);
129+ this ->collect_entities ();
130+ }
131+
132+ if (notify) {
133+ interrupt_guard_condition_->trigger ();
134+ }
135+ }
136+
125137std::vector<rclcpp::CallbackGroup::WeakPtr>
126138Executor::get_all_callback_groups ()
127139{
@@ -152,19 +164,12 @@ Executor::add_callback_group(
152164 (void ) node_ptr;
153165 this ->collector_ .add_callback_group (group_ptr);
154166
155- if (!spinning.load ()) {
156- std::lock_guard<std::mutex> guard (mutex_);
157- this ->collect_entities ();
158- }
159-
160- if (notify) {
161- try {
162- interrupt_guard_condition_->trigger ();
163- } catch (const rclcpp::exceptions::RCLError & ex) {
164- throw std::runtime_error (
165- std::string (
166- " Failed to trigger guard condition on callback group add: " ) + ex.what ());
167- }
167+ try {
168+ this ->trigger_entity_recollect (notify);
169+ } catch (const rclcpp::exceptions::RCLError & ex) {
170+ throw std::runtime_error (
171+ std::string (
172+ " Failed to trigger guard condition on callback group add: " ) + ex.what ());
168173 }
169174}
170175
@@ -173,19 +178,12 @@ Executor::add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_pt
173178{
174179 this ->collector_ .add_node (node_ptr);
175180
176- if (!spinning.load ()) {
177- std::lock_guard<std::mutex> guard (mutex_);
178- this ->collect_entities ();
179- }
180-
181- if (notify) {
182- try {
183- interrupt_guard_condition_->trigger ();
184- } catch (const rclcpp::exceptions::RCLError & ex) {
185- throw std::runtime_error (
186- std::string (
187- " Failed to trigger guard condition on node add: " ) + ex.what ());
188- }
181+ try {
182+ this ->trigger_entity_recollect (notify);
183+ } catch (const rclcpp::exceptions::RCLError & ex) {
184+ throw std::runtime_error (
185+ std::string (
186+ " Failed to trigger guard condition on node add: " ) + ex.what ());
189187 }
190188}
191189
@@ -196,18 +194,12 @@ Executor::remove_callback_group(
196194{
197195 this ->collector_ .remove_callback_group (group_ptr);
198196
199- if (!spinning.load ()) {
200- std::lock_guard<std::mutex> guard (mutex_);
201- this ->collect_entities ();
202- }
203- if (notify) {
204- try {
205- interrupt_guard_condition_->trigger ();
206- } catch (const rclcpp::exceptions::RCLError & ex) {
207- throw std::runtime_error (
208- std::string (
209- " Failed to trigger guard condition on callback group remove: " ) + ex.what ());
210- }
197+ try {
198+ this ->trigger_entity_recollect (notify);
199+ } catch (const rclcpp::exceptions::RCLError & ex) {
200+ throw std::runtime_error (
201+ std::string (
202+ " Failed to trigger guard condition on callback group remove: " ) + ex.what ());
211203 }
212204}
213205
@@ -222,19 +214,12 @@ Executor::remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node
222214{
223215 this ->collector_ .remove_node (node_ptr);
224216
225- if (!spinning.load ()) {
226- std::lock_guard<std::mutex> guard (mutex_);
227- this ->collect_entities ();
228- }
229-
230- if (notify) {
231- try {
232- interrupt_guard_condition_->trigger ();
233- } catch (const rclcpp::exceptions::RCLError & ex) {
234- throw std::runtime_error (
235- std::string (
236- " Failed to trigger guard condition on node remove: " ) + ex.what ());
237- }
217+ try {
218+ this ->trigger_entity_recollect (notify);
219+ } catch (const rclcpp::exceptions::RCLError & ex) {
220+ throw std::runtime_error (
221+ std::string (
222+ " Failed to trigger guard condition on node remove: " ) + ex.what ());
238223 }
239224}
240225
@@ -379,6 +364,10 @@ Executor::execute_any_executable(AnyExecutable & any_exec)
379364 return ;
380365 }
381366
367+ assert (
368+ (void (" cannot execute an AnyExecutable without a valid callback group" ),
369+ any_exec.callback_group ));
370+
382371 if (any_exec.timer ) {
383372 TRACETOOLS_TRACEPOINT (
384373 rclcpp_executor_execute,
@@ -403,9 +392,7 @@ Executor::execute_any_executable(AnyExecutable & any_exec)
403392 }
404393
405394 // Reset the callback_group, regardless of type
406- if (any_exec.callback_group ) {
407- any_exec.callback_group ->can_be_taken_from ().store (true );
408- }
395+ any_exec.callback_group ->can_be_taken_from ().store (true );
409396}
410397
411398template <typename Taker, typename Handler>
@@ -642,7 +629,6 @@ Executor::collect_entities()
642629 // In the case that an entity already has an expired weak pointer
643630 // before being removed from the waitset, additionally prune the waitset.
644631 this ->wait_set_ .prune_deleted_entities ();
645- this ->entities_need_rebuild_ .store (false );
646632}
647633
648634void
@@ -655,7 +641,7 @@ Executor::wait_for_work(std::chrono::nanoseconds timeout)
655641
656642 {
657643 std::lock_guard<std::mutex> guard (mutex_);
658- if (current_collection_. empty ( ) || this -> entities_need_rebuild_ . load ()) {
644+ if (this -> entities_need_rebuild_ . exchange ( false ) || current_collection_. empty ()) {
659645 this ->collect_entities ();
660646 }
661647 }
@@ -664,6 +650,13 @@ Executor::wait_for_work(std::chrono::nanoseconds timeout)
664650 RCUTILS_LOG_WARN_NAMED (
665651 " rclcpp" ,
666652 " empty wait set received in wait(). This should never happen." );
653+ } else {
654+ if (this ->wait_result_ ->kind () == WaitResultKind::Ready && current_notify_waitable_) {
655+ auto & rcl_wait_set = this ->wait_result_ ->get_wait_set ().get_rcl_wait_set ();
656+ if (current_notify_waitable_->is_ready (rcl_wait_set)) {
657+ current_notify_waitable_->execute (current_notify_waitable_->take_data ());
658+ }
659+ }
667660 }
668661}
669662
@@ -689,7 +682,7 @@ Executor::get_next_ready_executable(AnyExecutable & any_executable)
689682 auto entity_iter = current_collection_.timers .find (timer->get_timer_handle ().get ());
690683 if (entity_iter != current_collection_.timers .end ()) {
691684 auto callback_group = entity_iter->second .callback_group .lock ();
692- if (callback_group && !callback_group->can_be_taken_from ()) {
685+ if (! callback_group || !callback_group->can_be_taken_from ()) {
693686 current_timer_index++;
694687 continue ;
695688 }
@@ -719,7 +712,7 @@ Executor::get_next_ready_executable(AnyExecutable & any_executable)
719712 subscription->get_subscription_handle ().get ());
720713 if (entity_iter != current_collection_.subscriptions .end ()) {
721714 auto callback_group = entity_iter->second .callback_group .lock ();
722- if (callback_group && !callback_group->can_be_taken_from ()) {
715+ if (! callback_group || !callback_group->can_be_taken_from ()) {
723716 continue ;
724717 }
725718 any_executable.subscription = subscription;
@@ -735,7 +728,7 @@ Executor::get_next_ready_executable(AnyExecutable & any_executable)
735728 auto entity_iter = current_collection_.services .find (service->get_service_handle ().get ());
736729 if (entity_iter != current_collection_.services .end ()) {
737730 auto callback_group = entity_iter->second .callback_group .lock ();
738- if (callback_group && !callback_group->can_be_taken_from ()) {
731+ if (! callback_group || !callback_group->can_be_taken_from ()) {
739732 continue ;
740733 }
741734 any_executable.service = service;
@@ -751,7 +744,7 @@ Executor::get_next_ready_executable(AnyExecutable & any_executable)
751744 auto entity_iter = current_collection_.clients .find (client->get_client_handle ().get ());
752745 if (entity_iter != current_collection_.clients .end ()) {
753746 auto callback_group = entity_iter->second .callback_group .lock ();
754- if (callback_group && !callback_group->can_be_taken_from ()) {
747+ if (! callback_group || !callback_group->can_be_taken_from ()) {
755748 continue ;
756749 }
757750 any_executable.client = client;
@@ -767,7 +760,7 @@ Executor::get_next_ready_executable(AnyExecutable & any_executable)
767760 auto entity_iter = current_collection_.waitables .find (waitable.get ());
768761 if (entity_iter != current_collection_.waitables .end ()) {
769762 auto callback_group = entity_iter->second .callback_group .lock ();
770- if (callback_group && !callback_group->can_be_taken_from ()) {
763+ if (! callback_group || !callback_group->can_be_taken_from ()) {
771764 continue ;
772765 }
773766 any_executable.waitable = waitable;
0 commit comments