23 #include <rclcpp/callback_group.hpp>
24 #include "global_event_id_provider.hpp"
30 namespace cbg_executor
37 rclcpp::Waitable::WeakPtr waitable;
38 int internal_event_type;
42 return waitable.expired();
49 : callback(std::move(callback))
53 std::function<void()> callback;
64 : scheduler(scheduler), type(type)
76 virtual std::function<void(
size_t)> get_ready_callback_for_entity(
77 const rclcpp::SubscriptionBase::WeakPtr & entity) = 0;
78 virtual std::function<void(std::function<
void()> executed_callback)>
79 get_ready_callback_for_entity(
const rclcpp::TimerBase::WeakPtr & entity) = 0;
80 virtual std::function<void(
size_t)> get_ready_callback_for_entity(
81 const rclcpp::ClientBase::WeakPtr & entity) = 0;
82 virtual std::function<void(
size_t)> get_ready_callback_for_entity(
83 const rclcpp::ServiceBase::WeakPtr & entity) = 0;
84 virtual std::function<void(
size_t,
85 int)> get_ready_callback_for_entity(
const rclcpp::Waitable::WeakPtr & entity) = 0;
86 virtual std::function<void(
size_t)> get_ready_callback_for_entity(
95 std::lock_guard l(ready_mutex);
107 CallbackGroupType get_type() {
return type;}
112 bool in_queue =
false;
129 template<
typename add_fun>
133 std::lock_guard l(ready_mutex);
137 if(not_ready || !idle) {
150 void mark_as_skipped()
164 if (type != CallbackGroupType::Reentrant) {
169 std::mutex ready_mutex;
173 bool not_ready =
false;
179 CallbackGroupType type;
185 std::function<void()> execute_function;
196 : sync_function(sync_function) {}
204 CallbackGroupHandle * add_callback_group(
const rclcpp::CallbackGroup::SharedPtr & callback_group)
206 auto uPtr = get_handle_for_callback_group(callback_group);
207 CallbackGroupHandle * ret = uPtr.get();
209 std::lock_guard lk(ready_callback_groups_mutex);
211 callback_groups.push_back(std::move(uPtr));
215 void remove_callback_group(
const CallbackGroupHandle *callback_handle)
217 std::lock_guard lk(ready_callback_groups_mutex);
219 auto cbg_it = std::find(ready_callback_groups.begin(),
220 ready_callback_groups.end(), callback_handle);
221 if (cbg_it != ready_callback_groups.end()) {
222 ready_callback_groups.erase(cbg_it);
225 callback_groups.remove_if([&callback_handle] (
const auto & e) {
226 return e.get() == callback_handle;
239 std::lock_guard l(ready_callback_groups_mutex);
241 if (!handle->in_queue) {
242 ready_callback_groups.push_back(handle);
243 handle->in_queue =
true;
247 if(callback_group_was_idle) {
254 std::optional<ExecutableEntity> entity;
255 bool moreEntitiesReady{};
267 std::lock_guard l(ready_callback_groups_mutex);
271 ExecutableEntity{.execute_function = sync_function, .callback_handle =
nullptr},
272 .moreEntitiesReady =
false};
276 return get_next_ready_entity_intern();
280 GlobalEventIdProvider::MonotonicId max_id)
283 std::lock_guard l(ready_callback_groups_mutex);
286 return ExecutableEntityWithInfo{.entity =
287 ExecutableEntity{.execute_function = sync_function, .callback_handle =
nullptr},
288 .moreEntitiesReady =
false};
292 return get_next_ready_entity_intern(max_id);
295 virtual ExecutableEntityWithInfo get_next_ready_entity_intern() = 0;
296 virtual ExecutableEntityWithInfo get_next_ready_entity_intern(
297 GlobalEventIdProvider::MonotonicId max_id) = 0;
309 bool wake_worker =
false;
311 std::lock_guard l(ready_callback_groups_mutex);
329 if(e.callback_handle !=
nullptr) {
340 std::lock_guard lk(ready_callback_groups_mutex);
341 release_worker_once =
true;
343 work_ready_conditional.notify_one();
346 void block_worker_thread()
348 std::unique_lock lk(ready_callback_groups_mutex);
349 work_ready_conditional.wait(lk, [
this]() ->
bool {
350 return !ready_callback_groups.empty() || release_worker_once || release_workers;
352 release_worker_once =
false;
355 void block_worker_thread_for(std::chrono::nanoseconds timeout)
357 std::unique_lock lk(ready_callback_groups_mutex);
358 work_ready_conditional.wait_for(lk, timeout, [
this]() ->
bool {
359 return !ready_callback_groups.empty() || release_worker_once || release_workers;
361 release_worker_once =
false;
364 void release_all_worker_threads()
367 std::lock_guard lk(ready_callback_groups_mutex);
368 release_workers =
true;
370 work_ready_conditional.notify_all();
374 virtual std::unique_ptr<CallbackGroupHandle> get_handle_for_callback_group(
375 const rclcpp::CallbackGroup::SharedPtr & callback_group) = 0;
379 std::function<void ()> sync_function;
381 bool needs_sync =
false;
383 std::mutex ready_callback_groups_mutex;
384 std::deque<CallbackGroupHandle *> ready_callback_groups;
386 bool release_workers =
false;
387 bool release_worker_once =
false;
389 std::condition_variable work_ready_conditional;
391 std::list<std::unique_ptr<CallbackGroupHandle>> callback_groups;
void unblock_one_worker_thread()
void callback_group_ready(CallbackGroupHandle *handle, bool callback_group_was_idle)
void mark_entity_as_executed(const ExecutableEntity &e)
ExecutableEntityWithInfo get_next_ready_entity()
CBGScheduler(std::function< void()> sync_function)
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
virtual bool has_ready_entities() const =0
void add_ready_entity(const add_fun &fun)