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 29namespace webrtc { 30class TickInterval; 31 32class TickTime 33{ 34public: 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); 57private: 58 WebRtc_Word64 _ticks; 59}; 60 61class TickInterval 62{ 63public: 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 84private: 85 TickInterval(WebRtc_Word64 interval); 86 87 friend class TickTime; 88 friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs); 89 90private: 91 WebRtc_Word64 _interval; 92}; 93 94inline TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs) 95{ 96 return TickInterval(lhs._interval + rhs._interval); 97} 98 99inline TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs) 100{ 101 return TickInterval(lhs._interval - rhs._interval); 102} 103 104inline TickInterval operator-(const TickTime& lhs,const TickTime& rhs) 105{ 106 return TickInterval(lhs._ticks - rhs._ticks); 107} 108 109inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks) 110{ 111 TickTime time = lhs; 112 time._ticks += ticks; 113 return time; 114} 115inline bool operator>(const TickInterval& lhs, const TickInterval& rhs) 116{ 117 return lhs._interval > rhs._interval; 118} 119inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs) 120{ 121 return lhs._interval <= rhs._interval; 122} 123inline bool operator<(const TickInterval& lhs, const TickInterval& rhs) 124{ 125 return lhs._interval <= rhs._interval; 126} 127inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs) 128{ 129 return lhs._interval >= rhs._interval; 130} 131 132inline 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 181inline 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 199inline 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 218inline WebRtc_Word64 TickTime::Ticks() const 219{ 220 return _ticks; 221} 222 223inline 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 240inline 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 257inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks) 258{ 259 _ticks += ticks; 260 return *this; 261} 262 263inline TickInterval::TickInterval() : _interval(0) 264{ 265} 266 267inline TickInterval::TickInterval(const WebRtc_Word64 interval) 268 : _interval(interval) 269{ 270} 271 272inline 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 292inline 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 312inline TickInterval& TickInterval::operator+=(const TickInterval& rhs) 313{ 314 _interval += rhs._interval; 315 return *this; 316} 317 318inline 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