HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
timer.hpp
1// Copyright Take Vos 2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5
6#pragma once
7
8#include "unfair_mutex.hpp"
9#include "subsystem.hpp"
10#include "chrono.hpp"
11#include <mutex>
12#include <vector>
13#include <functional>
14#include <tuple>
15#include <thread>
16
17namespace tt {
18
21class timer {
22public:
27 using callback_type = std::function<void(utc_nanoseconds,bool)>;
29
30 timer(std::string name) noexcept;
31 ~timer();
32
37 void start() noexcept;
38
43 void stop() noexcept;
44
58 template<typename Callback> requires(std::is_invocable_v<Callback>)
59 [[nodiscard]] std::shared_ptr<callback_type> add_callback(std::chrono::nanoseconds interval, Callback callback, bool immediate=false) noexcept
60 {
61 ttlet current_time = utc_nanoseconds(std::chrono::utc_clock::now());
62 auto callback_ptr = std::make_shared<callback_type>(std::forward<Callback>(callback));
63
64 {
65 ttlet lock = std::scoped_lock(mutex);
66
67 callback_list.emplace_back(
69 calculate_next_wakeup(current_time, interval),
70 callback_ptr
71 );
72
73 if (std::ssize(callback_list) == 1) {
74 start_with_lock_held();
75 }
76 }
77
78 if (immediate) {
79 (*callback_ptr)(current_time, false);
80 }
81 return callback_ptr;
82 }
83
86 void remove_callback(callback_ptr_type const &callback_ptr) noexcept;
87
88 static timer &global() noexcept
89 {
90 return *start_subsystem_or_terminate(_global, nullptr, subsystem_init, subsystem_deinit);
91 }
92
93private:
94 struct callback_entry {
96 utc_nanoseconds next_wakeup;
98
99 callback_entry(
101 utc_nanoseconds next_wakeup,
102 std::shared_ptr<callback_type> const &callback_ptr) noexcept :
103 interval(interval), next_wakeup(next_wakeup), callback_ptr(callback_ptr)
104 {
105 }
106 };
107
108 static inline std::atomic<timer *> _global;
109
112 std::string name;
113
114 mutable unfair_mutex mutex;
115 std::jthread thread;
116 std::vector<callback_entry> callback_list;
117 size_t callback_count = 0;
118
124 [[nodiscard]] std::pair<std::vector<callback_ptr_type>, utc_nanoseconds>
125 find_triggered_callbacks(utc_nanoseconds current_time) noexcept;
126
129 void loop(std::stop_token stop_token) noexcept;
130
135 void start_with_lock_held() noexcept;
136
141 void stop_with_lock_held() noexcept;
142
143 [[nodiscard]] static utc_nanoseconds calculate_next_wakeup(utc_nanoseconds current_time, std::chrono::nanoseconds interval) noexcept;
144
145 [[nodiscard]] static timer *subsystem_init() noexcept;
146 static void subsystem_deinit() noexcept;
147};
148
149
150}
STL namespace.
Interval arithmetic.
Definition interval.hpp:29
A timer which will execute callbacks at given intervals.
Definition timer.hpp:21
void stop() noexcept
Stop the timer thread.
void remove_callback(callback_ptr_type const &callback_ptr) noexcept
Remove the callback function.
void start() noexcept
Start the timer thread.
std::shared_ptr< callback_type > add_callback(std::chrono::nanoseconds interval, Callback callback, bool immediate=false) noexcept
Add a callback function to be executed each interval.
Definition timer.hpp:59
T emplace_back(T... args)