hmbdc
simplify-high-performance-messaging-programming
Timers.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 
4 #include "hmbdc/time/Time.hpp"
5 #include "hmbdc/Exception.hpp"
6 #include "hmbdc/Compile.hpp"
7 
8 #include <functional>
9 #include <algorithm>
10 
11 #include <stdexcept>
12 #include <ctime>
13 
14 #include <boost/intrusive/set.hpp>
15 
16 
17 namespace hmbdc { namespace time {
18 struct TimerManager;
19 namespace timers_detail {
20  void noop(TimerManager&, SysTime const&);
21 }
22 
23 struct Timer
24 : boost::intrusive::set_base_hook<
25  boost::intrusive::link_mode<boost::intrusive::normal_link>
26  //the default safe_link appears too strict since many times the object is deleted
27  //before the container(TimerManager) is deleted and assert fires unnecesarily in that case
28 > {
29 protected:
30  SysTime getFireAt() const { return fireAt_; }
31 
32 public:
33  using Callback = std::function<void (TimerManager&, SysTime const&)>;
34  Timer(Callback cb = timers_detail::noop)
35  : armed(false)
36  , callback_(cb)
37  {}
38  void setCallback(Callback cb) {
39  callback_ = cb;
40  }
41  friend struct TimerManager;
42  bool operator < (Timer const& other) const
43  { return fireAt_ < other.fireAt_; }
44  bool operator <= (SysTime const& t) const
45  { return !(t < fireAt_); }
46 
47  virtual ~Timer(){}
48 
49 private:
50  void fired(TimerManager& tm, SysTime const& now) {
51  callback_(tm, now);
52  }
53  bool armed;
54  SysTime fireAt_;
55  Callback callback_;
56  virtual void reschedule(TimerManager& tm, SysTime const& now) = 0;
57 };
58 
59 namespace timers_detail {
60 inline
61 void noop(TimerManager&, SysTime const&)
62 {}
63 
64 } //timers_detail
65 
66 struct TimerManager {
67  /**
68  * @brief schedule the timer to start at a specific time
69  * @details make sure the Timer is not already scheduled
70  * otherwise undefined behavior
71  *
72  * @param fireAt the firing time
73  * @param timer the timer to fire
74  */
75  void schedule(SysTime fireAt, Timer& timer) {
76  timer.fireAt_ = fireAt;
77  timers_.insert(timer);
78  timer.armed = true;
79  }
80  /**
81  * @brief cancel a timer previously scheduled with the TimerManager
82  * @details if not scheduled, no effect
83  *
84  * @param timer to be canceled
85  */
86  void cancel(Timer& timer) {
87  auto range = timers_.equal_range(timer);
88  for (auto it = range.first; it != range.second; ++it) {
89  if (&*it == &timer) {
90  timers_.erase(it);
91  timer.armed = false;
92  return;
93  }
94  }
95  }
96 
97  void checkTimers(time::SysTime);
98 
99  Duration untilNextFire() const {
100  auto res = std::numeric_limits<Duration>::max();
101  if (timers_.begin() != timers_.end()) {
102  res = std::max(Duration(0), timers_.begin()->fireAt_ - SysTime::now());
103  }
104  return res;
105  }
106 
107 private:
108  using Timers = boost::intrusive::multiset<Timer>;
109  Timers timers_;
110 };
111 
112 
114  ReoccuringTimer(Duration const& interval, Callback callback = timers_detail::noop)
115  : Timer(callback)
116  , interval(interval)
117  {}
118  const Duration interval;
119 private:
120  virtual void reschedule(TimerManager& tm, SysTime const& now)
121  { tm.schedule(now + interval, *this); };
122 };
123 
124 struct DailyTimer : Timer {
125  DailyTimer(Callback callback = timers_detail::noop)
126  : Timer(callback)
127  {}
128 private:
129  virtual void reschedule(TimerManager& tm, SysTime const& now) {
130  Duration day = Duration::seconds(86400);
131  SysTime newFireTime = getFireAt() + day;
132  while (newFireTime < now) newFireTime += day;
133  tm.schedule(newFireTime, *this);
134  };
135 };
136 
137 struct OneTimeTimer : Timer {
138  OneTimeTimer(Callback callback = timers_detail::noop)
139  : Timer(callback)
140  {}
141 
142 private:
143  virtual void reschedule(TimerManager&, SysTime const&){};
144 };
145 
146 }}
Definition: Timers.hpp:23
Definition: Timers.hpp:66
Definition: Timers.hpp:124
void cancel(Timer &timer)
cancel a timer previously scheduled with the TimerManager
Definition: Timers.hpp:86
Definition: Time.hpp:14
Definition: Timers.hpp:137
void schedule(SysTime fireAt, Timer &timer)
schedule the timer to start at a specific time
Definition: Timers.hpp:75
Definition: Time.hpp:133
Definition: Base.hpp:13
Definition: Timers.hpp:113