【问题标题】:Boost Asio Async Connection Race Condition?提升 Asio 异步连接竞争条件?
【发布时间】: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


    【解决方案1】:

    Asio 库正准备标准化为 NetworkingTS。这部分确实是交易:

    处理程序仅由当前正在调用 io_context 的 run()、run_one()、run_for()、run_until()、poll() 或 poll_one() 的任何重载的线程调用

    您认为整个示例是 100% 单线程¹是正确的。不能有比赛。

    我个人觉得最好的资源是Threads and Boost.Asio页面:

    • 通过仅从单个线程调用 io_context::run(),用户的代码可以避免与同步相关的开发复杂性。例如,图书馆用户可以实现单线程的可扩展服务器(从用户的角度来看)。

    这也重申了之前的真相:

    [...] 以下保证:

    • 只会从当前正在调用 io_context::run() 的线程中调用异步完成处理程序。

    ¹ 取决于平台/扩展的潜在内部服务线程除外,如threads 页面详细信息

    【讨论】:

    • 作为对如何阅读 Asio 等“标准版”文档的一个很好的见解,我喜欢阅读 @VinnieFalco 在 composed operations 上的文章。他们非常清楚你必须如何以标准的心态阅读 Asio 文档。很少有词是偶然的,许多“涌现”的属性也没有多余的描述。例如。 this comment 中的解释尤其具有说明性。
    猜你喜欢
    • 2010-11-27
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多