【发布时间】:2019-01-17 17:25:42
【问题描述】:
这个问题的灵感来自 boost asio 文档 (link) 中关于异步计时器的教程。代码稍作修改,效果更明显。
有一个相关的问题,Multiple async_wait from a boost Asio deadline_timer。但我不确定该问题的答案是否适用于我的情况。
代码非常简单,如果重复的行被注释掉,就可以正常工作,如下所示。
持续时间为
1s的steady_timer调用async_wait。当它过期时,将调用处理程序。在处理程序内部,定时器的生命周期再延长一秒,定时器再次调用
async_wait。20 的变量
count用于限制计时器可以触发的次数。
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>
namespace asio = boost::asio;
void bind_handler(const boost::system::error_code& ec,
asio::steady_timer& t,
int count) {
if (count > 0) {
std::cout << "getting " << count << "\n";
t.expires_at(t.expiry() + std::chrono::seconds(1));
t.async_wait(boost::bind(bind_handler, asio::placeholders::error,
boost::ref(t), --count));
}
}
int main() {
asio::io_context io_context(1);
asio::steady_timer t(io_context, std::chrono::seconds(1));
int count = 20;
t.async_wait(boost::bind(bind_handler, asio::placeholders::error,
boost::ref(t), count));
//t.async_wait(boost::bind(bind_handler, asio::placeholders::error,
// boost::ref(t), count));
auto start = std::chrono::steady_clock::now();
io_context.run();
auto end = std::chrono::steady_clock::now();
std::cout
<< std::chrono::duration_cast<std::chrono::seconds>(end - start).count()
<< " seconds passed\n";
return 0;
}
此代码的输出如下所示。每经过一秒就会打印一个新行。
getting 20
getting 19
getting 18
...lines...
...omitted...
getting 3
getting 2
getting 1
21 seconds passed
但是,如果上面代码中的两行未注释,则程序的行为会非常不同。输出粘贴在下面。程序在一秒钟内打印从getting 20 到getting 1 的所有行,40 秒内什么都不显示,然后打印最后一行。
getting 20
getting 20
getting 19
getting 19
getting 18
getting 18
...lines...
...omitted...
getting 3
getting 3
getting 2
getting 2
getting 1
getting 1
41 seconds passed
我的问题是,async_wait 的多次递归调用如何影响程序的行为?我觉得某种数据竞赛正在进行,但数字仍然按顺序打印。此外,只涉及一个线程,正如我们在io_context构造函数中看到的那样。
【问题讨论】:
标签: c++ boost boost-asio