4 #include <condition_variable>
16 template <
typename TimerIdType = u
int8_t>
22 std::chrono::steady_clock::time_point
expiry;
31 m_thread = std::thread([
this]() { run(); });
48 std::function<
void(TimerIdType)> callback,
49 bool periodic =
false) {
54 std::lock_guard<std::mutex> lock(m_mutex);
57 entry.
expiry = std::chrono::steady_clock::now() + duration;
58 entry.
callback = std::move(callback);
64 m_timers[id] = std::move(entry);
79 std::lock_guard<std::mutex> lock(m_mutex);
80 return m_timers.erase(
id) > 0;
85 std::lock_guard<std::mutex> lock(m_mutex);
86 auto it = m_timers.find(
id);
87 if (it == m_timers.end()) {
91 it->second.expiry = std::chrono::steady_clock::now() + it->second.interval;
107 std::lock_guard<std::mutex> lock(m_mutex);
108 auto it = m_timers.find(
id);
109 if (it == m_timers.end()) {
113 it->second.interval = newDuration;
114 it->second.expiry = std::chrono::steady_clock::now() + newDuration;
127 std::lock_guard<std::mutex> lock(m_mutex);
128 auto it = m_timers.find(
id);
129 if (it == m_timers.end()) {
132 it->second.enabled =
false;
146 std::lock_guard<std::mutex> lock(m_mutex);
147 auto it = m_timers.find(
id);
148 if (it == m_timers.end()) {
151 if (!it->second.enabled) {
152 it->second.enabled =
true;
153 it->second.expiry = std::chrono::steady_clock::now() + it->second.interval;
175 std::lock_guard<std::mutex> lock(m_mutex);
188 std::lock_guard<std::mutex> lock(m_mutex);
189 return m_timers.find(
id) != m_timers.end();
199 std::lock_guard<std::mutex> lock(m_mutex);
200 return m_timers.size();
207 if (m_running.exchange(
false)) {
209 if (m_thread.joinable()) {
216 std::map<TimerId, TimerEntry> m_timers;
217 mutable std::mutex m_mutex;
218 std::condition_variable m_cv;
219 std::thread m_thread;
220 std::atomic<bool> m_running{
false};
224 std::unique_lock<std::mutex> lock(m_mutex);
226 if (m_timers.empty()) {
227 m_cv.wait(lock, [
this]() {
228 return !m_running || !m_timers.empty();
233 auto now = std::chrono::steady_clock::now();
234 auto nextExpiry = std::chrono::steady_clock::time_point::max();
236 for (
const auto &[
id, timer] : m_timers) {
237 if (timer.enabled && timer.expiry < nextExpiry) {
238 nextExpiry = timer.expiry;
242 if (nextExpiry > now) {
243 m_cv.wait_until(lock, nextExpiry, [
this]() {
249 std::vector<TimerId> expired;
250 for (
const auto &[
id, timer] : m_timers) {
251 if (timer.enabled && timer.expiry <= now) {
252 expired.push_back(
id);
260 auto it = m_timers.find(
id);
261 if (it == m_timers.end() || !it->second.enabled) {
266 auto callback = it->second.callback;
267 bool periodic = it->second.periodic;
268 auto interval = it->second.interval;
271 it->second.expiry = std::chrono::steady_clock::now() + interval;
bool disableTimer(TimerId id)
Disables a timer.
bool updateTimer(TimerId id, std::chrono::milliseconds newDuration)
Updates a timer duration.
bool resetTimer(TimerId id)
Restarts a timer (disables and enables it).
size_t timerCount() const
The number of timers.
bool removeTimer(TimerId id)
Removes the timer.
void stop()
Stops all timers and the timer manager.
bool restartTimer(TimerId id)
bool enableTimer(TimerId id)
Enables a disabled timer.
void stopAll()
Stops all timers and clears the timer list.
bool hasTimer(TimerId id) const
Check if specified timer exists.
std::optional< TimerId > addTimer(TimerId id, std::chrono::milliseconds duration, std::function< void(TimerIdType)> callback, bool periodic=false)
Add a timer.
std::chrono::steady_clock::time_point expiry
std::function< void(TimerIdType)> callback
std::chrono::milliseconds interval