tags:

views:

162

answers:

5

timeGetTime seems to be quite good to query for system time. However, its return value is 32-bit only, so it wraps around every 49 days approx.

It's not too hard to detect the rollover in calling code, but it adds some complexity, and (worse) requires keeping a state.

Is there some replacement for timeGetTime that would not have this wrap-around problem (probably by returning a 64-bit value), and have roughly the same precision and cost?

A: 

You could use RDTSC intrinsic. To get time in milliseconds you could get transform coefficient:

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 could get count 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 could use QueryPerformanceCounter/QueryPerformanceFrequency functions. Windows gives guarantees then the frequency cannot change while the system is running.

Kirill V. Lyadvinsky
SpeedStep but an end to the usefulness of this approach. http://en.wikipedia.org/wiki/SpeedStep
Hans Passant
True, for SpeedStep systems this will not work. Updated my answer.
Kirill V. Lyadvinsky
+1  A: 

Have a look at GetSystemTimeAsFileTime(). It fills a FILETIME struct that contains a "64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC)"

Elrohir
+1  A: 

What platform?

You could use GetTickCount64() if you're running on Vista or later, or synthesise your own GetTickCount64() from GetTickCount() and a timer...

I deal with the rollover issue in GetTickCount() and synthesising a GetTickCount64() on platforms that don't support it here on my blog about testing non-trivial code: http://www.lenholgate.com/archives/000773.html

Len Holgate
A: 

How are you trying to use it? I frequently use the Win32 equivalent when checking for durations that I know will be under 49 days. For example the following code will always work.

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

Even if timeGetTime rolled over while calling DoSomthingThatTakesLessThen49Days duration will still be correct.

Note the following code could fail on rollover.

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

but can easy be re-written to work as follows

DWORD start = timeGetTime();
DoSomthingThatTakesLessThen49Days();
if (timeGetTime() - start < 5000)
{
}
Stephen Nutt
+1  A: 

Nope, tracking roll-over requires state. It can be as simple as just incrementing your own 64-bit counter on each callback.

It is pretty unusual to want to track time periods to a resolution as low as 1 millisecond for up to 49 days. You'd have to worry that the accuracy is still there 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 kept accurate with a time server.

Hans Passant
The count toward rollover starts when the system starts, so the program does not have to be running for 49 days to see a rollover.
Thomas