3#define WIN32_LEAN_AND_MEAN
8#pragma intrinsic(_InterlockedCompareExchange64)
15#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
45#if defined(WIN32) && defined(_RESIP_MONOTONIC_CLOCK)
46unsigned ResipClock::mMaxSystemTimeWaitMs = 60000;
48unsigned ResipClock::mMaxSystemTimeWaitMs = UINT_MAX;
52ResipClock::WinMonoClock::PGTC64 ResipClock::WinMonoClock::mGTC64 = &ResipClock::WinMonoClock::GTCLockDuringRange::GTC64;
54ResipClock::WinMonoClock::WinMonoClock()
60ResipClock::WinMonoClock::Initialize(
void)
62 static Mutex mtxStart;
63 static volatile bool isInitialized=
false;
72#if defined(_MSC_VER) && (_MSC_VER >= 1400)
73 ResipClock::mMaxSystemTimeWaitMs = GTCInterlocked::GetMaxWaitMs();
74 mGTC64 = (PGTC64)>CInterlocked::GTC64;
75 DebugLog(<<
"Using GTCInterlocked::GTC64 as the monotonic clock for time functions.");
77 ResipClock::mMaxSystemTimeWaitMs = GTCLockDuringRange::GetMaxWaitMs();
78 mGTC64 = (PGTC64)>CLockDuringRange::GTC64;
79 DebugLog(<<
"Using GTCLockDuringRange::GTC64 as the monotonic clock for time functions.");
82 unsigned min=0,
max=0,actual=0;
87 InfoLog(<<
"Timer resolution: (min/max/actual/isMonotonic) = " << min <<
'/' <<
max <<
'/' << actual <<
88 '/' << ((isMono)?(
"true"):(
"false")));
93#define IS_ALIGNED(_pointer, _alignment) ((((ULONG_PTR) (_pointer)) & ((_alignment) - 1)) == 0)
95uint64_t ResipClock::WinMonoClock::GTCInterlocked::GTC64(
void)
97#if defined(_MSC_VER) && (_MSC_VER >= 1400)
98 ULARGE_INTEGER timeVal;
104 timeVal.QuadPart = _InterlockedCompareExchange64((LONGLONG
volatile *)&mBaseTime,0,0);
106 DWORD tickNow = ::timeGetTime();
108 if (tickNow != timeVal.LowPart)
115 DWORD diff = tickNow - timeVal.LowPart;
118 if (diff > mBaseTimeUpdateInterval)
120 ULARGE_INTEGER newVal;
122 newVal.QuadPart = timeVal.QuadPart + diff;
125 _InterlockedCompareExchange64((LONGLONG
volatile *)&mBaseTime,(LONGLONG)newVal.QuadPart,(LONGLONG)timeVal.QuadPart);
128 timeVal.QuadPart += diff;
131 return timeVal.QuadPart;
134 return GTCLock::GTC64();
138volatile uint64_t ResipClock::WinMonoClock::GTCInterlocked::mBaseTime = 0;
141ResipClock::WinMonoClock::GTCLock::GTC64(
void)
145 DWORD tickNow = ::timeGetTime();
147 if (tickNow != mBaseTime.LowPart)
149 mBaseTime.QuadPart += (tickNow - mBaseTime.LowPart);
152 return mBaseTime.QuadPart;
155ULARGE_INTEGER ResipClock::WinMonoClock::GTCLock::mBaseTime = {0,0};
156Mutex ResipClock::WinMonoClock::GTCLock::mMutex;
158uint64_t ResipClock::WinMonoClock::GTCLockDuringRange::GTC64(
void)
163 const DWORD TIMER_BEGIN_SAFE_RANGE = 0xffff;
164 const DWORD TIMER_END_SAFE_RANGE = 0xffff0000;
166 DWORD tick = ::timeGetTime();
168 if ( ( tick > TIMER_BEGIN_SAFE_RANGE ) && ( tick < TIMER_END_SAFE_RANGE ) )
171 ret.HighPart = mWrapCounter;
176 Lock lock(mWrapCounterMutex);
177 if (mPrevTick > tick)
183 ret.HighPart = mWrapCounter;
188uint32_t ResipClock::WinMonoClock::GTCLockDuringRange::mWrapCounter = 0;
189DWORD ResipClock::WinMonoClock::GTCLockDuringRange::mPrevTick = 0;
190Mutex ResipClock::WinMonoClock::GTCLockDuringRange::mWrapCounterMutex;
194ResipClock::getSystemTime()
198#if defined(WIN32) || defined(UNDER_CE)
199#ifdef _RESIP_MONOTONIC_CLOCK
200 static ResipClock::WinMonoClock clockInit;
201 return WinMonoClock::GetClock64() * 1000;
207 ::GetSystemTime(&st);
208 ::SystemTimeToFileTime(&st,&ft);
210 ::GetSystemTimeAsFileTime(&ft);
214 li.LowPart = ft.dwLowDateTime;
215 li.HighPart = ft.dwHighDateTime;
216 return li.QuadPart/10;
223#ifdef _RESIP_MONOTONIC_CLOCK
224 struct timespec now_monotonic;
225 if (clock_gettime( CLOCK_MONOTONIC, &now_monotonic ) == 0)
228 time = now_monotonic.tv_sec;
230 time += now_monotonic.tv_nsec/1000;
235 gettimeofday( &now , NULL );
248#if defined(WIN32) && !defined(__GNUC__)
249 return 18446744073709551615ui64;
251 return 18446744073709551615ULL;
265 ret += (futureMs*r)/10000;
277 min =
max = actual = 0;
281#if defined(_RESIP_MONOTONIC_CLOCK)
282#if !defined(NTSTATUS)
283#define NTSTATUS DWORD
285 typedef NTSTATUS (WINAPI*PNTQTR)(PULONG,PULONG,PULONG);
287 HMODULE hm = ::LoadLibrary(
"ntdll");
291 PNTQTR ntqtr = (PNTQTR)::GetProcAddress(hm,
"NtQueryTimerResolution");
295 ntqtr((PULONG)&min,(PULONG)&
max,(PULONG)&actual);
306 DWORD timeAdjustment=0;
307 BOOL timeAdjustmentDisabled=0;
310 ::GetSystemTimeAdjustment(&timeAdjustment,(PDWORD)&min,&timeAdjustmentDisabled);
318 clockid_t clock = CLOCK_REALTIME;
319#if defined(_RESIP_MONOTONIC_CLOCK)
320 clock = CLOCK_MONOTONIC;
324 if (clock_getres(clock,&res) == 0)
326 actual = (res.tv_sec * 1000000) + (res.tv_nsec / 1000);
#define resip_assert(x)
This file needs to work for both C and C++ code.
static int getRandom()
Returns a postive integer (31 bits) of randomness.
static uint64_t getTimeMs()
Returns the current clock time in milliseconds.
static uint64_t getForever()
Infinit time in future.
static uint64_t getRandomFutureTimeMs(uint64_t futureMs)
Returns an absolute time in ms that is between 50% and 90% of passed in ms from now.
static void queryTimerInfo(unsigned &minRes, unsigned &maxRes, unsigned &actualRes, bool &isMonotonic)
Gets the current clock's minimum, maximum and current/actual timer resolution and returns if the cloc...
dcm! – add UnusedChecking(_enum) below;
std::mutex Mutex
A semaphore that can be locked by only one thread at a time.
void sleepSeconds(unsigned int seconds)
std::unique_lock< Mutex > Lock
A convenience class to lock a Lockable (such as a Mutex) on object creation, and unlock on destructio...
unsigned long long uint64_t
void sleepMs(unsigned int ms)
unsigned __int64 uint64_t