25#ifndef JOIN_CORE_TIMER_HPP
26#define JOIN_CORE_TIMER_HPP
38#include <sys/timerfd.h>
46 template <
class ClockPolicy>
55 : _handle (timerfd_create (ClockPolicy::
type (), TFD_NONBLOCK | TFD_CLOEXEC))
60 throw std::system_error (errno, std::system_category (),
"timerfd_create failed");
109 template <
class Rep,
class Period,
typename Func>
110 void setOneShot (std::chrono::duration<Rep, Period> duration, Func&& callback)
112 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (duration);
113 _callback = std::forward<Func> (callback);
115 _ns = std::chrono::nanoseconds::zero ();
117 auto ts = toTimerSpec (ns);
118 timerfd_settime (handle (), 0, &ts,
nullptr);
126 template <
class Clock,
class Duration,
typename Func>
127 void setOneShot (std::chrono::time_point<Clock, Duration> timePoint, Func&& callback)
130 (std::is_same<ClockPolicy, RealTime>::value && std::is_same<Clock, std::chrono::system_clock>::value) ||
131 (std::is_same<ClockPolicy, Monotonic>::value &&
132 std::is_same<Clock, std::chrono::steady_clock>::value),
133 "Clock type mismatch timer policy");
135 auto elapsed = timePoint.time_since_epoch ();
136 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (elapsed);
137 _callback = std::forward<Func> (callback);
139 _ns = std::chrono::nanoseconds::zero ();
141 auto ts = toTimerSpec (ns);
142 timerfd_settime (handle (), TFD_TIMER_ABSTIME, &ts,
nullptr);
150 template <
class Rep,
class Period,
typename Func>
151 void setInterval (std::chrono::duration<Rep, Period> duration, Func&& callback)
153 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (duration);
154 _callback = std::forward<Func> (callback);
158 auto ts = toTimerSpec (ns,
true);
159 timerfd_settime (handle (), 0, &ts,
nullptr);
169 _ns = std::chrono::nanoseconds::zero ();
171 struct itimerspec ts = {};
172 timerfd_settime (handle (), 0, &ts,
nullptr);
181 struct itimerspec ts = {};
182 timerfd_gettime (handle (), &ts);
183 const bool hasValue = (ts.it_value.tv_sec != 0 || ts.it_value.tv_nsec != 0);
184 const bool hasInterval = (ts.it_interval.tv_sec != 0 || ts.it_interval.tv_nsec != 0);
185 return hasValue || hasInterval;
194 struct itimerspec ts = {};
195 timerfd_gettime (handle (), &ts);
196 return std::chrono::seconds (ts.it_value.tv_sec) + std::chrono::nanoseconds (ts.it_value.tv_nsec);
203 std::chrono::nanoseconds
interval () const noexcept
221 static constexpr int type () noexcept
223 return ClockPolicy::type ();
231 virtual void onReadable ([[maybe_unused]]
int fd)
override
233 uint64_t expirations;
234 ssize_t result = read (handle (), &expirations,
sizeof (expirations));
235 if (result ==
sizeof (expirations) && _callback)
237 for (uint64_t i = 0; i < expirations; ++i)
250 static constexpr itimerspec toTimerSpec (std::chrono::nanoseconds ns,
bool periodic =
false) noexcept
253 ts.it_value.tv_sec = ns.count () / _nsPerSec;
254 ts.it_value.tv_nsec = ns.count () % _nsPerSec;
257 ts.it_interval.tv_sec = ts.it_value.tv_sec;
258 ts.it_interval.tv_nsec = ts.it_value.tv_nsec;
267 int handle () const noexcept
273 static constexpr uint64_t _nsPerSec = 1000000000ULL;
276 std::function<void ()> _callback;
279 std::chrono::nanoseconds _ns{};
282 bool _oneShot =
true;
base timer class.
Definition timer.hpp:48
std::chrono::nanoseconds interval() const noexcept
get the interval of the running periodic timer.
Definition timer.hpp:203
std::chrono::nanoseconds remaining() const noexcept
get the remaining time until expiration.
Definition timer.hpp:192
void setOneShot(std::chrono::duration< Rep, Period > duration, Func &&callback)
arm the timer as a one-shot timer.
Definition timer.hpp:110
void cancel() noexcept
cancel the timer.
Definition timer.hpp:165
~BasicTimer() noexcept
destroy instance.
Definition timer.hpp:95
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:151
bool active() const noexcept
check if timer is running.
Definition timer.hpp:179
static constexpr int type() noexcept
get the timer type.
Definition timer.hpp:221
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:127
BasicTimer(BasicTimer &&other)=delete
move constructor.
bool oneShot() const noexcept
check if timer is a one-shot timer.
Definition timer.hpp:212
BasicTimer(Reactor &reactor=ReactorThread::reactor())
create instance.
Definition timer.hpp:54
BasicTimer & operator=(const BasicTimer &other)=delete
copy assignment operator.
Event handler interface class.
Definition reactor.hpp:46
friend class Reactor
friendship with reactor.
Definition reactor.hpp:122
static Reactor & reactor()
get the global Reactor instance.
Definition reactor.cpp:514
Reactor class.
Definition reactor.hpp:129
int delHandler(int fd, bool sync=true) noexcept
delete handler from reactor.
Definition reactor.cpp:155
int addHandler(int fd, EventHandler *handler, bool wantRead=true, bool wantWrite=false, bool sync=true) noexcept
add handler to reactor.
Definition reactor.cpp:100
Definition acceptor.hpp:32