1/* 2 * Copyright (c) 2012 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#elif WEBRTC_MAC 23#include <mach/mach_time.h> 24#include <string.h> 25#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 82 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 87private: 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} 118inline 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} 134 135inline TickTime TickTime::Now() 136{ 137 TickTime result; 138#if _WIN32 139 // TODO(wu): Remove QueryPerformanceCounter implementation. 140 #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; 171 // TODO(wu): Remove CLOCK_REALTIME implementation. 172 #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); 178#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); 187 asm("int3"); 188 } 189 } 190 // Use timebase to convert absolute time tick units into nanoseconds. 191 result._ticks = mach_absolute_time() * timebase.numer / timebase.denom; 192#else 193 struct timeval tv; 194 gettimeofday(&tv, NULL); 195 result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(tv.tv_usec); 196#endif 197 return result; 198} 199 200inline WebRtc_Word64 TickTime::MillisecondTimestamp() 201{ 202 TickTime now = TickTime::Now(); 203#if _WIN32 204 #ifdef USE_QUERY_PERFORMANCE_COUNTER 205 LARGE_INTEGER qpfreq; 206 QueryPerformanceFrequency(&qpfreq); 207 return (now._ticks * 1000) / qpfreq.QuadPart; 208 #else 209 return now._ticks; 210 #endif 211#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 212 return now._ticks / 1000000LL; 213#else 214 return now._ticks / 1000LL; 215#endif 216} 217 218inline WebRtc_Word64 TickTime::MicrosecondTimestamp() 219{ 220 TickTime now = TickTime::Now(); 221 222#if _WIN32 223 #ifdef USE_QUERY_PERFORMANCE_COUNTER 224 LARGE_INTEGER qpfreq; 225 QueryPerformanceFrequency(&qpfreq); 226 return (now._ticks * 1000) / (qpfreq.QuadPart/1000); 227 #else 228 return now._ticks *1000LL; 229 #endif 230#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 231 return now._ticks / 1000LL; 232#else 233 return now._ticks; 234#endif 235} 236 237inline WebRtc_Word64 TickTime::Ticks() const 238{ 239 return _ticks; 240} 241 242inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms) 243{ 244#if _WIN32 245 #ifdef USE_QUERY_PERFORMANCE_COUNTER 246 LARGE_INTEGER qpfreq; 247 QueryPerformanceFrequency(&qpfreq); 248 return (qpfreq.QuadPart * ms) / 1000; 249 #else 250 return ms; 251 #endif 252#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 253 return ms * 1000000LL; 254#else 255 return ms * 1000LL; 256#endif 257} 258 259inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks) 260{ 261#if _WIN32 262 #ifdef USE_QUERY_PERFORMANCE_COUNTER 263 LARGE_INTEGER qpfreq; 264 QueryPerformanceFrequency(&qpfreq); 265 return (ticks * 1000) / qpfreq.QuadPart; 266 #else 267 return ticks; 268 #endif 269#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 270 return ticks / 1000000LL; 271#else 272 return ticks / 1000LL; 273#endif 274} 275 276inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks) 277{ 278 _ticks += ticks; 279 return *this; 280} 281 282inline TickInterval::TickInterval() : _interval(0) 283{ 284} 285 286inline TickInterval::TickInterval(const WebRtc_Word64 interval) 287 : _interval(interval) 288{ 289} 290 291inline WebRtc_Word64 TickInterval::Milliseconds() const 292{ 293#if _WIN32 294 #ifdef USE_QUERY_PERFORMANCE_COUNTER 295 LARGE_INTEGER qpfreq; 296 QueryPerformanceFrequency(&qpfreq); 297 return (_interval * 1000) / qpfreq.QuadPart; 298 #else 299 // _interval is in ms 300 return _interval; 301 #endif 302#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 303 // _interval is in ns 304 return _interval / 1000000; 305#else 306 // _interval is usecs 307 return _interval / 1000; 308#endif 309} 310 311inline WebRtc_Word64 TickInterval::Microseconds() const 312{ 313#if _WIN32 314 #ifdef USE_QUERY_PERFORMANCE_COUNTER 315 LARGE_INTEGER qpfreq; 316 QueryPerformanceFrequency(&qpfreq); 317 return (_interval * 1000000) / qpfreq.QuadPart; 318 #else 319 // _interval is in ms 320 return _interval *1000LL; 321 #endif 322#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 323 // _interval is in ns 324 return _interval / 1000; 325#else 326 // _interval is usecs 327 return _interval; 328#endif 329} 330 331inline TickInterval& TickInterval::operator+=(const TickInterval& rhs) 332{ 333 _interval += rhs._interval; 334 return *this; 335} 336 337inline TickInterval& TickInterval::operator-=(const TickInterval& rhs) 338{ 339 _interval -= rhs._interval; 340 return *this; 341} 342} // namespace webrtc 343 344#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ 345