Reputation: 2542
In C++, I can call functions periodically in the range of milliseconds using the Windows Multimedia timer as following :
timeSetEvent(intPeriod_Milliseconds, 0, vidTimerCallback, ...., TIME_PERIODIC )
where intPeriod_Milliseconds
is an integer variable with the required period in milliseconds.
How can I get the function vidTimerCallback
to be called every 0.5 milliseconds or something in the range of microseconds ?
Now, I have something like this:
#include <windows.h>
double PCFreq = 0.0;
__int64 CounterStart = 0;
void StartCounter()
{
LARGE_INTEGER li;
if(!QueryPerformanceFrequency(&li))
cout << "QueryPerformanceFrequency failed!\n";
PCFreq = double(li.QuadPart)/1000.0;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
}
double GetCounter()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart-CounterStart)/PCFreq;
}
int main()
{
StartCounter();
Sleep(1000);
cout << GetCounter() <<"\n"; //It prints accurate time like 998
return 0;
}
But I can't further improve it to call a function periodically. I have something similar to this situation using the class here.
Also, I have something that works very well, but it's for C# not C++ (here).
Upvotes: 1
Views: 1799
Reputation: 1
Im not quiet sure what you are trying to achieve, but from what I can see it looks like you are trying to make some sort of a custom wait command?
void CustomWait(double MStoWait)
{
double StartCount = double( GetCounter() + MStoWait );
while(GetCounter() <= StartCount) {}
printf("%f\n" ,GetCounter());
}
And then the while loop in the main
while(1)
{
CustomWait(500.0);
//do stuff
}
Upvotes: 0
Reputation: 941218
That C# code uses a hot wait-loop to measure time. The .NET Stopwatch class is a wrapper for QueryPerformanceCounter(), you can use that too. The Thread.SpinWait() method is a wrapper for YieldProcessor(), you can use that too. The argument is merely the number of times you call it, using 10 is rather arbitrary.
Do keep in mind that this is not a spinwait that the thread scheduler is aware of. As far as it is concerned, you are burning through your thread quantum without ever yielding. And of course you are, that core isn't doing anything very useful. YieldProcessor() merely avoids setting the processor on fire by executing the PAUSE instruction. The consequence is that your timer will perform poorly when the machine gets loaded and other threads compete for CPU service. Your thread will go in the dog house for a while after it burned through its quantum, 45 msec is pretty normal. Do make sure that this isn't detrimental, it almost always is. Raising the thread priority helps a bit, you still can't compete with kernel threads. Particularly video and audio drivers will give you a migraine.
The multi-media timer doesn't have this problem, but of course you can't go below 1 msec. You should use CreateTimerQueueTimer() on all modern versions of Windows instead, it doesn't suffer from the miserable side-effects of calling timeBeginPeriod(). Strongly recommended over a hot wait-loop.
Upvotes: 4
Reputation: 604
You can't. Windows is not a real time OS, so even if it had functions that accepted microsecond parameters or else you were to design your own scheduler on top of Windows, you would still be unable to execute some function at such rates. In fact, Windows does not guarantee any real execution hard limits on when a specific thread will be woken as far as I know. Generally it operates at about 15 millisecond resolutions, so unless you call TimeBeginPeriod(1) somewhere in your app, asking Windows to perform Sleep(1) will most likely sleep 15 msecs.
Upvotes: 1