/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // System independant wrapper for polling elapsed time in ms and us. // The implementation works in the tick domain which can be mapped over to the // time domain. #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ #define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ #if _WIN32 #include #include #elif WEBRTC_LINUX #include #else #include #include #endif #include "typedefs.h" namespace webrtc { class TickInterval; class TickTime { public: // Current time in the tick domain. static TickTime Now(); // Now in the time domain in ms. static WebRtc_Word64 MillisecondTimestamp(); // Now in the time domain in us. static WebRtc_Word64 MicrosecondTimestamp(); WebRtc_Word64 Ticks() const; static WebRtc_Word64 MillisecondsToTicks(const WebRtc_Word64 ms); static WebRtc_Word64 TicksToMilliseconds(const WebRtc_Word64 ticks); // Returns a TickTime that is ticks later than the passed TickTime friend TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks); TickTime& operator+=(const WebRtc_Word64& rhs); // Returns a TickInterval that is the difference in ticks beween rhs and lhs friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs); private: WebRtc_Word64 _ticks; }; class TickInterval { public: TickInterval(); WebRtc_Word64 Milliseconds() const; WebRtc_Word64 Microseconds() const; // Returns the sum of two TickIntervals as a TickInterval friend TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs); TickInterval& operator-=(const TickInterval& rhs); // Returns a TickInterval corresponding to rhs - lhs friend TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs); TickInterval& operator+=(const TickInterval& rhs); private: TickInterval(WebRtc_Word64 interval); friend class TickTime; friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs); private: WebRtc_Word64 _interval; }; inline TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs) { return TickInterval(lhs._interval + rhs._interval); } inline TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs) { return TickInterval(lhs._interval - rhs._interval); } inline TickInterval operator-(const TickTime& lhs,const TickTime& rhs) { return TickInterval(lhs._ticks - rhs._ticks); } inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks) { TickTime time = lhs; time._ticks += ticks; return time; } inline TickTime TickTime::Now() { TickTime result; #if _WIN32 #ifdef USE_QUERY_PERFORMANCE_COUNTER // QueryPerformanceCounter returns the value from the TSC which is // incremented at the CPU frequency. The algorithm used requires // the CPU frequency to be constant. Technology like speed stepping // which has variable CPU frequency will therefore yield unpredictable, // incorrect time estimations. LARGE_INTEGER qpcnt; QueryPerformanceCounter(&qpcnt); result._ticks = qpcnt.QuadPart; #else static volatile LONG lastTimeGetTime = 0; static volatile WebRtc_Word64 numWrapTimeGetTime = 0; volatile LONG* lastTimeGetTimePtr = &lastTimeGetTime; DWORD now = timeGetTime(); // Atomically update the last gotten time DWORD old = InterlockedExchange(lastTimeGetTimePtr, now); if(now < old) { // If now is earlier than old, there may have been a race between // threads. // 0x0fffffff ~3.1 days, the code will not take that long to execute // so it must have been a wrap around. if(old > 0xf0000000 && now < 0x0fffffff) { numWrapTimeGetTime++; } } result._ticks = now + (numWrapTimeGetTime<<32); #endif #elif defined(WEBRTC_LINUX) struct timespec ts; #ifdef WEBRTC_CLOCK_TYPE_REALTIME clock_gettime(CLOCK_REALTIME, &ts); #else clock_gettime(CLOCK_MONOTONIC, &ts); #endif result._ticks = 1000000000LL * static_cast(ts.tv_sec) + static_cast(ts.tv_nsec); #else struct timeval tv; gettimeofday(&tv, NULL); result._ticks = 1000000LL * static_cast(tv.tv_sec) + static_cast(tv.tv_usec); #endif return result; } inline WebRtc_Word64 TickTime::MillisecondTimestamp() { TickTime now = TickTime::Now(); #if _WIN32 #ifdef USE_QUERY_PERFORMANCE_COUNTER LARGE_INTEGER qpfreq; QueryPerformanceFrequency(&qpfreq); return (now._ticks * 1000) / qpfreq.QuadPart; #else return now._ticks; #endif #elif WEBRTC_LINUX return now._ticks / 1000000LL; #else return now._ticks / 1000LL; #endif } inline WebRtc_Word64 TickTime::MicrosecondTimestamp() { TickTime now = TickTime::Now(); #if _WIN32 #ifdef USE_QUERY_PERFORMANCE_COUNTER LARGE_INTEGER qpfreq; QueryPerformanceFrequency(&qpfreq); return (now._ticks * 1000) / (qpfreq.QuadPart/1000); #else return now._ticks *1000LL; #endif #elif WEBRTC_LINUX return now._ticks / 1000LL; #else return now._ticks; #endif } inline WebRtc_Word64 TickTime::Ticks() const { return _ticks; } inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms) { #if _WIN32 #ifdef USE_QUERY_PERFORMANCE_COUNTER LARGE_INTEGER qpfreq; QueryPerformanceFrequency(&qpfreq); return (qpfreq.QuadPart * ms) / 1000; #else return ms; #endif #elif WEBRTC_LINUX return ms * 1000000LL; #else return ms * 1000LL; #endif } inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks) { #if _WIN32 #ifdef USE_QUERY_PERFORMANCE_COUNTER LARGE_INTEGER qpfreq; QueryPerformanceFrequency(&qpfreq); return (ticks * 1000) / qpfreq.QuadPart; #else return ticks; #endif #elif WEBRTC_LINUX return ticks / 1000000LL; #else return ticks / 1000LL; #endif } inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks) { _ticks += ticks; return *this; } inline TickInterval::TickInterval() : _interval(0) { } inline TickInterval::TickInterval(const WebRtc_Word64 interval) : _interval(interval) { } inline WebRtc_Word64 TickInterval::Milliseconds() const { #if _WIN32 #ifdef USE_QUERY_PERFORMANCE_COUNTER LARGE_INTEGER qpfreq; QueryPerformanceFrequency(&qpfreq); return (_interval * 1000) / qpfreq.QuadPart; #else // _interval is in ms return _interval; #endif #elif WEBRTC_LINUX // _interval is in ns return _interval / 1000000; #else // _interval is usecs return _interval / 1000; #endif } inline WebRtc_Word64 TickInterval::Microseconds() const { #if _WIN32 #ifdef USE_QUERY_PERFORMANCE_COUNTER LARGE_INTEGER qpfreq; QueryPerformanceFrequency(&qpfreq); return (_interval * 1000000) / qpfreq.QuadPart; #else // _interval is in ms return _interval *1000LL; #endif #elif WEBRTC_LINUX // _interval is in ns return _interval / 1000; #else // _interval is usecs return _interval; #endif } inline TickInterval& TickInterval::operator+=(const TickInterval& rhs) { _interval += rhs._interval; return *this; } inline TickInterval& TickInterval::operator-=(const TickInterval& rhs) { _interval -= rhs._interval; return *this; } } // namespace webrtc #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_