如何在 Asio 中取消组合异步操作?

问题描述 投票:0回答:1

我想使用组合的异步操作

asio::async_connect
,并取消它,可能是在它所进行的
basic_socket::async_connect
的各个调用之间。

以同样的方式,我想取消我自己组合的异步操作(使用

async_compose
)。

不是问如何取消非组合成员函数

basic_socket::async_connect
,为此我可以调用
basic_socket::cancel

free 函数是组合的,因此在套接字上调用

cancel
可能会停止正在进行的
socket::async_connect
,但它不会停止排队操作。

  1. 如何取消

    asio::async_connect

  2. 一般来说,如何取消组合操作?

  3. 如何取消自定义组合操作? (至少使用第三个选项,我可以侵入某种取消令牌系统,该系统可以检查“构建块”异步操作之间的标志,但在这种情况下我仍然无法使用现有的组合操作)。

要总结这个问题,请参阅 Robert Leahy 的 2019 CppCon 演讲中的图表:

这显示了

async_write
的问题,组合操作也存在此问题。

Robert Leahy 通过在包装对象中重新实现

async_write
来解决这个问题,该对象在调用底层流上的每个原子
async_write_some
操作之前检查取消标志。

也许这就是解决方案,但这意味着我必须重新实现每个内置组合 asio 操作才能使用这种类似的包装对象。

c++ c++17 boost-asio cancellation
1个回答
0
投票

稍后为后代重新审视我自己的问题:我认为组合取消支持是一个相当新的功能,并且截至撰写本文时,很多此类内容仍然是

experimental::

从 Asio 1.19.0 开始,如果组合操作支持取消(请参阅文档),那么您似乎可以将

cancellation_slot
绑定到它(使用
bind_cancellation_slot
)并使用关联的
 触发它cancellation_signal
,或者使用 逻辑运算符与
awaitables
,这将自动触发取消。

文档中描述了此过程:https://think-async.com/Asio/boost_asio_1_22_1/doc/html/boost_asio/overview/core/cancellation.html给出了以下示例:

class session
  : public std::enable_shared_from_this<proxy>
{
  ...

  void do_read()
  {
    auto self = shared_from_this();
    socket_.async_read_some(
        buffer(data_),
        boost::asio::bind_cancellation_slot(
          cancel_signal_.slot(),
          [self](boost::system::error_code error, std::size_t n)
          {
            ...
          }
        )
      );
  }

  ...

  void request_cancel()
  {
    cancel_signal_.emit(boost::asio::cancellation_type::total);
  }

  ...

  boost::asio::cancellation_signal cancel_signal_;
};

这些

cancellation_slot
/
cancellation_signal
看起来就像花哨的
std::stop_tokens
一样。在自定义组合操作中使用它们实现取消似乎有所不同,具体取决于您使用的组合方法(
async_compose
experimental::co_composed
、回调链),但 co_composed 文档 提供了手动和隐式取消检查的示例回声协议。
co_composed
使用一些神奇的
auto state
对象来进行取消检查,我猜它是某个地方
cancellation_slot
的包装器。

© www.soinside.com 2019 - 2024. All rights reserved.