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");
63 if (_reactor ==
nullptr)
114 template <
class Rep,
class Period,
typename Func>
115 void setOneShot (std::chrono::duration<Rep, Period> duration, Func&& callback)
117 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (duration);
118 _callback = std::forward<Func> (callback);
120 _ns = std::chrono::nanoseconds::zero ();
122 auto ts = toTimerSpec (ns);
123 timerfd_settime (handle (), 0, &ts,
nullptr);
131 template <
class Clock,
class Duration,
typename Func>
132 void setOneShot (std::chrono::time_point<Clock, Duration> timePoint, Func&& callback)
135 (std::is_same<ClockPolicy, RealTime>::value && std::is_same<Clock, std::chrono::system_clock>::value) ||
136 (std::is_same<ClockPolicy, Monotonic>::value &&
137 std::is_same<Clock, std::chrono::steady_clock>::value),
138 "Clock type mismatch timer policy");
140 auto elapsed = timePoint.time_since_epoch ();
141 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (elapsed);
142 _callback = std::forward<Func> (callback);
144 _ns = std::chrono::nanoseconds::zero ();
146 auto ts = toTimerSpec (ns);
147 timerfd_settime (handle (), TFD_TIMER_ABSTIME, &ts,
nullptr);
155 template <
class Rep,
class Period,
typename Func>
156 void setInterval (std::chrono::duration<Rep, Period> duration, Func&& callback)
158 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (duration);
159 _callback = std::forward<Func> (callback);
163 auto ts = toTimerSpec (ns,
true);
164 timerfd_settime (handle (), 0, &ts,
nullptr);
174 _ns = std::chrono::nanoseconds::zero ();
176 struct itimerspec ts = {};
177 timerfd_settime (handle (), 0, &ts,
nullptr);
186 struct itimerspec ts = {};
187 timerfd_gettime (handle (), &ts);
188 const bool hasValue = (ts.it_value.tv_sec != 0 || ts.it_value.tv_nsec != 0);
189 const bool hasInterval = (ts.it_interval.tv_sec != 0 || ts.it_interval.tv_nsec != 0);
190 return hasValue || hasInterval;
199 struct itimerspec ts = {};
200 timerfd_gettime (handle (), &ts);
201 return std::chrono::seconds (ts.it_value.tv_sec) + std::chrono::nanoseconds (ts.it_value.tv_nsec);
208 std::chrono::nanoseconds
interval () const noexcept
226 static constexpr int type () noexcept
228 return ClockPolicy::type ();
236 virtual void onReceive ([[maybe_unused]]
int fd)
override
238 uint64_t expirations;
239 ssize_t result = read (handle (), &expirations,
sizeof (expirations));
240 if (result ==
sizeof (expirations) && _callback)
242 for (uint64_t i = 0; i < expirations; ++i)
255 static constexpr itimerspec toTimerSpec (std::chrono::nanoseconds ns,
bool periodic =
false) noexcept
258 ts.it_value.tv_sec = ns.count () / _nsPerSec;
259 ts.it_value.tv_nsec = ns.count () % _nsPerSec;
262 ts.it_interval.tv_sec = ts.it_value.tv_sec;
263 ts.it_interval.tv_nsec = ts.it_value.tv_nsec;
272 int handle () const noexcept
278 static constexpr uint64_t _nsPerSec = 1000000000ULL;
281 std::function<void ()> _callback;
284 std::chrono::nanoseconds _ns{};
287 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:208
std::chrono::nanoseconds remaining() const noexcept
get the remaining time until expiration.
Definition timer.hpp:197
void setOneShot(std::chrono::duration< Rep, Period > duration, Func &&callback)
arm the timer as a one-shot timer.
Definition timer.hpp:115
void cancel() noexcept
cancel the timer.
Definition timer.hpp:170
~BasicTimer() noexcept
destroy instance.
Definition timer.hpp:100
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:156
bool active() const noexcept
check if timer is running.
Definition timer.hpp:184
static constexpr int type() noexcept
get the timer type.
Definition timer.hpp:226
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:132
BasicTimer(BasicTimer &&other)=delete
move constructor.
bool oneShot() const noexcept
check if timer is a one-shot timer.
Definition timer.hpp:217
BasicTimer & operator=(const BasicTimer &other)=delete
copy assignment operator.
BasicTimer(Reactor *reactor=nullptr)
create instance.
Definition timer.hpp:54
Event handler interface class.
Definition reactor.hpp:46
friend class Reactor
friendship with reactor.
Definition reactor.hpp:113
static Reactor * reactor()
get the global Reactor instance.
Definition reactor.cpp:449
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
Definition acceptor.hpp:32