diff options
Diffstat (limited to 'src/system_wrappers/interface/tick_util.h')
-rw-r--r-- | src/system_wrappers/interface/tick_util.h | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/src/system_wrappers/interface/tick_util.h b/src/system_wrappers/interface/tick_util.h new file mode 100644 index 0000000000..4c280677b5 --- /dev/null +++ b/src/system_wrappers/interface/tick_util.h @@ -0,0 +1,304 @@ +/* + * 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 <windows.h> +#include <mmsystem.h> +#elif WEBRTC_LINUX +#include <ctime> +#else +#include <sys/time.h> +#include <time.h> +#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<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(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_ |