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 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 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 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 218 inline WebRtc_Word64 TickTime::Ticks() const 219 { 220 return _ticks; 221 } 222 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 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 263 inline TickInterval::TickInterval() : _interval(0) 264 { 265 } 266 267 inline TickInterval::TickInterval(const WebRtc_Word64 interval) 268 : _interval(interval) 269 { 270 } 271 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 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