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
33 namespace webrtc {
34
35 class TickInterval;
36
37 // Class representing the current time.
38 class 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.
83 class 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
115 inline TickInterval operator+(const TickInterval& lhs,
116 const TickInterval& rhs) {
117 return TickInterval(lhs.interval_ + rhs.interval_);
118 }
119
120 inline TickInterval operator-(const TickInterval& lhs,
121 const TickInterval& rhs) {
122 return TickInterval(lhs.interval_ - rhs.interval_);
123 }
124
125 inline TickInterval operator-(const TickTime& lhs, const TickTime& rhs) {
126 return TickInterval(lhs.ticks_ - rhs.ticks_);
127 }
128
129 inline TickTime operator+(const TickTime lhs, const int64_t ticks) {
130 TickTime time = lhs;
131 time.ticks_ += ticks;
132 return time;
133 }
134
135 inline bool operator>(const TickInterval& lhs, const TickInterval& rhs) {
136 return lhs.interval_ > rhs.interval_;
137 }
138
139 inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs) {
140 return lhs.interval_ <= rhs.interval_;
141 }
142
143 inline bool operator<(const TickInterval& lhs, const TickInterval& rhs) {
144 return lhs.interval_ <= rhs.interval_;
145 }
146
147 inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs) {
148 return lhs.interval_ >= rhs.interval_;
149 }
150
TickTime()151 inline TickTime::TickTime()
152 : ticks_(0) {
153 }
154
TickTime(int64_t ticks)155 inline TickTime::TickTime(int64_t ticks)
156 : ticks_(ticks) {
157 }
158
Now()159 inline TickTime TickTime::Now() {
160 if (use_fake_clock_)
161 return TickTime(fake_ticks_);
162 else
163 return TickTime(QueryOsForTicks());
164 }
165
MillisecondTimestamp()166 inline 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
MicrosecondTimestamp()183 inline 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
Ticks()200 inline int64_t TickTime::Ticks() const {
201 return ticks_;
202 }
203
MillisecondsToTicks(const int64_t ms)204 inline 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
TicksToMilliseconds(const int64_t ticks)220 inline 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
236 inline TickTime& TickTime::operator+=(const int64_t& ticks) {
237 ticks_ += ticks;
238 return *this;
239 }
240
TickInterval()241 inline TickInterval::TickInterval() : interval_(0) {
242 }
243
TickInterval(const int64_t interval)244 inline TickInterval::TickInterval(const int64_t interval)
245 : interval_(interval) {
246 }
247
Milliseconds()248 inline 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
Microseconds()267 inline 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
286 inline TickInterval& TickInterval::operator+=(const TickInterval& rhs) {
287 interval_ += rhs.interval_;
288 return *this;
289 }
290
291 inline 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