From 6bf8225f63888a01bf8279209de5a9e488ea8285 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 8 Jan 2024 19:01:59 +0100 Subject: [PATCH] libos: Add Timer::reset, restart and stop --- libos/include/os/Timer.h | 6 ++++++ libos/src/Timer.cpp | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/libos/include/os/Timer.h b/libos/include/os/Timer.h index eeb503af..9a97087b 100644 --- a/libos/include/os/Timer.h +++ b/libos/include/os/Timer.h @@ -22,15 +22,21 @@ namespace os static Result> create_singleshot(unsigned int milliseconds, Action&& action); static Result> create_repeating(unsigned int milliseconds, Action&& action); + void restart(); + void reset(unsigned int milliseconds); + void stop(); + ~Timer(); private: timer_t m_timerid { -1 }; bool m_repeating; + bool m_stopped { false }; struct timespec m_interval; Action m_action; void check_if_should_invoke_action(); + void readd_if_necessary(); Timer() = default; diff --git a/libos/src/Timer.cpp b/libos/src/Timer.cpp index 4a958245..4ac08fc3 100644 --- a/libos/src/Timer.cpp +++ b/libos/src/Timer.cpp @@ -54,21 +54,45 @@ namespace os return timer; } + void Timer::restart() + { + struct itimerspec itimer = { .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, .it_value = m_interval }; + + timer_settime(m_timerid, 0, &itimer, nullptr); + + readd_if_necessary(); + } + + void Timer::reset(unsigned int milliseconds) + { + m_interval = { .tv_sec = milliseconds / 1000, .tv_nsec = (milliseconds % 1000) * 1'000'000 }; + restart(); + } + + void Timer::stop() + { + EventLoop::the().m_timer_list.remove(this); + m_stopped = true; + + struct itimerspec itimer; + memset(&itimer, 0, sizeof(itimer)); + timer_settime(m_timerid, 0, &itimer, nullptr); + } + void Timer::check_if_should_invoke_action() { struct itimerspec remaining; if (timer_gettime(m_timerid, &remaining) < 0) return; - if (!remaining.it_value.tv_sec && !remaining.it_value.tv_nsec) + if (!remaining.it_value.tv_sec && !remaining.it_value.tv_nsec && !m_stopped) { // Timer expired! m_action(); if (!m_repeating) { - timer_delete(m_timerid); EventLoop::the().m_timer_list.remove(this); - m_timerid = -1; + m_stopped = true; } else { @@ -79,6 +103,15 @@ namespace os } } + void Timer::readd_if_necessary() + { + if (m_stopped) + { + m_stopped = false; + EventLoop::the().m_timer_list.append(this); + } + } + Timer::~Timer() { if (m_timerid >= 0) timer_delete(m_timerid);