libos: Add Timer::reset, restart and stop

This commit is contained in:
apio 2024-01-08 19:01:59 +01:00
parent 1223c6c20b
commit 6bf8225f63
Signed by: apio
GPG Key ID: B8A7D06E42258954
2 changed files with 42 additions and 3 deletions

View File

@ -22,15 +22,21 @@ namespace os
static Result<OwnedPtr<Timer>> create_singleshot(unsigned int milliseconds, Action&& action); static Result<OwnedPtr<Timer>> create_singleshot(unsigned int milliseconds, Action&& action);
static Result<OwnedPtr<Timer>> create_repeating(unsigned int milliseconds, Action&& action); static Result<OwnedPtr<Timer>> create_repeating(unsigned int milliseconds, Action&& action);
void restart();
void reset(unsigned int milliseconds);
void stop();
~Timer(); ~Timer();
private: private:
timer_t m_timerid { -1 }; timer_t m_timerid { -1 };
bool m_repeating; bool m_repeating;
bool m_stopped { false };
struct timespec m_interval; struct timespec m_interval;
Action m_action; Action m_action;
void check_if_should_invoke_action(); void check_if_should_invoke_action();
void readd_if_necessary();
Timer() = default; Timer() = default;

View File

@ -54,21 +54,45 @@ namespace os
return timer; 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() void Timer::check_if_should_invoke_action()
{ {
struct itimerspec remaining; struct itimerspec remaining;
if (timer_gettime(m_timerid, &remaining) < 0) return; 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! // Timer expired!
m_action(); m_action();
if (!m_repeating) if (!m_repeating)
{ {
timer_delete(m_timerid);
EventLoop::the().m_timer_list.remove(this); EventLoop::the().m_timer_list.remove(this);
m_timerid = -1; m_stopped = true;
} }
else 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() Timer::~Timer()
{ {
if (m_timerid >= 0) timer_delete(m_timerid); if (m_timerid >= 0) timer_delete(m_timerid);