3

I'm working on a timing system and I'll implement a timer class.

#include <windows.h>
#include <stdio.h>
#include <time.h>

int main()
{
    clock_t t1, t2;
    t1 = clock();
    Sleep(10);
    t2 = clock();
    printf("%i\n", (int)(t2 - t1));
    return 0;
}

This program should print "10" but it prints "15" or "16". I need more accurate which is less than 1 ms! Suggestions? (maybe with select()'s timeout?)

NOTE: I've run this program on Windows 7 Ultimate x86. Program compiled with MinGW (C/C++) x86.

NOW I THINK >>

Community
  • 1
  • 1
PilawyerDev
  • 271
  • 2
  • 16

3 Answers3

4

Sleep() is accurate to the operating system's clock interrupt rate. Which by default on Windows ticks 64 times per second. Or once every 15.625 msec, as you found out.

You can increase that rate, call timeBeginPeriod(10). Use timeEndPeriod(10) when you're done. You are still subject to normal thread scheduling latencies so you still don't have a guarantee that your thread will resume running after 10 msec. And won't when the machine is heavily loaded. Using SetThreadPriority() to boost the priority, increasing the odds that it will.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    ... or even timeBeginPeriod(1). But: Better use `wPeriodMin` of the `TIMECAPS` structure filled by a call to [timeGetDevCaps](http://msdn.microsoft.com/en-us/library/windows/desktop/dd757627%28v=vs.85%29.aspx). Note: The resulting period depends on the underlying hardware. – Arno Oct 17 '13 at 13:13
  • Only ask for what you need, using 1 is wasteful. The minimum period doesn't matter much, it is already automatically adjusted and there isn't anything you can do about it if it is more than you need. The last machine that didn't support it died 15 years ago anyway. – Hans Passant Oct 17 '13 at 13:34
  • Is it more than needed? The call to Sleep(10) may not always happen **in phase, at the time of the interrupt**. Calling Sleep(10) 5 ms ahead of the next interrupt will result in a total sleep of 15 ms when timeBeginPeriod(10) is used. – Arno Oct 17 '13 at 14:31
  • Yes, that's true. Then again, the code already started running at a clock interrupt so there's accidental phasing. – Hans Passant Oct 17 '13 at 14:43
  • well, there may be some loop structure with such approaches but the code given here is asynchronous. ... never mind. – Arno Oct 17 '13 at 14:49
2

Your problem is that the "clock" only ticks 64 times per second (I've seen systems that can go up to 2000, but no higher). If you are creating a timer class, you probably want to have much higher resolution than even 2000. Use QueryPerformanceCounter to get higher resolution. See QueryPerformanceCounter and overflows for an example.

Note that if you want to sleep for very short intervals, you will have to call QueryPerformanceCounter in a tight loop.

Community
  • 1
  • 1
Gabe
  • 84,912
  • 12
  • 139
  • 238
1

Sleep() is not accurate in the way you want it to be.

It will cause the thread to sleep for AT LEAST the length of time you specify, but there's no guarantee that the OS will return control to your thread at exactly that specified time.

Baldrick
  • 11,712
  • 2
  • 31
  • 35