#include <iostream> #include <> #include <thread> #pragma comment( lib, "Winmm" ) static int counter = 0; static int64_t ticks_per_second; void __stdcall on_timer(HWND h, UINT ui, UINT_PTR up, DWORD dw) { std::cout << "time out, counter=" << counter << std::endl; counter = 0; } void get_message_trd_func() { SetTimer(NULL, 0, 1000, on_timer); MSG msg; while (GetMessageA(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessageA(&msg); } } int main() { std::cout << "go!" << std::endl; timeBeginPeriod(1); QueryPerformanceFrequency((LARGE_INTEGER*)&ticks_per_second); const double expected = 1.0 / 60.0; const int64_t expected_ticks = (int64_t)(expected * ticks_per_second); std::thread thr(get_message_trd_func); for (;;) { int64_t before_ticks = 0; QueryPerformanceCounter((LARGE_INTEGER*)&before_ticks); // do something... for (int i = 0; i < 10000; i++) { float a = i * i + i + sin(i) + sqrt(i); } int64_t after_ticks = 0; QueryPerformanceCounter((LARGE_INTEGER*)&after_ticks); counter++; int64_t ticks_need_sleep = expected_ticks - (after_ticks - before_ticks); double ms_need_sleep = (double)ticks_need_sleep / ticks_per_second * 1000.0; if (ms_need_sleep >= 1.0) Sleep((DWORD)ms_need_sleep); else continue; } }
The win32api are mainly used here.
MMRESULT timeBeginPeriodUse this API requires link
Winmm
, so we add it at the top of the file#pragma comment( lib, "Winmm" )
.
Its function is to request to improve the accuracy of some timers, such as hereSleep
, By default, Windows only seems to provide us with rough accuracy of about 10ms, so here we directly request the highest accuracy possible, that is,1ms
.QueryPerformanceFrequencyThe API is used to get the accuracy of a "performance timer" in ticks per second. On my machine its value is
10000000
, the accuracy can be seen is still very satisfactory. Here we will use it withexpected
(that is, the interval expected to be in units s) are multiplied to obtain an interval in units of ticks.QueryPerformanceCounterThe API detects the value of the "performance timer" in ticks, and its accuracy is described as <1us in msdn.
Then combine the above APIs and several simple mathematical operations, so that the function can be called in a relatively stable timed manner (here is 1s 60 times):
time out, counter=59 time out, counter=59 time out, counter=60 time out, counter=59 time out, counter=58 time out, counter=60
When you comment outtimeBeginPeriod
After the call, you will find that the result is not very optimistic (even if we expect 1s to be called 60 times):
time out, counter=33 time out, counter=31 time out, counter=32 time out, counter=31
Finally, this may be common in the game's frame rate control, and in fact I know these things from here (x
This is the article about using c++ to stably execute a function on Windows. For more related contents of c++ timing execution, please search for my previous article or continue browsing the related articles below. I hope everyone will support me in the future!