每1秒调用一次函数(精确地) [英] Calling a function every 1 second (precisely)
问题描述
我正在使用C ++开发一个简单的游戏模拟程序,有一个名为update()的函数可以更新游戏的当前状态,必须每1秒钟精确调用一次.如果我使用这样的循环:
I am working on a simple game simulation program in C++, there's a function called update() that updates the current state of the game, it has to be called every 1 second precisely. If I use a loop like this:
while(//some condition) {
update();
Sleep(1000);
}
然后,该函数将不会每隔1秒调用一次,而是每隔(1 + update()的执行时间)调用一次. 我了解了各种解决方案,例如异步函数,多线程或使用std :: chrono计算函数的执行时间,并将其从1000ms参数中减去以进行睡眠.对于我的简单案例而言,其中一些过于复杂,如果我不太了解它们,则其他一些使用起来似乎是不安全的.
Then the function will not be called every 1 second, instead, every (1 + execution time of update () ). I read about various solutions like async functions, multithreading, or calculating the function's execution time using std::chrono and subtracting it from the 1000ms parameter to sleep. Some of those were too complicated for my simple case, and others seemed unsafe to use if I don't understand them really well.
谁能告诉我什么是适合我要求的解决方案? 预先感谢.
Can anyone tell me what would be a suitable solution to my requirement? Thanks in advance.
推荐答案
除了需要长时间睡眠外,您还需要直到某个时间点进行睡眠.例如,如果您的第一次更新恰好是2:00:00.000,则您以后的更新应尽可能接近2:00:01.000、2:00:02.000等.
Instead of sleeping for a duration, you need to sleep until a time point. For example, if your first update is at precisely 2:00:00.000, your future updates should come as closely as possible to 2:00:01.000, 2:00:02.000, etc.
要实现此目的,您可以指定一个线程进行更新,并且在更新之后,下次进入睡眠状态直到下一次进行计划的更新. chrono::system_clock::time_point
和this_thread::sleep_until
是执行此操作的工具.
To achieve this you can dedicate a thread to updating, and after the update, goes to sleep until the next time to do a scheduled update. chrono::system_clock::time_point
and this_thread::sleep_until
are your tools to do this.
例如:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
class UpdateManager
{
public:
explicit UpdateManager() = default;
private:
static std::atomic<int> now_;
static std::atomic<bool> stop_;
struct update_thread
: private std::thread
{
~update_thread();
update_thread(update_thread&&) = default;
using std::thread::thread;
};
public:
static update_thread start();
};
void update();
// source
std::atomic<int> UpdateManager::now_{0};
std::atomic<bool> UpdateManager::stop_{false};
UpdateManager::update_thread::~update_thread()
{
if (joinable())
{
stop_ = true;
join();
}
}
UpdateManager::update_thread
UpdateManager::start()
{
return update_thread{[]
{
using namespace std;
using namespace std::chrono;
auto next = system_clock::now() + 1s;
while (!stop_)
{
update();
this_thread::sleep_until(next);
next += 1s;
}
}};
}
#include "date/date.h"
void
update()
{
using namespace date;
using namespace std;
using namespace std::chrono;
cerr << system_clock::now() << '\n';
}
// demo
int
main()
{
auto t = UpdateManager::start();
using namespace std;
this_thread::sleep_for(10s);
}
仅出于演示目的(对于逻辑不是必需的),我使用的是 Howard Hinnant,免费的开源日期/时间库,以微秒为单位打印当前时间(UTC),以说明该技术的稳定性.该程序的示例输出为:
Just for demo purposes (not necessary for the logic), I'm using Howard Hinnant's, free, open-source date/time library to print the current time (UTC) to microsecond precision in order to illustrate the stability of this technique. A sample output of this program is:
2018-05-02 15:14:25.634809
2018-05-02 15:14:26.637934
2018-05-02 15:14:27.636629
2018-05-02 15:14:28.637947
2018-05-02 15:14:29.638413
2018-05-02 15:14:30.639437
2018-05-02 15:14:31.637217
2018-05-02 15:14:32.637895
2018-05-02 15:14:33.637749
2018-05-02 15:14:34.639084
这篇关于每1秒调用一次函数(精确地)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!