15 #ifndef RCLCPP__EXPERIMENTAL__TIMERS_MANAGER_HPP_
16 #define RCLCPP__EXPERIMENTAL__TIMERS_MANAGER_HPP_
21 #include <condition_variable>
29 #include "rclcpp/context.hpp"
30 #include "rclcpp/timer.hpp"
34 namespace experimental
88 std::shared_ptr<rclcpp::Context> context,
90 const std::shared_ptr<void> &)> on_ready_callback =
nullptr);
106 void add_timer(rclcpp::TimerBase::SharedPtr timer);
189 using TimerPtr = rclcpp::TimerBase::SharedPtr;
190 using WeakTimerPtr = rclcpp::TimerBase::WeakPtr;
215 TimersHeap locked_heap = this->validate_and_lock();
216 bool added = locked_heap.add_timer(std::move(timer));
220 this->store(locked_heap);
234 TimersHeap locked_heap = this->validate_and_lock();
235 bool removed = locked_heap.remove_timer(std::move(timer));
239 this->store(locked_heap);
252 for (
auto & weak_timer : weak_heap_) {
253 auto timer = weak_timer.lock();
254 if (timer.get() == timer_id) {
264 const WeakTimerPtr & front()
const
266 return weak_heap_.front();
274 return weak_heap_.empty();
285 TimersHeap validate_and_lock()
287 TimersHeap locked_heap;
288 bool any_timer_destroyed =
false;
290 for (
auto weak_timer : weak_heap_) {
291 auto timer = weak_timer.lock();
295 locked_heap.owned_heap_.push_back(std::move(timer));
301 any_timer_destroyed =
true;
307 if (any_timer_destroyed) {
308 locked_heap.heapify();
310 this->store(locked_heap);
324 void store(
const TimersHeap & heap)
328 for (
auto t : heap.owned_heap_) {
329 weak_heap_.push_back(t);
342 std::vector<WeakTimerPtr> weak_heap_;
363 auto it = std::find(owned_heap_.begin(), owned_heap_.end(), timer);
364 if (it != owned_heap_.end()) {
368 owned_heap_.push_back(std::move(timer));
369 std::push_heap(owned_heap_.begin(), owned_heap_.end(), timer_greater);
383 auto it = std::find(owned_heap_.begin(), owned_heap_.end(), timer);
384 if (it == owned_heap_.end()) {
388 owned_heap_.erase(it);
400 return owned_heap_.front();
407 const TimerPtr & front()
const
409 return owned_heap_.front();
418 return owned_heap_.empty();
427 return owned_heap_.size();
436 size_t ready_timers = 0;
438 for (TimerPtr t : owned_heap_) {
457 owned_heap_.push_back(owned_heap_[0]);
459 std::pop_heap(owned_heap_.begin(), owned_heap_.end(), timer_greater);
461 owned_heap_.pop_back();
469 std::make_heap(owned_heap_.begin(), owned_heap_.end(), timer_greater);
475 void clear_timers_on_reset_callbacks()
477 for (TimerPtr & t : owned_heap_) {
478 t->clear_on_reset_callback();
486 friend TimersHeap WeakTimersHeap::validate_and_lock();
492 friend void WeakTimersHeap::store(
const TimersHeap & heap);
499 static bool timer_greater(TimerPtr a, TimerPtr b)
502 return a->time_until_trigger() > b->time_until_trigger();
505 std::vector<TimerPtr> owned_heap_;
524 std::optional<std::chrono::nanoseconds> get_head_timeout_unsafe();
531 void execute_ready_timers_unsafe();
535 const std::shared_ptr<void> &)> on_ready_callback_ =
nullptr;
538 std::thread timers_thread_;
540 std::mutex timers_mutex_;
542 std::mutex stop_mutex_;
544 std::condition_variable timers_cv_;
546 bool timers_updated_ {
false};
548 std::atomic<bool> running_ {
false};
550 std::shared_ptr<rclcpp::Context> context_;
552 WeakTimersHeap weak_timers_heap_;
This class provides a way for storing and executing timer objects. It provides APIs to suit the needs...
RCLCPP_PUBLIC TimersManager(std::shared_ptr< rclcpp::Context > context, std::function< void(const rclcpp::TimerBase *, const std::shared_ptr< void > &)> on_ready_callback=nullptr)
Construct a new TimersManager object.
RCLCPP_PUBLIC void start()
Starts a thread that takes care of executing the timers stored in this object. Function will throw an...
RCLCPP_PUBLIC ~TimersManager()
Destruct the TimersManager object making sure to stop thread and release memory.
RCLCPP_PUBLIC void remove_timer(rclcpp::TimerBase::SharedPtr timer)
Remove a single timer from the object storage. Will do nothing if the timer was not being stored here...
RCLCPP_PUBLIC std::optional< std::chrono::nanoseconds > get_head_timeout()
Get the amount of time before the next timer triggers. This function is thread safe.
RCLCPP_PUBLIC bool execute_head_timer()
Executes head timer if ready. This function is thread safe. This function will try to execute the tim...
RCLCPP_PUBLIC void clear()
Remove all the timers stored in the object. Function is thread safe and it can be called regardless o...
RCLCPP_PUBLIC size_t get_number_ready_timers()
Get the number of timers that are currently ready. This function is thread safe.
RCLCPP_PUBLIC void add_timer(rclcpp::TimerBase::SharedPtr timer)
Adds a new timer to the storage, maintaining weak ownership of it. Function is thread safe and it can...
RCLCPP_PUBLIC void stop()
Stops the timers thread. Will do nothing if the timer thread was not running.
RCLCPP_PUBLIC void execute_ready_timer(const rclcpp::TimerBase *timer_id, const std::shared_ptr< void > &data)
Executes timer identified by its ID. This function is thread safe. This function will try to execute ...
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.