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 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 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 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 197 inline WebRtc_Word64 TickTime::Ticks() const 198 { 199 return _ticks; 200 } 201 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 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 242 inline TickInterval::TickInterval() : _interval(0) 243 { 244 } 245 246 inline TickInterval::TickInterval(const WebRtc_Word64 interval) 247 : _interval(interval) 248 { 249 } 250 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 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