Open Lighting Architecture  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Clock.h
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  * Clock.h
17  * Provides the TimeInterval and TimeStamp classes.
18  * Copyright (C) 2005-2012 Simon Newton
19  *
20  * The struct timeval can represent both absolute time and time intervals.
21  * We define our own wrapper classes that:
22  * - hide some of the platform differences, like the fact windows doesn't
23  * provide timersub.
24  * - Reduces bugs by using the compiler to check if the value was supposed
25  * to be an interval or absolute time. For example, passing an absolute
26  * time intstead of an Interval to RegisterTimeout would be bad.
27  */
28 
29 #ifndef INCLUDE_OLA_CLOCK_H_
30 #define INCLUDE_OLA_CLOCK_H_
31 
32 #if HAVE_CONFIG_H
33 # include <config.h>
34 #endif
35 
36 #include <ola/base/Macro.h>
37 #include <stdint.h>
38 #include <sys/time.h>
39 
40 #include <iomanip>
41 #include <ostream>
42 #include <sstream>
43 #include <string>
44 
45 
46 namespace ola {
47 
48 static const int USEC_IN_SECONDS = 1000000;
49 static const int ONE_THOUSAND = 1000;
50 
55 class BaseTimeVal {
56  public:
57  // Constructors
58  BaseTimeVal() { timerclear(&m_tv); }
59 
60  BaseTimeVal(int32_t sec, int32_t usec) {
61  m_tv.tv_sec = sec;
62  m_tv.tv_usec = usec;
63  }
64 
65  explicit BaseTimeVal(const struct timeval &timestamp) { m_tv = timestamp; }
66  explicit BaseTimeVal(int64_t interval_useconds) { Set(interval_useconds); }
67 
68  BaseTimeVal(const BaseTimeVal &other) : m_tv(other.m_tv) {}
69 
70  // Assignable
71  BaseTimeVal& operator=(const BaseTimeVal& other) {
72  if (this != &other) {
73  m_tv = other.m_tv;
74  }
75  return *this;
76  }
77 
78  BaseTimeVal& operator=(const struct timeval &tv) {
79  m_tv = tv;
80  return *this;
81  }
82 
83  // Comparables
84  bool operator==(const BaseTimeVal &other) const {
85  return timercmp(&m_tv, &other.m_tv, ==);
86  }
87 
88  bool operator!=(const BaseTimeVal &other) const {
89  return !(*this == other);
90  }
91 
92  bool operator>(const BaseTimeVal &other) const {
93  return timercmp(&m_tv, &other.m_tv, >);
94  }
95 
96  bool operator>=(const BaseTimeVal &other) const {
97  return timercmp(&m_tv, &other.m_tv, >=);
98  }
99 
100  bool operator<(const BaseTimeVal &other) const {
101  return timercmp(&m_tv, &other.m_tv, <);
102  }
103 
104  bool operator<=(const BaseTimeVal &other) const {
105  return timercmp(&m_tv, &other.m_tv, <=);
106  }
107 
108  // Arithmetic
109  BaseTimeVal& operator+=(const BaseTimeVal& other) {
110  if (this != &other) {
111  timeradd(&m_tv, &other.m_tv, &m_tv);
112  }
113  return *this;
114  }
115 
116  BaseTimeVal &operator-=(const BaseTimeVal &other) {
117  if (this != &other) {
118  TimerSub(m_tv, other.m_tv, &m_tv);
119  }
120  return *this;
121  }
122 
123  const BaseTimeVal operator+(const BaseTimeVal &interval) const {
124  BaseTimeVal result = *this;
125  result += interval;
126  return result;
127  }
128 
129  const BaseTimeVal operator-(const BaseTimeVal &other) const {
130  BaseTimeVal result;
131  TimerSub(m_tv, other.m_tv, &result.m_tv);
132  return result;
133  }
134 
135  BaseTimeVal operator*(unsigned int i) const {
136  int64_t as_int = (*this).AsInt();
137  as_int *= i;
138  return BaseTimeVal(as_int);
139  }
140 
141  // Various other methods.
142  bool IsSet() const {
143  return timerisset(&m_tv);
144  }
145 
146  void AsTimeval(struct timeval *tv) const {
147  *tv = m_tv;
148  }
149 
150  // Returns the seconds portion.
151  time_t Seconds() const { return m_tv.tv_sec; }
152  // Returns the microseconds portion
153  suseconds_t MicroSeconds() const { return m_tv.tv_usec; }
154 
155  // Returns the entire BaseTimeVal as milliseconds
156  int64_t InMilliSeconds() const {
157  return (m_tv.tv_sec * static_cast<int64_t>(ONE_THOUSAND) +
158  m_tv.tv_usec / ONE_THOUSAND);
159  }
160 
161  // Returns the entire BaseTimeVal as microseconds.
162  int64_t AsInt() const {
163  return (m_tv.tv_sec * static_cast<int64_t>(USEC_IN_SECONDS) +
164  m_tv.tv_usec);
165  }
166 
167  std::string ToString() const {
168  std::stringstream str;
169  str << m_tv.tv_sec << "." << std::setfill('0') << std::setw(6)
170  << m_tv.tv_usec;
171  return str.str();
172  }
173 
174  private:
175  struct timeval m_tv;
176 
180  void TimerSub(const struct timeval &tv1, const struct timeval &tv2,
181  struct timeval *result) const {
182  result->tv_sec = tv1.tv_sec - tv2.tv_sec;
183  result->tv_usec = tv1.tv_usec - tv2.tv_usec;
184  if (result->tv_usec < 0) {
185  result->tv_sec--;
186  result->tv_usec += USEC_IN_SECONDS;
187  }
188  }
189 
190  void Set(int64_t interval_useconds) {
191 #ifdef HAVE_TIME_T
192  m_tv.tv_sec = static_cast<time_t>(
193  interval_useconds / USEC_IN_SECONDS);
194 #else
195  m_tv.tv_sec = interval_useconds / USEC_IN_SECONDS;
196 #endif
197 
198 #ifdef HAVE_SUSECONDS_T
199  m_tv.tv_usec = static_cast<suseconds_t>(
200  interval_useconds % USEC_IN_SECONDS);
201 #else
202  m_tv.tv_usec = interval_useconds % USEC_IN_SECONDS;
203 #endif
204  }
205 };
206 
207 /*
208  * A time interval, with usecond accuracy.
209  */
211  public:
212  // Constructors
213  TimeInterval() {}
214  TimeInterval(int32_t sec, int32_t usec) : m_interval(sec, usec) {}
215  explicit TimeInterval(int64_t usec) : m_interval(usec) {}
216 
217  TimeInterval(const TimeInterval &other) : m_interval(other.m_interval) {}
218 
219  // Assignable
220  TimeInterval& operator=(const TimeInterval& other) {
221  if (this != &other) {
222  m_interval = other.m_interval;
223  }
224  return *this;
225  }
226 
227  // Comparables
228  bool operator==(const TimeInterval &other) const {
229  return m_interval == other.m_interval;
230  }
231 
232  bool operator!=(const TimeInterval &other) const {
233  return m_interval != other.m_interval;
234  }
235 
236  bool operator>(const TimeInterval &other) const {
237  return m_interval > other.m_interval;
238  }
239 
240  bool operator>=(const TimeInterval &other) const {
241  return m_interval >= other.m_interval;
242  }
243 
244  bool operator<(const TimeInterval &other) const {
245  return m_interval < other.m_interval;
246  }
247 
248  bool operator<=(const TimeInterval &other) const {
249  return m_interval <= other.m_interval;
250  }
251 
252  // Arithmetic
253  TimeInterval& operator+=(const TimeInterval& other) {
254  if (this != &other) {
255  m_interval += other.m_interval;
256  }
257  return *this;
258  }
259 
260  TimeInterval operator*(unsigned int i) const {
261  return TimeInterval(m_interval * i);
262  }
263 
264  // Various other methods.
265  bool IsZero() const { return !m_interval.IsSet(); }
266 
267  void AsTimeval(struct timeval *tv) const { m_interval.AsTimeval(tv); }
268 
269  time_t Seconds() const { return m_interval.Seconds(); }
270  suseconds_t MicroSeconds() const { return m_interval.MicroSeconds(); }
271 
272  int64_t InMilliSeconds() const { return m_interval.InMilliSeconds(); }
273  int64_t AsInt() const { return m_interval.AsInt(); }
274 
275  std::string ToString() const { return m_interval.ToString(); }
276 
277  friend std::ostream& operator<< (std::ostream &out,
278  const TimeInterval &interval) {
279  return out << interval.m_interval.ToString();
280  }
281 
282  private:
283  explicit TimeInterval(const BaseTimeVal &time_val) : m_interval(time_val) {}
284 
285  BaseTimeVal m_interval;
286  friend class TimeStamp;
287 };
288 
289 
290 /*
291  * Represents a point in time with usecond accuracy.
292  */
293 class TimeStamp {
294  public:
295  // Constructors
296  TimeStamp() {}
297  explicit TimeStamp(const struct timeval &timestamp) : m_tv(timestamp) {}
298 
299  TimeStamp(const TimeStamp &other) : m_tv(other.m_tv) {}
300 
301  // Assignable
302  TimeStamp& operator=(const TimeStamp& other) {
303  if (this != &other) {
304  m_tv = other.m_tv;
305  }
306  return *this;
307  }
308 
309  TimeStamp& operator=(const struct timeval &tv) {
310  m_tv = tv;
311  return *this;
312  }
313 
314  // Comparables
315  bool operator==(const TimeStamp &other) const { return m_tv == other.m_tv; }
316  bool operator!=(const TimeStamp &other) const { return m_tv != other.m_tv; }
317  bool operator>(const TimeStamp &other) const { return m_tv > other.m_tv; }
318  bool operator>=(const TimeStamp &other) const { return m_tv >= other.m_tv; }
319  bool operator<(const TimeStamp &other) const { return m_tv < other.m_tv; }
320  bool operator<=(const TimeStamp &other) const { return m_tv <= other.m_tv; }
321 
322  // Arithmetic
323  TimeStamp &operator+=(const TimeInterval &interval) {
324  m_tv += interval.m_interval;
325  return *this;
326  }
327 
328  TimeStamp &operator-=(const TimeInterval &interval) {
329  m_tv -= interval.m_interval;
330  return *this;
331  }
332 
333  const TimeStamp operator+(const TimeInterval &interval) const {
334  return TimeStamp(m_tv + interval.m_interval);
335  }
336 
337  const TimeInterval operator-(const TimeStamp &other) const {
338  return TimeInterval(m_tv - other.m_tv);
339  }
340 
341  const TimeStamp operator-(const TimeInterval &interval) const {
342  return TimeStamp(m_tv - interval.m_interval);
343  }
344 
345  // Various other methods.
346  bool IsSet() const { return m_tv.IsSet(); }
347 
348  time_t Seconds() const { return m_tv.Seconds(); }
349  suseconds_t MicroSeconds() const { return m_tv.MicroSeconds(); }
350 
351  std::string ToString() const { return m_tv.ToString(); }
352 
353  friend std::ostream& operator<< (std::ostream &out,
354  const TimeStamp &timestamp) {
355  return out << timestamp.m_tv.ToString();
356  }
357 
358  private:
359  BaseTimeVal m_tv;
360 
361  explicit TimeStamp(const BaseTimeVal &time_val) : m_tv(time_val) {}
362 };
363 
364 
365 /*
366  * Used to get the current time.
367  */
368 class Clock {
369  public:
370  Clock() {}
371  virtual ~Clock() {}
372  virtual void CurrentTime(TimeStamp *timestamp) const {
373  struct timeval tv;
374  gettimeofday(&tv, NULL);
375  *timestamp = tv;
376  }
377 
378  private:
380 };
381 
382 
386 class MockClock: public Clock {
387  public:
388  MockClock() : Clock() {}
389 
390  // Advance the time
391  void AdvanceTime(const TimeInterval &interval) {
392  m_offset += interval;
393  }
394 
395  void AdvanceTime(int32_t sec, int32_t usec) {
396  TimeInterval interval(sec, usec);
397  m_offset += interval;
398  }
399 
400  void CurrentTime(TimeStamp *timestamp) const {
401  struct timeval tv;
402  gettimeofday(&tv, NULL);
403  *timestamp = tv;
404  *timestamp += m_offset;
405  }
406  private:
407  TimeInterval m_offset;
408 };
409 } // namespace ola
410 #endif // INCLUDE_OLA_CLOCK_H_