1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11// System independant wrapper for polling elapsed time in ms and us.
12// The implementation works in the tick domain which can be mapped over to the
13// time domain.
14#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
15#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
16
17#if _WIN32
18// Note: The Windows header must always be included before mmsystem.h
19#include <windows.h>
20#include <mmsystem.h>
21#elif WEBRTC_LINUX
22#include <time.h>
23#elif WEBRTC_MAC
24#include <mach/mach_time.h>
25#include <string.h>
26#else
27#include <sys/time.h>
28#include <time.h>
29#endif
30
31#include "webrtc/typedefs.h"
32
33namespace webrtc {
34
35class TickInterval;
36
37// Class representing the current time.
38class TickTime {
39 public:
40  TickTime();
41  explicit TickTime(int64_t ticks);
42
43  // Current time in the tick domain.
44  static TickTime Now();
45
46  // Now in the time domain in ms.
47  static int64_t MillisecondTimestamp();
48
49  // Now in the time domain in us.
50  static int64_t MicrosecondTimestamp();
51
52  // Returns the number of ticks in the tick domain.
53  int64_t Ticks() const;
54
55  static int64_t MillisecondsToTicks(const int64_t ms);
56
57  static int64_t TicksToMilliseconds(const int64_t ticks);
58
59  // Returns a TickTime that is ticks later than the passed TickTime.
60  friend TickTime operator+(const TickTime lhs, const int64_t ticks);
61  TickTime& operator+=(const int64_t& ticks);
62
63  // Returns a TickInterval that is the difference in ticks beween rhs and lhs.
64  friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
65
66  // Call to engage the fake clock. This is useful for tests since relying on
67  // a real clock often makes the test flaky.
68  static void UseFakeClock(int64_t start_millisecond);
69
70  // Advance the fake clock. Must be called after UseFakeClock.
71  static void AdvanceFakeClock(int64_t milliseconds);
72
73 private:
74  static int64_t QueryOsForTicks();
75
76  static bool use_fake_clock_;
77  static int64_t fake_ticks_;
78
79  int64_t ticks_;
80};
81
82// Represents a time delta in ticks.
83class TickInterval {
84 public:
85  TickInterval();
86
87  int64_t Milliseconds() const;
88  int64_t Microseconds() const;
89
90  // Returns the sum of two TickIntervals as a TickInterval.
91  friend TickInterval operator+(const TickInterval& lhs,
92                                const TickInterval& rhs);
93  TickInterval& operator+=(const TickInterval& rhs);
94
95  // Returns a TickInterval corresponding to rhs - lhs.
96  friend TickInterval operator-(const TickInterval& lhs,
97                                const TickInterval& rhs);
98  TickInterval& operator-=(const TickInterval& rhs);
99
100  friend bool operator>(const TickInterval& lhs, const TickInterval& rhs);
101  friend bool operator<=(const TickInterval& lhs, const TickInterval& rhs);
102  friend bool operator<(const TickInterval& lhs, const TickInterval& rhs);
103  friend bool operator>=(const TickInterval& lhs, const TickInterval& rhs);
104
105 private:
106  explicit TickInterval(int64_t interval);
107
108  friend class TickTime;
109  friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
110
111 private:
112  int64_t interval_;
113};
114
115inline TickInterval operator+(const TickInterval& lhs,
116                              const TickInterval& rhs) {
117  return TickInterval(lhs.interval_ + rhs.interval_);
118}
119
120inline TickInterval operator-(const TickInterval& lhs,
121                              const TickInterval& rhs) {
122  return TickInterval(lhs.interval_ - rhs.interval_);
123}
124
125inline TickInterval operator-(const TickTime& lhs, const TickTime& rhs) {
126  return TickInterval(lhs.ticks_ - rhs.ticks_);
127}
128
129inline TickTime operator+(const TickTime lhs, const int64_t ticks) {
130  TickTime time = lhs;
131  time.ticks_ += ticks;
132  return time;
133}
134
135inline bool operator>(const TickInterval& lhs, const TickInterval& rhs) {
136  return lhs.interval_ > rhs.interval_;
137}
138
139inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs) {
140  return lhs.interval_ <= rhs.interval_;
141}
142
143inline bool operator<(const TickInterval& lhs, const TickInterval& rhs) {
144  return lhs.interval_ <= rhs.interval_;
145}
146
147inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs) {
148  return lhs.interval_ >= rhs.interval_;
149}
150
151inline TickTime::TickTime()
152    : ticks_(0) {
153}
154
155inline TickTime::TickTime(int64_t ticks)
156    : ticks_(ticks) {
157}
158
159inline TickTime TickTime::Now() {
160  if (use_fake_clock_)
161    return TickTime(fake_ticks_);
162  else
163    return TickTime(QueryOsForTicks());
164}
165
166inline int64_t TickTime::MillisecondTimestamp() {
167  int64_t ticks = TickTime::Now().Ticks();
168#if _WIN32
169#ifdef USE_QUERY_PERFORMANCE_COUNTER
170  LARGE_INTEGER qpfreq;
171  QueryPerformanceFrequency(&qpfreq);
172  return (ticks * 1000) / qpfreq.QuadPart;
173#else
174  return ticks;
175#endif
176#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
177  return ticks / 1000000LL;
178#else
179  return ticks / 1000LL;
180#endif
181}
182
183inline int64_t TickTime::MicrosecondTimestamp() {
184  int64_t ticks = TickTime::Now().Ticks();
185#if _WIN32
186#ifdef USE_QUERY_PERFORMANCE_COUNTER
187  LARGE_INTEGER qpfreq;
188  QueryPerformanceFrequency(&qpfreq);
189  return (ticks * 1000) / (qpfreq.QuadPart / 1000);
190#else
191  return ticks * 1000LL;
192#endif
193#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
194  return ticks / 1000LL;
195#else
196  return ticks;
197#endif
198}
199
200inline int64_t TickTime::Ticks() const {
201  return ticks_;
202}
203
204inline int64_t TickTime::MillisecondsToTicks(const int64_t ms) {
205#if _WIN32
206#ifdef USE_QUERY_PERFORMANCE_COUNTER
207  LARGE_INTEGER qpfreq;
208  QueryPerformanceFrequency(&qpfreq);
209  return (qpfreq.QuadPart * ms) / 1000;
210#else
211  return ms;
212#endif
213#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
214  return ms * 1000000LL;
215#else
216  return ms * 1000LL;
217#endif
218}
219
220inline int64_t TickTime::TicksToMilliseconds(const int64_t ticks) {
221#if _WIN32
222#ifdef USE_QUERY_PERFORMANCE_COUNTER
223  LARGE_INTEGER qpfreq;
224  QueryPerformanceFrequency(&qpfreq);
225  return (ticks * 1000) / qpfreq.QuadPart;
226#else
227  return ticks;
228#endif
229#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
230  return ticks / 1000000LL;
231#else
232  return ticks / 1000LL;
233#endif
234}
235
236inline TickTime& TickTime::operator+=(const int64_t& ticks) {
237  ticks_ += ticks;
238  return *this;
239}
240
241inline TickInterval::TickInterval() : interval_(0) {
242}
243
244inline TickInterval::TickInterval(const int64_t interval)
245  : interval_(interval) {
246}
247
248inline int64_t TickInterval::Milliseconds() const {
249#if _WIN32
250#ifdef USE_QUERY_PERFORMANCE_COUNTER
251  LARGE_INTEGER qpfreq;
252  QueryPerformanceFrequency(&qpfreq);
253  return (interval_ * 1000) / qpfreq.QuadPart;
254#else
255  // interval_ is in ms
256  return interval_;
257#endif
258#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
259  // interval_ is in ns
260  return interval_ / 1000000;
261#else
262  // interval_ is usecs
263  return interval_ / 1000;
264#endif
265}
266
267inline int64_t TickInterval::Microseconds() const {
268#if _WIN32
269#ifdef USE_QUERY_PERFORMANCE_COUNTER
270  LARGE_INTEGER qpfreq;
271  QueryPerformanceFrequency(&qpfreq);
272  return (interval_ * 1000000) / qpfreq.QuadPart;
273#else
274  // interval_ is in ms
275  return interval_ * 1000LL;
276#endif
277#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
278  // interval_ is in ns
279  return interval_ / 1000;
280#else
281  // interval_ is usecs
282  return interval_;
283#endif
284}
285
286inline TickInterval& TickInterval::operator+=(const TickInterval& rhs) {
287  interval_ += rhs.interval_;
288  return *this;
289}
290
291inline TickInterval& TickInterval::operator-=(const TickInterval& rhs) {
292  interval_ -= rhs.interval_;
293  return *this;
294}
295
296}  // namespace webrtc
297
298#endif  // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
299