• 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 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