What is the best replacement for timeGetTime to avoid wrapping?

timeGetTime seems pretty good for querying the system time. However, its return value is only 32 bits, so it wraps around every 49 days.

It is not too difficult to detect rollovers when calling the code, but it adds some complexity, and (worse) requires maintaining state.

Is there a replacement for timeGetTime that does not have this workaround problem (possibly returning a 64-bit value) and have approximately the same accuracy and cost?

+4
source share
8 answers

No, roll-over tracking requires state. It can be as simple as just incrementing your own 64-bit counter with every callback.

It is very unusual to want to track time periods with a resolution of up to 1 millisecond for up to 49 days. You will have to worry that accuracy still exists after such a long period. The next step is to use the clock, GetTickCount (64), GetSystemTimeAsFileTime have a resolution of 15.625 milliseconds and are stored exactly with the time server.

+2
source

Which platform?

You can use GetTickCount64 () if you are running Vista or later, or synthesize your own GetTickCount64() from GetTickCount() and a timer ...

I look at the rollover problem in GetTickCount() and synthesize GetTickCount64() on platforms that do not support it here in my blog on testing non-trivial code: http://www.lenholgate.com/blog/2008/04/practical-testing- 17 --- a-whole-new-approach.html

+5
source

If you don’t need a time that exceeds 49 days , you can ignore the wrapper for FREE . Just always subtract the previous GetTime () time from the current timeGetTime (), and you will always get the measured delta time, which is accurate even when flowing around, provided that you synchronize events with a total duration of less than 49 days. This all works because of the way unsigned modular math works inside the computer.

 // this code ALWAYS works, even with wrap-around! DWORD dwStart = timeGetTime(); // provided the event timed here has a duration of less than 49 days DWORD dwDuration = timeGetTime()-dwStart; 

TIP: Look in TimeBeginPeriod (1L) to increase the accuracy of timeGetTime ().

BUT ... if you want a 64-bit version of timeGetTime, here it is:

 __int64 timeGetTime64() { static __int64 time64=0; // warning: if multiple threads call this function, protect with a critical section! return (time64 += (timeGetTime()-(DWORD)time64)); } 

Please note that if this function is not called at least once every 49 days, this function will not be able to correctly determine the wrapper.

+4
source

See GetSystemTimeAsFileTime () . It populates the FILETIME structure, which contains a β€œ64-bit value representing the number of 100 nanosecond intervals since January 1, 1601 (UTC)”

+1
source

How are you trying to use it? I often use the Win32 equivalent when checking for a duration that I know will be less than 49 days. For example, the following code will always work.

 DWORD start = timeGetTime(); DoSomthingThatTakesLessThen49Days(); DWORD duration = timeGetTime() - start; 

Even if timeGetTime DoSomthingThatTakesLessThen49Days over when calling DoSomthingThatTakesLessThen49Days duration , it will still be correct.

Please note that the following code cannot complete when rollover.

 DWORD start = timeGetTime(); DoSomthingThatTakesLessThen49Days(); if (now + 5000 < timeGetTime()) { } 

but it can be easily rewritten to work as follows

 DWORD start = timeGetTime(); DoSomthingThatTakesLessThen49Days(); if (timeGetTime() - start < 5000) { } 
+1
source

Assuming you can guarantee that this function will be called at least once every 49 days, something like this will work:

 // Returns current time in milliseconds uint64_t timeGetTime64() { static uint32_t _prevVal = 0; static uint64_t _wrapOffset = 0; uint32_t newVal = (uint32_t) timeGetTime(); if (newVal < _prevVal) _wrapOffset += (((uint64_t)1)<<32); _prevVal = newVal; return _wrapOffset+newVal; } 

Please note that due to the use of static variables this function is not multi-threaded, therefore, if you plan to call it from several threads, you must serialize it through a critical section or mutex or similar.

+1
source

You can use RDTSC . To get the time in milliseconds, you can get the conversion factor:

 double get_rdtsc_coeff() { static double coeff = 0.0; if ( coeff < 1.0 ) { // count it only once unsigned __int64 t00 = __rdtsc(); Sleep(1000); unsigned __int64 t01 = __rdtsc(); coeff = (t01-t00)/1000.0; } return coeff; // transformation coefficient } 

Now you can get the number of milliseconds from the last reset:

 __int64 get_ms_from_start() { return static_cast<__int64>(__rdtsc()/get_rdtsc_coeff()); } 

If your system uses SpeedStep or similar technologies, you can use QueryPerformanceCounter / QueryPerformanceFrequency . Windows gives guarantees, then the frequency cannot change during the operation of the system.

0
source

I’m not sure if this fully suits your needs, but

 std::chrono::system_clock 

may match what you are looking for.

http://en.cppreference.com/w/cpp/chrono/system_clock

0
source

Source: https://habr.com/ru/post/1309649/


All Articles