#include #include #include #include #include "timer.hpp" uint64_t sc::timer::next_id = 0; std::mutex sc::timer::mutex; void sc::timer::callback(union sigval sv) { timer* self = reinterpret_cast(sv.sival_ptr); self->_expired_func(*self); } sc::timer::timer(double time, bool repeat, void(*expired_func)(const timer&), void* context) : _id {}, _time {time}, _repeat {repeat}, _expired_func {expired_func}, _context {context} { { std::lock_guard lock {mutex}; _id = ++next_id; } struct sigevent se; se.sigev_notify = SIGEV_THREAD; se.sigev_value.sival_int = 0; se.sigev_value.sival_ptr = this; se.sigev_notify_function = callback; se.sigev_notify_attributes = nullptr; throw_if_min1_msg(timer_create(CLOCK_MONOTONIC, &se, &_tid), "could not create timer"); time_t secs = floor(time / 1000); long ns = (time - 1000 * secs) * 1000000; struct itimerspec its; its.it_value.tv_sec = secs; its.it_value.tv_nsec = ns; if (repeat) { its.it_interval.tv_sec = secs; its.it_interval.tv_nsec = ns; } else { its.it_interval.tv_sec = 0; its.it_interval.tv_nsec = 0; } throw_if_min1_msg(timer_settime(_tid, 0, &its, nullptr), "could not set timer"); } sc::timer::~timer() { timer_delete(_tid); } void sc::timer::time_left(struct itimerspec& cur_value) const { throw_if_min1_msg(timer_gettime(_tid, &cur_value), "could not get time"); } double sc::timer::time_left() const { struct itimerspec its; time_left(its); return its.it_value.tv_sec + its.it_value.tv_nsec * 1000000000; } bool sc::timer::is_armed() const { struct itimerspec its; time_left(its); return its.it_value.tv_sec != 0 || its.it_value.tv_nsec != 0; }