23
23
24
24
#include " rcl/allocator.h"
25
25
#include " rcl/error_handling.h"
26
+ #include " rclcpp/executors/executor_notify_waitable.hpp"
26
27
#include " rclcpp/subscription_wait_set_mask.hpp"
27
28
#include " rcpputils/scope_exit.hpp"
28
29
@@ -46,6 +47,11 @@ Executor::Executor(const rclcpp::ExecutorOptions & options)
46
47
: spinning(false ),
47
48
interrupt_guard_condition_(options.context),
48
49
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_),
49
55
wait_set_(std::make_shared<rclcpp::WaitSet>())
50
56
{
51
57
// Store the context for later use.
@@ -59,39 +65,45 @@ Executor::Executor(const rclcpp::ExecutorOptions & options)
59
65
}
60
66
});
61
67
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 ());
66
70
}
67
71
68
72
Executor::~Executor ()
69
73
{
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
+ });
79
87
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);});
83
92
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);});
87
97
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);});
91
102
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);});
95
107
96
108
// Remove shutdown callback handle registered to Context
97
109
if (!context_->remove_on_shutdown_callback (shutdown_callback_handle_)) {
@@ -129,15 +141,14 @@ Executor::add_callback_group(
129
141
(void ) node_ptr;
130
142
this ->collector_ .add_callback_group (group_ptr);
131
143
132
- if (notify)
133
- {
144
+ if (notify) {
134
145
// Interrupt waiting to handle removed callback group
135
146
try {
136
147
interrupt_guard_condition_.trigger ();
137
148
} catch (const rclcpp::exceptions::RCLError & ex) {
138
149
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 ());
141
152
}
142
153
}
143
154
}
@@ -146,15 +157,14 @@ void
146
157
Executor::add_node (rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify)
147
158
{
148
159
this ->collector_ .add_node (node_ptr);
149
- if (notify)
150
- {
160
+ if (notify) {
151
161
// Interrupt waiting to handle removed callback group
152
162
try {
153
163
interrupt_guard_condition_.trigger ();
154
164
} catch (const rclcpp::exceptions::RCLError & ex) {
155
165
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 ());
158
168
}
159
169
}
160
170
}
@@ -166,15 +176,14 @@ Executor::remove_callback_group(
166
176
{
167
177
this ->collector_ .remove_callback_group (group_ptr);
168
178
169
- if (notify)
170
- {
179
+ if (notify) {
171
180
// Interrupt waiting to handle removed callback group
172
181
try {
173
182
interrupt_guard_condition_.trigger ();
174
183
} catch (const rclcpp::exceptions::RCLError & ex) {
175
184
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 ());
178
187
}
179
188
}
180
189
}
@@ -183,34 +192,21 @@ void
183
192
Executor::add_node (std::shared_ptr<rclcpp::Node> node_ptr, bool notify)
184
193
{
185
194
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
- }
198
195
}
199
196
200
197
void
201
198
Executor::remove_node (rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify)
202
199
{
203
200
this ->collector_ .remove_node (node_ptr);
204
201
205
- if (notify)
206
- {
202
+ if (notify) {
207
203
// Interrupt waiting to handle removed callback group
208
204
try {
209
205
interrupt_guard_condition_.trigger ();
210
206
} catch (const rclcpp::exceptions::RCLError & ex) {
211
207
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 ());
214
210
}
215
211
}
216
212
}
@@ -356,16 +352,10 @@ Executor::execute_any_executable(AnyExecutable & any_exec)
356
352
if (any_exec.waitable ) {
357
353
any_exec.waitable ->execute (any_exec.data );
358
354
}
355
+
359
356
// 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 );
369
359
}
370
360
}
371
361
@@ -506,47 +496,65 @@ Executor::execute_client(
506
496
}
507
497
508
498
void
509
- Executor::wait_for_work (std::chrono::nanoseconds timeout )
499
+ Executor::collect_entities ( )
510
500
{
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
+ });
532
524
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
+ }
536
545
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 ());
540
550
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 ();
544
553
}
545
554
546
555
auto wait_result = wait_set_->wait (timeout);
547
556
548
- if (wait_result.kind () == WaitResultKind::Empty)
549
- {
557
+ if (wait_result.kind () == WaitResultKind::Empty) {
550
558
RCUTILS_LOG_WARN_NAMED (
551
559
" rclcpp" ,
552
560
" empty wait set received in wait(). This should never happen." );
@@ -562,8 +570,7 @@ Executor::get_next_ready_executable(AnyExecutable & any_executable)
562
570
TRACEPOINT (rclcpp_executor_get_next_ready);
563
571
std::lock_guard<std::mutex> guard{mutex_};
564
572
565
- if (ready_executables_.size () == 0 )
566
- {
573
+ if (ready_executables_.size () == 0 ) {
567
574
return false ;
568
575
}
569
576
0 commit comments