Will Perone

Tired of all those different versions of windows having different timer resolution for Sleep() ? Here is a little trick on how to sleep for an accurate number of milliseconds.

First off at the beginning of your program you need to have:
HANDLE     hMMEvent; // this guy should be global or a static class member

hMMEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
ResetEvent(hMMEvent);	
Then just define a custom sleep function like the following:
void MySleep(float seconds) // can change this to be passed in milliseconds if you want
{ 
    const unsigned int milliseconds= (unsigned int)(seconds*1000.f);

    if (!milliseconds)
    {
       ::Sleep(0); // call the normal sleep function
       return;
    }	
	
    MMRESULT uID = timeSetEvent(milliseconds, 0, (LPTIMECALLBACK)hMMEvent,NULL,TIME_CALLBACK_EVENT_SET);
    DWORD dwWaitRez = WaitForSingleObject(hMMEvent, milliseconds+1);
    ResetEvent(hMMEvent);
    timeKillEvent(uID);
}
Don't forget to link with winmm.lib for this to work. This more accurate sleep function allows you to do neat things like clamp your application's framerate. You should check for a high performance counter and get the time the application takes to process a frame, then sleep for the rest of the time till you hit the clamp value
First, at the beginning of your code you will want to have the following:
// globals
__int64    TimeCounter;
__int64    TimeFrequency;   
float      Timetimelast2;
bool       hirestimer;


QueryPerformanceFrequency((LARGE_INTEGER *)&TimeFrequency);
if (!QueryPerformanceCounter((LARGE_INTEGER *)&TimeCounter))		
     hirestimer= false;		   
else hirestimer= true;	
Timetimelast2= GetTime();

Then we will define the following functions:

float GetTime()
{	
	if (hirestimer)
	{
		QueryPerformanceCounter((LARGE_INTEGER *)&TimeCounter);
		return (float)TimeCounter/TimeFrequency;
	} else 
		return (float)clock()/CLOCKS_PER_SEC;					
}

void LockFrameRate(unsigned int lockedframerate) // in frames per second
{
	const float timediff_limit= 1.f/(float)lockedframerate;
	
	timelast= timecurr;	
	timecurr= GetTime();
	timediff= timecurr-timelast;
	
	// sleep till we hit constant framerate
	if (timecurr-Timetimelast2 < timediff_limit)	
        MySleep(timediff_limit - (timecurr-Timetimelast2));

	Timetimelast2= GetTime(); // set here so that we can determine the time for the rest of the application's processing
}
Now all you need to do is call LockFrameRate with the frame rate you want to have, although there is a bit of a catch in that you are working at a maximum resolution of 1 ms time difference. And for example, to lock at 60fps will be 1000/60 = 16 & 2/3 so it's going to round down to 16ms sleep which casting back up yields about 62.5fps so you may not be able to perfectly get the fps you want even with this method but this is generally close enough for most applications. For an implementation of this see my Uber Timer.
No Comments yet, be the first!
<- for private contact