| /* |
| * Copyright (c) 2012 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> |
| #elif WEBRTC_MAC |
| #include <mach/mach_time.h> |
| #include <string.h> |
| #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); |
| |
| friend bool operator>(const TickInterval& lhs, const TickInterval& rhs); |
| friend bool operator<=(const TickInterval& lhs, const TickInterval& rhs); |
| friend bool operator<(const TickInterval& lhs, const TickInterval& rhs); |
| friend bool operator>=(const TickInterval& lhs, 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 bool operator>(const TickInterval& lhs, const TickInterval& rhs) |
| { |
| return lhs._interval > rhs._interval; |
| } |
| inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs) |
| { |
| return lhs._interval <= rhs._interval; |
| } |
| inline bool operator<(const TickInterval& lhs, const TickInterval& rhs) |
| { |
| return lhs._interval <= rhs._interval; |
| } |
| inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs) |
| { |
| return lhs._interval >= rhs._interval; |
| } |
| |
| inline TickTime TickTime::Now() |
| { |
| TickTime result; |
| #if _WIN32 |
| // TODO(wu): Remove QueryPerformanceCounter implementation. |
| #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; |
| // TODO(wu): Remove CLOCK_REALTIME implementation. |
| #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); |
| #elif defined(WEBRTC_MAC) |
| static mach_timebase_info_data_t timebase; |
| if (timebase.denom == 0) { |
| // Get the timebase if this is the first time we run. |
| // Recommended by Apple's QA1398. |
| kern_return_t retval = mach_timebase_info(&timebase); |
| if (retval != KERN_SUCCESS) { |
| // TODO(wu): Implement CHECK similar to chrome for all the platforms. |
| // Then replace this with a CHECK(retval == KERN_SUCCESS); |
| asm("int3"); |
| } |
| } |
| // Use timebase to convert absolute time tick units into nanoseconds. |
| result._ticks = mach_absolute_time() * timebase.numer / timebase.denom; |
| #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 defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
| 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 defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
| 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 defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
| 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 defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
| 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 defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
| // _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 defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
| // _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_ |