67 lines
1.8 KiB
C++
67 lines
1.8 KiB
C++
#include <cmath>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
#include <libscerror.hpp>
|
|
#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<timer*>(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<std::mutex> 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;
|
|
}
|