• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     friend bool operator>(const TickInterval& lhs, const TickInterval& rhs);
80     friend bool operator<=(const TickInterval& lhs, const TickInterval& rhs);
81     friend bool operator<(const TickInterval& lhs, const TickInterval& rhs);
82     friend bool operator>=(const TickInterval& lhs, const TickInterval& rhs);
83 
84 private:
85     TickInterval(WebRtc_Word64 interval);
86 
87     friend class TickTime;
88     friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
89 
90 private:
91     WebRtc_Word64 _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 TickInterval& lhs, const TickInterval& rhs)
100 {
101     return TickInterval(lhs._interval - rhs._interval);
102 }
103 
104 inline TickInterval operator-(const TickTime& lhs,const TickTime& rhs)
105 {
106     return TickInterval(lhs._ticks - rhs._ticks);
107 }
108 
109 inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks)
110 {
111     TickTime time = lhs;
112     time._ticks += ticks;
113     return time;
114 }
115 inline bool operator>(const TickInterval& lhs, const TickInterval& rhs)
116 {
117     return lhs._interval > rhs._interval;
118 }
119 inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs)
120 {
121     return lhs._interval <= rhs._interval;
122 }
123 inline bool operator<(const TickInterval& lhs, const TickInterval& rhs)
124 {
125     return lhs._interval <= rhs._interval;
126 }
127 inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs)
128 {
129     return lhs._interval >= rhs._interval;
130 }
131 
Now()132 inline TickTime TickTime::Now()
133 {
134     TickTime result;
135 #if _WIN32
136     #ifdef USE_QUERY_PERFORMANCE_COUNTER
137         // QueryPerformanceCounter returns the value from the TSC which is
138         // incremented at the CPU frequency. The algorithm used requires
139         // the CPU frequency to be constant. Technology like speed stepping
140         // which has variable CPU frequency will therefore yield unpredictable,
141         // incorrect time estimations.
142         LARGE_INTEGER qpcnt;
143         QueryPerformanceCounter(&qpcnt);
144         result._ticks = qpcnt.QuadPart;
145     #else
146         static volatile LONG lastTimeGetTime = 0;
147         static volatile WebRtc_Word64 numWrapTimeGetTime = 0;
148         volatile LONG* lastTimeGetTimePtr = &lastTimeGetTime;
149         DWORD now = timeGetTime();
150         // Atomically update the last gotten time
151         DWORD old = InterlockedExchange(lastTimeGetTimePtr, now);
152         if(now < old)
153         {
154             // If now is earlier than old, there may have been a race between
155             // threads.
156             // 0x0fffffff ~3.1 days, the code will not take that long to execute
157             // so it must have been a wrap around.
158             if(old > 0xf0000000 && now < 0x0fffffff)
159             {
160                 numWrapTimeGetTime++;
161             }
162         }
163         result._ticks = now + (numWrapTimeGetTime<<32);
164     #endif
165 #elif defined(WEBRTC_LINUX)
166     struct timespec ts;
167     #ifdef WEBRTC_CLOCK_TYPE_REALTIME
168         clock_gettime(CLOCK_REALTIME, &ts);
169     #else
170         clock_gettime(CLOCK_MONOTONIC, &ts);
171     #endif
172     result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec);
173 #else
174     struct timeval tv;
175     gettimeofday(&tv, NULL);
176     result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(tv.tv_usec);
177 #endif
178     return result;
179 }
180 
MillisecondTimestamp()181 inline WebRtc_Word64 TickTime::MillisecondTimestamp()
182 {
183     TickTime now = TickTime::Now();
184 #if _WIN32
185     #ifdef USE_QUERY_PERFORMANCE_COUNTER
186         LARGE_INTEGER qpfreq;
187         QueryPerformanceFrequency(&qpfreq);
188         return (now._ticks * 1000) / qpfreq.QuadPart;
189     #else
190         return now._ticks;
191     #endif
192 #elif WEBRTC_LINUX
193     return now._ticks / 1000000LL;
194 #else
195     return now._ticks / 1000LL;
196 #endif
197 }
198 
MicrosecondTimestamp()199 inline WebRtc_Word64 TickTime::MicrosecondTimestamp()
200 {
201     TickTime now = TickTime::Now();
202 
203 #if _WIN32
204     #ifdef USE_QUERY_PERFORMANCE_COUNTER
205         LARGE_INTEGER qpfreq;
206         QueryPerformanceFrequency(&qpfreq);
207         return (now._ticks * 1000) / (qpfreq.QuadPart/1000);
208     #else
209         return now._ticks *1000LL;
210     #endif
211 #elif WEBRTC_LINUX
212     return now._ticks / 1000LL;
213 #else
214     return now._ticks;
215 #endif
216 }
217 
Ticks()218 inline WebRtc_Word64 TickTime::Ticks() const
219 {
220     return _ticks;
221 }
222 
MillisecondsToTicks(const WebRtc_Word64 ms)223 inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms)
224 {
225 #if _WIN32
226     #ifdef USE_QUERY_PERFORMANCE_COUNTER
227         LARGE_INTEGER qpfreq;
228         QueryPerformanceFrequency(&qpfreq);
229         return (qpfreq.QuadPart * ms) / 1000;
230     #else
231         return ms;
232     #endif
233 #elif WEBRTC_LINUX
234     return ms * 1000000LL;
235 #else
236     return ms * 1000LL;
237 #endif
238 }
239 
TicksToMilliseconds(const WebRtc_Word64 ticks)240 inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks)
241 {
242 #if _WIN32
243     #ifdef USE_QUERY_PERFORMANCE_COUNTER
244         LARGE_INTEGER qpfreq;
245         QueryPerformanceFrequency(&qpfreq);
246         return (ticks * 1000) / qpfreq.QuadPart;
247     #else
248         return ticks;
249     #endif
250 #elif WEBRTC_LINUX
251     return ticks / 1000000LL;
252 #else
253     return ticks / 1000LL;
254 #endif
255 }
256 
257 inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks)
258 {
259     _ticks += ticks;
260     return *this;
261 }
262 
TickInterval()263 inline TickInterval::TickInterval() : _interval(0)
264 {
265 }
266 
TickInterval(const WebRtc_Word64 interval)267 inline TickInterval::TickInterval(const WebRtc_Word64 interval)
268     : _interval(interval)
269 {
270 }
271 
Milliseconds()272 inline WebRtc_Word64 TickInterval::Milliseconds() const
273 {
274 #if _WIN32
275     #ifdef USE_QUERY_PERFORMANCE_COUNTER
276         LARGE_INTEGER qpfreq;
277         QueryPerformanceFrequency(&qpfreq);
278         return (_interval * 1000) / qpfreq.QuadPart;
279     #else
280 	// _interval is in ms
281         return _interval;
282     #endif
283 #elif WEBRTC_LINUX
284     // _interval is in ns
285     return _interval / 1000000;
286 #else
287     // _interval is usecs
288     return _interval / 1000;
289 #endif
290 }
291 
Microseconds()292 inline WebRtc_Word64 TickInterval::Microseconds() const
293 {
294 #if _WIN32
295     #ifdef USE_QUERY_PERFORMANCE_COUNTER
296         LARGE_INTEGER qpfreq;
297         QueryPerformanceFrequency(&qpfreq);
298         return (_interval * 1000000) / qpfreq.QuadPart;
299     #else
300 	// _interval is in ms
301         return _interval *1000LL;
302     #endif
303 #elif WEBRTC_LINUX
304     // _interval is in ns
305     return _interval / 1000;
306 #else
307     // _interval is usecs
308     return _interval;
309 #endif
310 }
311 
312 inline TickInterval& TickInterval::operator+=(const TickInterval& rhs)
313 {
314     _interval += rhs._interval;
315     return *this;
316 }
317 
318 inline TickInterval& TickInterval::operator-=(const TickInterval& rhs)
319 {
320     _interval -= rhs._interval;
321     return *this;
322 }
323 } // namespace webrtc
324 
325 #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
326