blob: c3432154ea65f9948bafe010b18ad6f7f1f6b3e9 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
wu@webrtc.org6e6ea042012-03-12 19:42:22 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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>
wu@webrtc.org6e6ea042012-03-12 19:42:22 +000022#elif WEBRTC_MAC
23#include <mach/mach_time.h>
24#include <string.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000025#else
26#include <sys/time.h>
27#include <time.h>
28#endif
29
30#include "typedefs.h"
31
32namespace webrtc {
33class TickInterval;
34
35class TickTime
36{
37public:
38 // Current time in the tick domain.
39 static TickTime Now();
40
41 // Now in the time domain in ms.
42 static WebRtc_Word64 MillisecondTimestamp();
43
44 // Now in the time domain in us.
45 static WebRtc_Word64 MicrosecondTimestamp();
46
47 WebRtc_Word64 Ticks() const;
48
49 static WebRtc_Word64 MillisecondsToTicks(const WebRtc_Word64 ms);
50
51 static WebRtc_Word64 TicksToMilliseconds(const WebRtc_Word64 ticks);
52
53 // Returns a TickTime that is ticks later than the passed TickTime
54 friend TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks);
55 TickTime& operator+=(const WebRtc_Word64& rhs);
56
57
58 // Returns a TickInterval that is the difference in ticks beween rhs and lhs
59 friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
60private:
61 WebRtc_Word64 _ticks;
62};
63
64class TickInterval
65{
66public:
67 TickInterval();
68
69 WebRtc_Word64 Milliseconds() const;
70 WebRtc_Word64 Microseconds() const;
71
72 // Returns the sum of two TickIntervals as a TickInterval
73 friend TickInterval operator+(const TickInterval& lhs,
74 const TickInterval& rhs);
75 TickInterval& operator-=(const TickInterval& rhs);
76
77 // Returns a TickInterval corresponding to rhs - lhs
78 friend TickInterval operator-(const TickInterval& lhs,
79 const TickInterval& rhs);
80 TickInterval& operator+=(const TickInterval& rhs);
81
kjellander@webrtc.org9e7774f2011-09-23 11:33:31 +000082 friend bool operator>(const TickInterval& lhs, const TickInterval& rhs);
83 friend bool operator<=(const TickInterval& lhs, const TickInterval& rhs);
84 friend bool operator<(const TickInterval& lhs, const TickInterval& rhs);
85 friend bool operator>=(const TickInterval& lhs, const TickInterval& rhs);
86
niklase@google.com470e71d2011-07-07 08:21:25 +000087private:
88 TickInterval(WebRtc_Word64 interval);
89
90 friend class TickTime;
91 friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
92
93private:
94 WebRtc_Word64 _interval;
95};
96
97inline TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs)
98{
99 return TickInterval(lhs._interval + rhs._interval);
100}
101
102inline TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs)
103{
104 return TickInterval(lhs._interval - rhs._interval);
105}
106
107inline TickInterval operator-(const TickTime& lhs,const TickTime& rhs)
108{
109 return TickInterval(lhs._ticks - rhs._ticks);
110}
111
112inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks)
113{
114 TickTime time = lhs;
115 time._ticks += ticks;
116 return time;
117}
kjellander@webrtc.org9e7774f2011-09-23 11:33:31 +0000118inline bool operator>(const TickInterval& lhs, const TickInterval& rhs)
119{
120 return lhs._interval > rhs._interval;
121}
122inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs)
123{
124 return lhs._interval <= rhs._interval;
125}
126inline bool operator<(const TickInterval& lhs, const TickInterval& rhs)
127{
128 return lhs._interval <= rhs._interval;
129}
130inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs)
131{
132 return lhs._interval >= rhs._interval;
133}
niklase@google.com470e71d2011-07-07 08:21:25 +0000134
135inline TickTime TickTime::Now()
136{
137 TickTime result;
138#if _WIN32
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000139 // TODO(wu): Remove QueryPerformanceCounter implementation.
niklase@google.com470e71d2011-07-07 08:21:25 +0000140 #ifdef USE_QUERY_PERFORMANCE_COUNTER
141 // QueryPerformanceCounter returns the value from the TSC which is
142 // incremented at the CPU frequency. The algorithm used requires
143 // the CPU frequency to be constant. Technology like speed stepping
144 // which has variable CPU frequency will therefore yield unpredictable,
145 // incorrect time estimations.
146 LARGE_INTEGER qpcnt;
147 QueryPerformanceCounter(&qpcnt);
148 result._ticks = qpcnt.QuadPart;
149 #else
150 static volatile LONG lastTimeGetTime = 0;
151 static volatile WebRtc_Word64 numWrapTimeGetTime = 0;
152 volatile LONG* lastTimeGetTimePtr = &lastTimeGetTime;
153 DWORD now = timeGetTime();
154 // Atomically update the last gotten time
155 DWORD old = InterlockedExchange(lastTimeGetTimePtr, now);
156 if(now < old)
157 {
158 // If now is earlier than old, there may have been a race between
159 // threads.
160 // 0x0fffffff ~3.1 days, the code will not take that long to execute
161 // so it must have been a wrap around.
162 if(old > 0xf0000000 && now < 0x0fffffff)
163 {
164 numWrapTimeGetTime++;
165 }
166 }
167 result._ticks = now + (numWrapTimeGetTime<<32);
168 #endif
169#elif defined(WEBRTC_LINUX)
170 struct timespec ts;
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000171 // TODO(wu): Remove CLOCK_REALTIME implementation.
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 #ifdef WEBRTC_CLOCK_TYPE_REALTIME
173 clock_gettime(CLOCK_REALTIME, &ts);
174 #else
175 clock_gettime(CLOCK_MONOTONIC, &ts);
176 #endif
177 result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec);
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000178#elif defined(WEBRTC_MAC)
179 static mach_timebase_info_data_t timebase;
180 if (timebase.denom == 0) {
181 // Get the timebase if this is the first time we run.
182 // Recommended by Apple's QA1398.
183 kern_return_t retval = mach_timebase_info(&timebase);
184 if (retval != KERN_SUCCESS) {
185 // TODO(wu): Implement CHECK similar to chrome for all the platforms.
186 // Then replace this with a CHECK(retval == KERN_SUCCESS);
sjlee@webrtc.org414fa7f2012-09-11 17:25:46 +0000187#ifndef WEBRTC_IOS
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000188 asm("int3");
sjlee@webrtc.org4b425082012-09-10 17:58:21 +0000189#else
190 __builtin_trap();
sjlee@webrtc.org414fa7f2012-09-11 17:25:46 +0000191#endif // WEBRTC_IOS
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000192 }
193 }
194 // Use timebase to convert absolute time tick units into nanoseconds.
195 result._ticks = mach_absolute_time() * timebase.numer / timebase.denom;
niklase@google.com470e71d2011-07-07 08:21:25 +0000196#else
197 struct timeval tv;
198 gettimeofday(&tv, NULL);
199 result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(tv.tv_usec);
200#endif
201 return result;
202}
203
204inline WebRtc_Word64 TickTime::MillisecondTimestamp()
205{
206 TickTime now = TickTime::Now();
207#if _WIN32
208 #ifdef USE_QUERY_PERFORMANCE_COUNTER
209 LARGE_INTEGER qpfreq;
210 QueryPerformanceFrequency(&qpfreq);
211 return (now._ticks * 1000) / qpfreq.QuadPart;
212 #else
213 return now._ticks;
214 #endif
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000215#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000216 return now._ticks / 1000000LL;
217#else
218 return now._ticks / 1000LL;
219#endif
220}
221
222inline WebRtc_Word64 TickTime::MicrosecondTimestamp()
223{
224 TickTime now = TickTime::Now();
225
226#if _WIN32
227 #ifdef USE_QUERY_PERFORMANCE_COUNTER
228 LARGE_INTEGER qpfreq;
229 QueryPerformanceFrequency(&qpfreq);
230 return (now._ticks * 1000) / (qpfreq.QuadPart/1000);
231 #else
232 return now._ticks *1000LL;
233 #endif
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000234#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 return now._ticks / 1000LL;
236#else
237 return now._ticks;
238#endif
239}
240
241inline WebRtc_Word64 TickTime::Ticks() const
242{
243 return _ticks;
244}
245
246inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms)
247{
248#if _WIN32
249 #ifdef USE_QUERY_PERFORMANCE_COUNTER
250 LARGE_INTEGER qpfreq;
251 QueryPerformanceFrequency(&qpfreq);
252 return (qpfreq.QuadPart * ms) / 1000;
253 #else
254 return ms;
255 #endif
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000256#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000257 return ms * 1000000LL;
258#else
259 return ms * 1000LL;
260#endif
261}
262
263inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks)
264{
265#if _WIN32
266 #ifdef USE_QUERY_PERFORMANCE_COUNTER
267 LARGE_INTEGER qpfreq;
268 QueryPerformanceFrequency(&qpfreq);
269 return (ticks * 1000) / qpfreq.QuadPart;
270 #else
271 return ticks;
272 #endif
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000273#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 return ticks / 1000000LL;
275#else
276 return ticks / 1000LL;
277#endif
278}
279
280inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks)
281{
282 _ticks += ticks;
283 return *this;
284}
285
286inline TickInterval::TickInterval() : _interval(0)
287{
288}
289
290inline TickInterval::TickInterval(const WebRtc_Word64 interval)
291 : _interval(interval)
292{
293}
294
295inline WebRtc_Word64 TickInterval::Milliseconds() const
296{
297#if _WIN32
298 #ifdef USE_QUERY_PERFORMANCE_COUNTER
299 LARGE_INTEGER qpfreq;
300 QueryPerformanceFrequency(&qpfreq);
301 return (_interval * 1000) / qpfreq.QuadPart;
302 #else
303 // _interval is in ms
304 return _interval;
305 #endif
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000306#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000307 // _interval is in ns
308 return _interval / 1000000;
309#else
310 // _interval is usecs
311 return _interval / 1000;
312#endif
313}
314
315inline WebRtc_Word64 TickInterval::Microseconds() const
316{
317#if _WIN32
318 #ifdef USE_QUERY_PERFORMANCE_COUNTER
319 LARGE_INTEGER qpfreq;
320 QueryPerformanceFrequency(&qpfreq);
321 return (_interval * 1000000) / qpfreq.QuadPart;
322 #else
323 // _interval is in ms
324 return _interval *1000LL;
325 #endif
wu@webrtc.org6e6ea042012-03-12 19:42:22 +0000326#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000327 // _interval is in ns
328 return _interval / 1000;
329#else
330 // _interval is usecs
331 return _interval;
332#endif
333}
334
335inline TickInterval& TickInterval::operator+=(const TickInterval& rhs)
336{
337 _interval += rhs._interval;
338 return *this;
339}
340
341inline TickInterval& TickInterval::operator-=(const TickInterval& rhs)
342{
343 _interval -= rhs._interval;
344 return *this;
345}
346} // namespace webrtc
347
348#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_