如果调用 asio::strand 的析构函数时,该链上仍有一些就绪/未就绪的处理程序怎么办?

Posted

技术标签:

【中文标题】如果调用 asio::strand 的析构函数时,该链上仍有一些就绪/未就绪的处理程序怎么办?【英文标题】:What if when the destructor of a asio::strand is called, there are still some ready/unready handlers on this strand? 【发布时间】:2014-05-23 06:29:30 【问题描述】:

如果在调用 asio::strand 的析构函数时,该链上仍有一些就绪/未就绪的处理程序怎么办?

根据文档:

尚未调用的通过链发布的处理程序将 仍然以符合保证的方式发送 非并发。

这是否意味着它仍然会调用所有的处理程序,包括等待未就绪的处理程序准备好,就好像它没有被销毁一样(可能除了不接受新的处理程序)?

或者我对“未就绪的处理程序”在概念上是错误的——异步操作不会在完成之前将其处理程序发布到链上?如果调用了目标链的析构函数,这个异步操作会意识到这一点吗?

【问题讨论】:

【参考方案1】:

来自documentation:

通过strand 发布的尚未被调用的处理程序仍将以满足非并发保证的方式调度。

基本上,strand 可以被认为是关联的,但不拥有处理程序队列。如果处理程序队列当前没有处理程序发布到io_service,那么它将从自身弹出一个处理程序并将其发布到关联的io_service。此流程保证不会同时调用发布到同一 strand 的处理程序。

所有发布到strand 的处理程序都被认为可以运行。因此,strand API 缺少完成条件。当strands 与异步操作一起使用时,initiating function 通常提供一个从strand::wrap() 返回的handler

async_op(..., s.wrap(a));

async_op() 完成时,它将调用从s.wrap(a) 返回的处理程序。然后,此处理程序会将用户提供的处理程序a 发布到与原始s 链关联的同一队列的strand 中。由于strand对象的生命周期不影响处理队列的生命周期,所以async_op()不需要关心s的生命周期。

当与strand 关联的io_service 被销毁时,未调用的处理程序将被销毁。 documentation 声明:

计划在io_service 或任何关联的strand 上延迟调用的未调用处理程序对象将被销毁。


更详细地说,strand 实现负责将处理程序排队并保证一次只有一个处理程序发布到io_service,以及@987654350 @ 只提供一个委托给 strand 实现 的公共 API。每个strand 都与一个strand implementation 相关联,而一个strand implementation 可能与许多strands 相关联。这种关系允许多个不同的strand 对象共享单个strand 实现。因此,文档remarks:

实现不保证通过不同的链对象发布或分派的处理程序将被同时调用。

Boost.Asio 控制这些 strand 实现 的生命周期,并在固定大小的 strand 实现 池中延迟分配它们。可以通过将BOOST_ASIO_STRAND_IMPLEMENTATIONS 定义为所需的数字来配置池的大小。由于 strand 对象的生命周期不会影响 strand 实现 的生命周期,因此异步操作不需要关心包裹处理程序的 strand 的生命周期。

【讨论】:

对不起,我没有清楚地解释我的问题。刚刚更新了。 @updogliu 我已经更新了答案,希望能为您的问题提供高级和低级的详细信息。 您的另一个答案应该转到 Asio 文档!非常感谢! 整个 Asio 是否有一个单一的链实现池,或者每个 io_service 都有自己的一个? @updogliu 池每个io_servicestrand_impl 池由strand_service 维护,每个io_serviceservice_registry 将不超过一个strand_service

以上是关于如果调用 asio::strand 的析构函数时,该链上仍有一些就绪/未就绪的处理程序怎么办?的主要内容,如果未能解决你的问题,请参考以下文章

虚析构函数

受保护的与私有的析构函数

继承和组合混搭的情况下,构造和析构函数的调用顺序

C++中,子类会继承父类的虚函数表!对于父类的析构函数(虚函数) 也会继承吗?

C++ 设置基类的析构函数为虚函数

静态对象成员会在所属类的析构函数被调用时自动析构吗?