asio::async_connect
,并取消它,可能是在它所进行的 basic_socket::async_connect
的各个调用之间。
async_compose
)。
basic_socket::async_connect
,为此我可以调用basic_socket::cancel
。
free 函数是组合的,因此在套接字上调用
cancel
可能会停止正在进行的 socket::async_connect
,但它不会停止排队操作。
如何取消
asio::async_connect
?
一般来说,如何取消组合操作?
如何取消自定义组合操作? (至少使用第三个选项,我可以侵入某种取消令牌系统,该系统可以检查“构建块”异步操作之间的标志,但在这种情况下我仍然无法使用现有的组合操作)。
要总结这个问题,请参阅 Robert Leahy 的 2019 CppCon 演讲中的图表:
这显示了
async_write
的问题,组合操作也存在此问题。
Robert Leahy 通过在包装对象中重新实现
async_write
来解决这个问题,该对象在调用底层流上的每个原子 async_write_some
操作之前检查取消标志。
也许这就是解决方案,但这意味着我必须重新实现每个内置组合 asio 操作才能使用这种类似的包装对象。
稍后为后代重新审视我自己的问题:我认为组合取消支持是一个相当新的功能,并且截至撰写本文时,很多此类内容仍然是
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
的包装器。