305 lines
8.0 KiB
C
305 lines
8.0 KiB
C
|
/*
|
||
|
* 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_
|