diff --git a/src/timer.cpp b/src/timer.cpp new file mode 100644 index 0000000..9fcbf83 --- /dev/null +++ b/src/timer.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include "timer.hpp" + +using namespace sc; + +uint64_t timer::next_id = 0; +std::mutex timer::mutex; + +timer::timer(void(*callback)(union sigval), double time, bool repeat) + : _id {}, _time {time}, _repeat {repeat} +{ + { + 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 = &_id; + 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"); +} + +timer::~timer() { + throw_if_min1_msg(timer_delete(_tid), "could not delete timer"); +} + +void timer::time(struct itimerspec& cur_value) const { + throw_if_min1_msg(timer_gettime(_tid, &cur_value), "could not get time"); +} + +double timer::time() const { + struct itimerspec its; + time(its); + return its.it_value.tv_sec + its.it_value.tv_nsec * 1000000000; +} + +bool timer::is_armed() const { + struct itimerspec its; + time(its); + return its.it_value.tv_sec != 0 || its.it_value.tv_nsec != 0; +} diff --git a/src/timer.hpp b/src/timer.hpp new file mode 100644 index 0000000..e10f8ae --- /dev/null +++ b/src/timer.hpp @@ -0,0 +1,30 @@ +#ifndef _timer_H_ +#define _timer_H_ + +#include +#include + +namespace sc { + + class timer { + static uint64_t next_id; + static std::mutex mutex; + + timer_t _tid; + uint64_t _id; + double _time; + bool _repeat; + + public: + timer(void(*callback)(union sigval), double time, bool repeat = false); + ~timer(); + + void time(struct itimerspec& cur_value) const; + double time() const; + bool is_armed() const; + bool repeat() const { return _repeat; } + }; + +} + +#endif // _timer_H_