22 #include <rclcpp/callback_group.hpp>
23 #include "global_event_id_provider.hpp"
29 namespace cbg_executor
36 rclcpp::Waitable::WeakPtr waitable;
37 int internal_event_type;
41 return waitable.expired();
48 : callback(std::move(callback))
52 std::function<void()> callback;
63 : scheduler(scheduler), type(type)
75 virtual std::function<void(
size_t)> get_ready_callback_for_entity(
76 const rclcpp::SubscriptionBase::WeakPtr & entity) = 0;
77 virtual std::function<void(std::function<
void()> executed_callback)>
78 get_ready_callback_for_entity(
const rclcpp::TimerBase::WeakPtr & entity) = 0;
79 virtual std::function<void(
size_t)> get_ready_callback_for_entity(
80 const rclcpp::ClientBase::WeakPtr & entity) = 0;
81 virtual std::function<void(
size_t)> get_ready_callback_for_entity(
82 const rclcpp::ServiceBase::WeakPtr & entity) = 0;
83 virtual std::function<void(
size_t,
84 int)> get_ready_callback_for_entity(
const rclcpp::Waitable::WeakPtr & entity) = 0;
85 virtual std::function<void(
size_t)> get_ready_callback_for_entity(
94 std::lock_guard l(ready_mutex);
106 CallbackGroupType get_type() {
return type;}
111 bool in_queue =
false;
128 template<
typename add_fun>
132 std::lock_guard l(ready_mutex);
136 if(not_ready || !idle) {
149 void mark_as_skipped()
163 if (type != CallbackGroupType::Reentrant) {
168 std::mutex ready_mutex;
172 bool not_ready =
false;
178 CallbackGroupType type;
184 std::function<void()> execute_function;
195 : sync_function(sync_function) {}
203 CallbackGroupHandle * add_callback_group(
const rclcpp::CallbackGroup::SharedPtr & callback_group)
205 auto uPtr = get_handle_for_callback_group(callback_group);
206 CallbackGroupHandle * ret = uPtr.get();
208 std::lock_guard lk(ready_callback_groups_mutex);
210 callback_groups.push_back(std::move(uPtr));
214 void remove_callback_group(
const CallbackGroupHandle *callback_handle)
216 std::lock_guard lk(ready_callback_groups_mutex);
217 ready_callback_groups.erase(std::find(ready_callback_groups.begin(),
218 ready_callback_groups.end(), callback_handle));
220 callback_groups.remove_if([&callback_handle] (
const auto & e) {
221 return e.get() == callback_handle;
233 if (!handle->in_queue) {
234 std::lock_guard l(ready_callback_groups_mutex);
236 ready_callback_groups.push_back(handle);
237 handle->in_queue =
true;
240 if(callback_group_was_idle) {
247 std::optional<ExecutableEntity> entity;
248 bool moreEntitiesReady{};
260 std::lock_guard l(ready_callback_groups_mutex);
264 ExecutableEntity{.execute_function = sync_function, .callback_handle =
nullptr},
265 .moreEntitiesReady =
false};
269 return get_next_ready_entity_intern();
273 GlobalEventIdProvider::MonotonicId max_id)
276 std::lock_guard l(ready_callback_groups_mutex);
279 return ExecutableEntityWithInfo{.entity =
280 ExecutableEntity{.execute_function = sync_function, .callback_handle =
nullptr},
281 .moreEntitiesReady =
false};
285 return get_next_ready_entity_intern(max_id);
288 virtual ExecutableEntityWithInfo get_next_ready_entity_intern() = 0;
289 virtual ExecutableEntityWithInfo get_next_ready_entity_intern(
290 GlobalEventIdProvider::MonotonicId max_id) = 0;
302 bool wake_worker =
false;
304 std::lock_guard l(ready_callback_groups_mutex);
322 if(e.callback_handle !=
nullptr) {
333 std::lock_guard lk(ready_callback_groups_mutex);
334 release_worker_once =
true;
336 work_ready_conditional.notify_one();
339 void block_worker_thread()
341 std::unique_lock lk(ready_callback_groups_mutex);
342 work_ready_conditional.wait(lk, [
this]() ->
bool {
343 return !ready_callback_groups.empty() || release_worker_once || release_workers;
345 release_worker_once =
false;
348 void block_worker_thread_for(std::chrono::nanoseconds timeout)
350 std::unique_lock lk(ready_callback_groups_mutex);
351 work_ready_conditional.wait_for(lk, timeout, [
this]() ->
bool {
352 return !ready_callback_groups.empty() || release_worker_once || release_workers;
354 release_worker_once =
false;
357 void release_all_worker_threads()
360 std::lock_guard lk(ready_callback_groups_mutex);
361 release_workers =
true;
363 work_ready_conditional.notify_all();
367 virtual std::unique_ptr<CallbackGroupHandle> get_handle_for_callback_group(
368 const rclcpp::CallbackGroup::SharedPtr & callback_group) = 0;
372 std::function<void ()> sync_function;
374 bool needs_sync =
false;
376 std::mutex ready_callback_groups_mutex;
377 std::deque<CallbackGroupHandle *> ready_callback_groups;
379 bool release_workers =
false;
380 bool release_worker_once =
false;
382 std::condition_variable work_ready_conditional;
384 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)