1 /*
2 * Copyright (c) 2011 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 #include <windows.h>
19 #include <mmsystem.h>
20 #elif WEBRTC_LINUX
21 #include <ctime>
22 #else
23 #include <sys/time.h>
24 #include <time.h>
25 #endif
26
27 #include "typedefs.h"
28
29 namespace webrtc {
30 class TickInterval;
31
32 class TickTime
33 {
34 public:
35 // Current time in the tick domain.
36 static TickTime Now();
37
38 // Now in the time domain in ms.
39 static WebRtc_Word64 MillisecondTimestamp();
40
41 // Now in the time domain in us.
42 static WebRtc_Word64 MicrosecondTimestamp();
43
44 WebRtc_Word64 Ticks() const;
45
46 static WebRtc_Word64 MillisecondsToTicks(const WebRtc_Word64 ms);
47
48 static WebRtc_Word64 TicksToMilliseconds(const WebRtc_Word64 ticks);
49
50 // Returns a TickTime that is ticks later than the passed TickTime
51 friend TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks);
52 TickTime& operator+=(const WebRtc_Word64& rhs);
53
54
55 // Returns a TickInterval that is the difference in ticks beween rhs and lhs
56 friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
57 private:
58 WebRtc_Word64 _ticks;
59 };
60
61 class TickInterval
62 {
63 public:
64 TickInterval();
65
66 WebRtc_Word64 Milliseconds() const;
67 WebRtc_Word64 Microseconds() const;
68
69 // Returns the sum of two TickIntervals as a TickInterval
70 friend TickInterval operator+(const TickInterval& lhs,
71 const TickInterval& rhs);
72 TickInterval& operator-=(const TickInterval& rhs);
73
74 // Returns a TickInterval corresponding to rhs - lhs
75 friend TickInterval operator-(const TickInterval& lhs,
76 const TickInterval& rhs);
77 TickInterval& operator+=(const TickInterval& rhs);
78
79 private:
80 TickInterval(WebRtc_Word64 interval);
81
82 friend class TickTime;
83 friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
84
85 private:
86 WebRtc_Word64 _interval;
87 };
88
89 inline TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs)
90 {
91 return TickInterval(lhs._interval + rhs._interval);
92 }
93
94 inline TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs)
95 {
96 return TickInterval(lhs._interval - rhs._interval);
97 }
98
99 inline TickInterval operator-(const TickTime& lhs,const TickTime& rhs)
100 {
101 return TickInterval(lhs._ticks - rhs._ticks);
102 }
103
104 inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks)
105 {
106 TickTime time = lhs;
107 time._ticks += ticks;
108 return time;
109 }
110
Now()111 inline TickTime TickTime::Now()
112 {
113 TickTime result;
114 #if _WIN32
115 #ifdef USE_QUERY_PERFORMANCE_COUNTER
116 // QueryPerformanceCounter returns the value from the TSC which is
117 // incremented at the CPU frequency. The algorithm used requires
118 // the CPU frequency to be constant. Technology like speed stepping
119 // which has variable CPU frequency will therefore yield unpredictable,
120 // incorrect time estimations.
121 LARGE_INTEGER qpcnt;
122 QueryPerformanceCounter(&qpcnt);
123 result._ticks = qpcnt.QuadPart;
124 #else
125 static volatile LONG lastTimeGetTime = 0;
126 static volatile WebRtc_Word64 numWrapTimeGetTime = 0;
127 volatile LONG* lastTimeGetTimePtr = &lastTimeGetTime;
128 DWORD now = timeGetTime();
129 // Atomically update the last gotten time
130 DWORD old = InterlockedExchange(lastTimeGetTimePtr, now);
131 if(now < old)
132 {
133 // If now is earlier than old, there may have been a race between
134 // threads.
135 // 0x0fffffff ~3.1 days, the code will not take that long to execute
136 // so it must have been a wrap around.
137 if(old > 0xf0000000 && now < 0x0fffffff)
138 {
139 numWrapTimeGetTime++;
140 }
141 }
142 result._ticks = now + (numWrapTimeGetTime<<32);
143 #endif
144 #elif defined(WEBRTC_LINUX)
145 struct timespec ts;
146 #ifdef WEBRTC_CLOCK_TYPE_REALTIME
147 clock_gettime(CLOCK_REALTIME, &ts);
148 #else
149 clock_gettime(CLOCK_MONOTONIC, &ts);
150 #endif
151 result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec);
152 #else
153 struct timeval tv;
154 gettimeofday(&tv, NULL);
155 result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(tv.tv_usec);
156 #endif
157 return result;
158 }
159
MillisecondTimestamp()160 inline WebRtc_Word64 TickTime::MillisecondTimestamp()
161 {
162 TickTime now = TickTime::Now();
163 #if _WIN32
164 #ifdef USE_QUERY_PERFORMANCE_COUNTER
165 LARGE_INTEGER qpfreq;
166 QueryPerformanceFrequency(&qpfreq);
167 return (now._ticks * 1000) / qpfreq.QuadPart;
168 #else
169 return now._ticks;
170 #endif
171 #elif WEBRTC_LINUX
172 return now._ticks / 1000000LL;
173 #else
174 return now._ticks / 1000LL;
175 #endif
176 }
177
MicrosecondTimestamp()178 inline WebRtc_Word64 TickTime::MicrosecondTimestamp()
179 {
180 TickTime now = TickTime::Now();
181
182 #if _WIN32
183 #ifdef USE_QUERY_PERFORMANCE_COUNTER
184 LARGE_INTEGER qpfreq;
185 QueryPerformanceFrequency(&qpfreq);
186 return (now._ticks * 1000) / (qpfreq.QuadPart/1000);
187 #else
188 return now._ticks *1000LL;
189 #endif
190 #elif WEBRTC_LINUX
191 return now._ticks / 1000LL;
192 #else
193 return now._ticks;
194 #endif
195 }
196
Ticks()197 inline WebRtc_Word64 TickTime::Ticks() const
198 {
199 return _ticks;
200 }
201
MillisecondsToTicks(const WebRtc_Word64 ms)202 inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms)
203 {
204 #if _WIN32
205 #ifdef USE_QUERY_PERFORMANCE_COUNTER
206 LARGE_INTEGER qpfreq;
207 QueryPerformanceFrequency(&qpfreq);
208 return (qpfreq.QuadPart * ms) / 1000;
209 #else
210 return ms;
211 #endif
212 #elif WEBRTC_LINUX
213 return ms * 1000000LL;
214 #else
215 return ms * 1000LL;
216 #endif
217 }
218
TicksToMilliseconds(const WebRtc_Word64 ticks)219 inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks)
220 {
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 WEBRTC_LINUX
230 return ticks / 1000000LL;
231 #else
232 return ticks / 1000LL;
233 #endif
234 }
235
236 inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks)
237 {
238 _ticks += ticks;
239 return *this;
240 }
241
TickInterval()242 inline TickInterval::TickInterval() : _interval(0)
243 {
244 }
245
TickInterval(const WebRtc_Word64 interval)246 inline TickInterval::TickInterval(const WebRtc_Word64 interval)
247 : _interval(interval)
248 {
249 }
250
Milliseconds()251 inline WebRtc_Word64 TickInterval::Milliseconds() const
252 {
253 #if _WIN32
254 #ifdef USE_QUERY_PERFORMANCE_COUNTER
255 LARGE_INTEGER qpfreq;
256 QueryPerformanceFrequency(&qpfreq);
257 return (_interval * 1000) / qpfreq.QuadPart;
258 #else
259 // _interval is in ms
260 return _interval;
261 #endif
262 #elif WEBRTC_LINUX
263 // _interval is in ns
264 return _interval / 1000000;
265 #else
266 // _interval is usecs
267 return _interval / 1000;
268 #endif
269 }
270
Microseconds()271 inline WebRtc_Word64 TickInterval::Microseconds() const
272 {
273 #if _WIN32
274 #ifdef USE_QUERY_PERFORMANCE_COUNTER
275 LARGE_INTEGER qpfreq;
276 QueryPerformanceFrequency(&qpfreq);
277 return (_interval * 1000000) / qpfreq.QuadPart;
278 #else
279 // _interval is in ms
280 return _interval *1000LL;
281 #endif
282 #elif WEBRTC_LINUX
283 // _interval is in ns
284 return _interval / 1000;
285 #else
286 // _interval is usecs
287 return _interval;
288 #endif
289 }
290
291 inline TickInterval& TickInterval::operator+=(const TickInterval& rhs)
292 {
293 _interval += rhs._interval;
294 return *this;
295 }
296
297 inline TickInterval& TickInterval::operator-=(const TickInterval& rhs)
298 {
299 _interval -= rhs._interval;
300 return *this;
301 }
302 } // namespace webrtc
303
304 #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
305