25#ifndef JOIN_CORE_TIMER_HPP
26#define JOIN_CORE_TIMER_HPP
37#include <sys/timerfd.h>
48 template <
class ClockPolicy>
57 : _handle (timerfd_create (_policy.
type (), TFD_NONBLOCK | TFD_CLOEXEC))
62 throw std::system_error (errno, std::system_category (),
"timerfd_create failed");
65 if (_reactor ==
nullptr)
116 template <
class Rep,
class Period,
typename Func>
117 void setOneShot (std::chrono::duration<Rep, Period> duration, Func&& callback)
119 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (duration);
120 _callback = std::forward<Func> (callback);
122 _ns = std::chrono::nanoseconds::zero ();
125 timerfd_settime (
handle (), 0, &ts,
nullptr);
133 template <
class Clock,
class Duration,
typename Func>
134 void setOneShot (std::chrono::time_point<Clock, Duration> timePoint, Func&& callback)
137 (std::is_same<ClockPolicy, RealTime>::value && std::is_same<Clock, std::chrono::system_clock>::value) ||
138 (std::is_same<ClockPolicy, Monotonic>::value &&
139 std::is_same<Clock, std::chrono::steady_clock>::value),
140 "Clock type mismatch timer policy");
142 auto elapsed = timePoint.time_since_epoch ();
143 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (elapsed);
144 _callback = std::forward<Func> (callback);
146 _ns = std::chrono::nanoseconds::zero ();
149 timerfd_settime (
handle (), TFD_TIMER_ABSTIME, &ts,
nullptr);
157 template <
class Rep,
class Period,
typename Func>
158 void setInterval (std::chrono::duration<Rep, Period> duration, Func&& callback)
160 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (duration);
161 _callback = std::forward<Func> (callback);
166 timerfd_settime (
handle (), 0, &ts,
nullptr);
176 _ns = std::chrono::nanoseconds::zero ();
178 struct itimerspec ts = {};
179 timerfd_settime (
handle (), 0, &ts,
nullptr);
188 struct itimerspec ts = {};
189 timerfd_gettime (
handle (), &ts);
190 const bool hasValue = (ts.it_value.tv_sec != 0 || ts.it_value.tv_nsec != 0);
191 const bool hasInterval = (ts.it_interval.tv_sec != 0 || ts.it_interval.tv_nsec != 0);
192 return hasValue || hasInterval;
201 struct itimerspec ts = {};
202 timerfd_gettime (
handle (), &ts);
203 return std::chrono::seconds (ts.it_value.tv_sec) + std::chrono::nanoseconds (ts.it_value.tv_nsec);
210 std::chrono::nanoseconds
interval () const noexcept
230 return _policy.type ();
238 virtual void onReceive ([[maybe_unused]]
int fd)
override
240 uint64_t expirations;
241 ssize_t result = read (
handle (), &expirations,
sizeof (expirations));
242 if (result ==
sizeof (expirations) && _callback)
244 for (uint64_t i = 0; i < expirations; ++i)
257 static itimerspec
toTimerSpec (std::chrono::nanoseconds ns,
bool periodic =
false) noexcept
259 struct itimerspec ts = {};
260 ts.it_value.tv_sec = ns.count () / NS_PER_SEC;
261 ts.it_value.tv_nsec = ns.count () % NS_PER_SEC;
264 ts.it_interval.tv_sec = ts.it_value.tv_sec;
265 ts.it_interval.tv_nsec = ts.it_value.tv_nsec;
281 static constexpr uint64_t NS_PER_SEC = 1000000000ULL;
287 std::function<void ()> _callback;
290 std::chrono::nanoseconds _ns{};
293 bool _oneShot =
true;
319 constexpr
int type () const noexcept
321 return CLOCK_REALTIME;
342 constexpr
int type () const noexcept
344 return CLOCK_MONOTONIC;
base timer class.
Definition timer.hpp:50
virtual void onReceive(int fd) override
method called when data are ready to be read on handle.
Definition timer.hpp:238
std::chrono::nanoseconds interval() const noexcept
get the interval of the running periodic timer.
Definition timer.hpp:210
void setOneShot(std::chrono::duration< Rep, Period > duration, Func &&callback)
arm the timer as a one-shot timer.
Definition timer.hpp:117
int handle() const noexcept
get native handle.
Definition timer.hpp:274
void cancel() noexcept
cancel the timer.
Definition timer.hpp:172
std::chrono::nanoseconds remaining() const
get the remaining time until expiration.
Definition timer.hpp:199
static itimerspec toTimerSpec(std::chrono::nanoseconds ns, bool periodic=false) noexcept
convert nsec to itimerspec.
Definition timer.hpp:257
BasicTimer(const BasicTimer &other)=delete
copy constructor.
void setInterval(std::chrono::duration< Rep, Period > duration, Func &&callback)
arm the timer as a periodic timer.
Definition timer.hpp:158
bool active() const noexcept
check if timer is running.
Definition timer.hpp:186
void setOneShot(std::chrono::time_point< Clock, Duration > timePoint, Func &&callback)
arm the timer as a one-shot timer with absolute time.
Definition timer.hpp:134
BasicTimer(BasicTimer &&other)=delete
move constructor.
bool oneShot() const noexcept
check if timer is a one-shot timer.
Definition timer.hpp:219
int type() const noexcept
get the timer type.
Definition timer.hpp:228
BasicTimer & operator=(const BasicTimer &other)=delete
copy assignment operator.
BasicTimer(Reactor *reactor=nullptr)
create instance.
Definition timer.hpp:56
virtual ~BasicTimer() noexcept
destroy instance.
Definition timer.hpp:102
Event handler interface class.
Definition reactor.hpp:46
friend class Reactor
friendship with reactor.
Definition reactor.hpp:113
monotonic clock policy class.
Definition timer.hpp:329
constexpr Monotonic() noexcept=default
construct the timer policy instance by default.
constexpr int type() const noexcept
get timer type.
Definition timer.hpp:342
static Reactor * reactor()
get the global Reactor instance.
Definition reactor.cpp:438
Reactor class.
Definition reactor.hpp:120
int delHandler(int fd, bool sync=true) noexcept
delete handler from reactor.
Definition reactor.cpp:150
int addHandler(int fd, EventHandler *handler, bool sync=true) noexcept
add handler to reactor.
Definition reactor.cpp:94
real time clock policy class.
Definition timer.hpp:306
constexpr int type() const noexcept
get timer type.
Definition timer.hpp:319
constexpr RealTime() noexcept=default
construct the timer policy instance by default.
Definition acceptor.hpp:32