ge211
ge211_time.h
1 #pragma once
2 
3 #include "ge211_forward.h"
4 
5 #include <chrono>
6 #include <ratio>
7 #include <thread>
8 
9 namespace ge211 {
10 
11 namespace detail {
12 
13 using Clock = std::conditional_t<
14  std::chrono::high_resolution_clock::is_steady,
15  std::chrono::high_resolution_clock,
16  std::chrono::steady_clock>;
17 
18 } // end namespace detail
19 
21 namespace time {
22 
30 class Duration
31 {
32 public:
34  Duration() : duration_{} {}
35 
37  explicit Duration(double seconds)
38  : Duration{std::chrono::duration<double>{seconds}} {}
39 
41  double seconds() const
42  {
43  auto seconds =
44  std::chrono::duration_cast<std::chrono::duration<double>>(
45  duration_);
46  return seconds.count();
47  }
48 
50  long milliseconds() const
51  {
52  auto millis =
53  std::chrono::duration_cast<std::chrono::duration<long, std::milli>>(
54  duration_);
55  return millis.count();
56  }
57 
60 
61  bool operator==(Duration other) const
62  {
63  return duration_ == other.duration_;
64  }
65 
66  bool operator!=(Duration other) const
67  {
68  return duration_ != other.duration_;
69  }
70 
71  bool operator<(Duration other) const
72  {
73  return duration_ < other.duration_;
74  }
75 
76  bool operator<=(Duration other) const
77  {
78  return duration_ <= other.duration_;
79  }
80 
81  bool operator>(Duration other) const
82  {
83  return duration_ > other.duration_;
84  }
85 
86  bool operator>=(Duration other) const
87  {
88  return duration_ >= other.duration_;
89  }
90 
92 
95 
96  Duration operator+(Duration other) const
97  {
98  return {duration_ + other.duration_};
99  }
100 
101  Duration operator-(Duration other) const
102  {
103  return {duration_ - other.duration_};
104  }
105 
106  Duration operator*(double factor) const
107  {
108  return {duration_ * factor};
109  }
110 
111  Duration operator/(double factor) const
112  {
113  return {duration_ / factor};
114  }
115 
116  Duration& operator+=(Duration other)
117  {
118  return *this = *this + other;
119  }
120 
121  Duration& operator-=(Duration other)
122  {
123  return *this = *this - other;
124  }
125 
126  Duration& operator*=(double factor)
127  {
128  return *this = *this * factor;
129  }
130 
131  Duration& operator/=(double factor)
132  {
133  return *this = *this / factor;
134  }
135 
137 
138 private:
139  friend Time_point;
140  friend detail::Engine;
141 
142  Duration(std::chrono::duration<double> duration)
143  : Duration{std::chrono::duration_cast<detail::Clock::duration>
144  (duration)} {}
145 
146  Duration(detail::Clock::duration duration)
147  : duration_{duration} {}
148 
149  void sleep_for() const
150  {
151  std::this_thread::sleep_for(duration_);
152  }
153 
154  detail::Clock::duration duration_;
155 };
156 
161 {
162 public:
164  Time_point() : time_point_{} {}
165 
167  static Time_point now() { return Time_point(detail::Clock::now()); }
168 
171 
172  bool operator==(Time_point other) const
173  {
174  return time_point_ == other.time_point_;
175  }
176 
177  bool operator!=(Time_point other) const
178  {
179  return time_point_ != other.time_point_;
180  }
181 
182  bool operator<(Time_point other) const
183  {
184  return time_point_ < other.time_point_;
185  }
186 
187  bool operator<=(Time_point other) const
188  {
189  return time_point_ <= other.time_point_;
190  }
191 
192  bool operator>(Time_point other) const
193  {
194  return time_point_ > other.time_point_;
195  }
196 
197  bool operator>=(Time_point other) const
198  {
199  return time_point_ >= other.time_point_;
200  }
201 
203 
206 
207  Duration operator-(Time_point other) const
208  {
209  return Duration{time_point_ - other.time_point_};
210  }
211 
212  Time_point operator+(Duration duration) const
213  {
214  return Time_point{time_point_ + duration.duration_};
215  }
216 
217  Time_point operator-(Duration duration) const
218  {
219  return Time_point{time_point_ - duration.duration_};
220  }
221 
222  Time_point& operator+=(Duration duration)
223  {
224  return *this = *this + duration;
225  }
226 
227  Time_point& operator-=(Duration duration)
228  {
229  return *this = *this - duration;
230  }
231 
233 
234 private:
235  Time_point(detail::Clock::time_point time_point)
236  : time_point_{time_point} {}
237 
238  detail::Clock::time_point time_point_;
239 };
240 
242 class Timer
243 {
244 public:
246  Timer() : start_time_{now_()} {}
247 
253  static Timer future(Duration duration)
254  {
255  Timer result;
256  result.start_time_ += duration;
257  return result;
258  }
259 
262  {
263  Time_point previous = start_time_;
264  start_time_ = now_();
265  return start_time_ - previous;
266  }
267 
272  {
273  return start_time_;
274  }
275 
280  {
281  return now_() - start_time_;
282  }
283 
284 private:
285  Time_point start_time_;
286 
287  static Time_point now_() { return Time_point::now(); }
288 };
289 
292 {
293 public:
296  explicit Pausable_timer(bool start_paused = false)
297  {
298  is_paused_ = start_paused;
299 
300  if (is_paused_)
301  elapsed_time_ = Duration{};
302  else
303  fake_start_time_ = now_();
304  }
305 
307  bool is_paused() const
308  {
309  return is_paused_;
310  }
311 
316  {
317  if (is_paused_) {
318  return elapsed_time_;
319  } else {
320  return now_() - fake_start_time_;
321  }
322  }
323 
329  {
330  if (!is_paused_) {
331  elapsed_time_ = now_() - fake_start_time_;
332  is_paused_ = true;
333  }
334 
335  return elapsed_time_;
336  }
337 
339  void resume()
340  {
341  if (is_paused_) {
342  fake_start_time_ = now_() - elapsed_time_;
343  is_paused_ = false;
344  }
345  }
346 
350  {
351  if (is_paused_) {
352  auto result = elapsed_time_;
353  elapsed_time_ = Duration{};
354  return result;
355  } else {
356  auto now = now_();
357  auto result = now - fake_start_time_;
358  fake_start_time_ = now;
359  return result;
360  }
361  }
362 
363 private:
364  union
365  {
366  Time_point fake_start_time_; // when not paused
367  Duration elapsed_time_; // when paused
368  };
369  bool is_paused_;
370 
371  static Time_point now_() { return Time_point::now(); }
372 };
373 
374 } // end namespace time
375 
376 }
377 
Duration reset()
Resets the timer, returning the elapsed time since starting or the most recent reset().
Definition: ge211_time.h:349
A class for timing intervals. The result is a Duration.
Definition: ge211_time.h:242
Duration elapsed_time() const
Returns how much time has elapsed since this timer was started or most recently reset.
Definition: ge211_time.h:279
The game engine namespace.
Definition: ge211.h:17
static Timer future(Duration duration)
Creates a timer whose “start time” is some Duration in the future.
Definition: ge211_time.h:253
bool is_paused() const
Checks whether the timer is currently paused.
Definition: ge211_time.h:307
Duration()
Constructs the zero duration.
Definition: ge211_time.h:34
A point in time.
Definition: ge211_time.h:160
Duration reset()
Resets a timer, returning the time it was at before it was reset.
Definition: ge211_time.h:261
double seconds() const
Gets this duration in seconds.
Definition: ge211_time.h:41
Duration elapsed_time() const
The elapsed time since the start or most recent reset, not counting paused times. ...
Definition: ge211_time.h:315
void resume()
Unpauses the timer. If the timer is already running, has no effect.
Definition: ge211_time.h:339
Duration(double seconds)
Constructs the duration of the given number of seconds.
Definition: ge211_time.h:37
A class for timing intervals while supporting pausing.
Definition: ge211_time.h:291
Time_point()
Constructs the zero time point (the epoch).
Definition: ge211_time.h:164
Duration pause()
Pauses the timer.
Definition: ge211_time.h:328
Timer()
Creates a new timer, running from the time it was created.
Definition: ge211_time.h:246
long milliseconds() const
Gets this duration, approximately, in milliseconds.
Definition: ge211_time.h:50
A length of time.
Definition: ge211_time.h:30
Time_point start_time() const
Returns the actual time when this timer was started or most recently reset.
Definition: ge211_time.h:271
static Time_point now()
Returns the current time.
Definition: ge211_time.h:167
Pausable_timer(bool start_paused=false)
Constructs a new pausable timer.
Definition: ge211_time.h:296