【发布时间】:2020-11-22 08:59:41
【问题描述】:
我正在查看Boost Asio Blocking TCP Client timeout 示例,特别感兴趣的是如何实现连接超时。我们如何从文档中知道回调处理程序和后续检查不会引入竞争条件?
异步连接命令
boost::asio::async_connect(socket_, iter, var(ec) = _1);
执行var(ec) = _1,它是一旦执行就设置错误代码的处理程序。或者,可以在此处使用完整且显式的 lambda。
同时,check_deadline 函数似乎是
由deadline_ 成员调用。超时似乎是通过让截止日期强制关闭套接字来强制执行的,因此我们假设可能是阻塞语句
do io_service_.run_one(); while (ec == boost::asio::error::would_block);
会回来的。起初我认为错误代码必须是原子的,但似乎并非如此。相反,this page 似乎表明只要对套接字/上下文的调用来自同一线程,strand 模型就会起作用。
因此我们假设每个截止日期(在 Asio 中)的回调和async_connect 例程的句柄不会同时运行。文档中的诸如this 之类的页面暗示处理程序只会在run() 调用期间执行,这将阻止在处理程序当前更改其值期间执行命令while(ec == whatever)。
我如何明确知道这一点?文档中有什么明确告诉我没有处理程序将在这些例程之外执行?如果为真,proactor design pattern 上的页面必须推断这一点,但绝不会明确指出“发起者”指向“完成处理程序”的位置。
我发现的关闭是documentation for io_context 的说法
对 I/O 对象的同步操作隐式运行 io_context 单个操作的对象。 io_context 函数 run(), 必须调用 run_one()、run_for()、run_until()、poll() 或 poll_one() 让 io_context 代表 a 执行异步操作 C++ 程序。异步操作已完成的通知 通过调用关联的处理程序来传递。处理程序是 仅由当前调用任何重载的线程调用 run()、run_one()、run_for()、run_until()、poll() 或 poll_one() io_context。
这意味着如果我有一个线程运行run_one() 命令,那么它的控制路径将等待直到有一个处理程序可用,并最终通过一个处理程序返回并检查ec 值。
这是否正确并且是“处理程序仅由当前正在调用 io_context 的 run()、run_one()、run_for()、run_until()、poll() 或 poll_one() 的任何重载的线程调用。 "为了解代码将如何始终运行而找到的最佳语句?有其他的介绍吗?
【问题讨论】:
标签: c++ concurrency boost-asio