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