如果调用 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 缺少完成条件。当strand
s 与异步操作一起使用时,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 可能与许多strand
s 相关联。这种关系允许多个不同的strand
对象共享单个strand 实现。因此,文档remarks:
实现不保证通过不同的链对象发布或分派的处理程序将被同时调用。
Boost.Asio 控制这些 strand 实现 的生命周期,并在固定大小的 strand 实现 池中延迟分配它们。可以通过将BOOST_ASIO_STRAND_IMPLEMENTATIONS
定义为所需的数字来配置池的大小。由于 strand
对象的生命周期不会影响 strand 实现 的生命周期,因此异步操作不需要关心包裹处理程序的 strand
的生命周期。
【讨论】:
对不起,我没有清楚地解释我的问题。刚刚更新了。 @updogliu 我已经更新了答案,希望能为您的问题提供高级和低级的详细信息。 您的另一个答案应该转到 Asio 文档!非常感谢! 整个 Asio 是否有一个单一的链实现池,或者每个io_service
都有自己的一个?
@updogliu 池每个io_service
。 strand_impl
池由strand_service
维护,每个io_service
的service_registry
将不超过一个strand_service
。以上是关于如果调用 asio::strand 的析构函数时,该链上仍有一些就绪/未就绪的处理程序怎么办?的主要内容,如果未能解决你的问题,请参考以下文章