我还没有找到它的需要,因为它可以通过正确设计异步调用链来正确解决。一般来说,Boost.Asio API 经过精心设计,可以防止复杂的应用程序在异步流程中变得复杂。
如果您已经检查了调用链,并且绝对确定重新设计它们的工作在当前和未来比引入清除链的复杂性更大,那么有一种方法可以实现它。然而,它确实有删除所有未调用的处理程序的主要副作用。strand
,及其相关的io_service
.
When a strand
被毁坏了,其析构函数 http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/io_service__strand/_strand.html安排未调用的处理程序延迟调用io_service
维持非并发的保证。这io_service
析构函数 http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/io_service/_io_service.html表明计划延迟调用的未调用处理程序对象将被销毁。因此,通过控制寿命strand
and io_service
,可以清除一串中的处理程序。
这是一个带有辅助类的过于简化的示例clearable_strand
.
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
class clearable_strand
{
public:
clearable_strand(boost::asio::io_service& main_io_service)
: main_io_service_(main_io_service)
{
clear();
}
public:
template <typename Handler>
void post(const Handler& handler)
{
// Post handler into the local strand.
local_strand_->post(handler);
// Local service now has work, so post its run handler to the
// main service.
main_io_service_.post(boost::bind(
&boost::asio::io_service::run_one, boost::ref(local_io_service_)));
}
void clear()
{
// Destroy previous (if any).
local_strand_ = boost::none;
local_io_service_ = boost::none;
// Reconstruct.
local_io_service_ = boost::in_place();
local_strand_ = boost::in_place(boost::ref(local_io_service_.get()));
}
private:
boost::asio::io_service& main_io_service_;
boost::optional<boost::asio::io_service> local_io_service_;
boost::optional<boost::asio::strand> local_strand_;
};
为了最大限度地减少影响,以便只有strand
的处理程序被销毁,该类使用内部io_service
而不是附加strand
到主要io_service
。当工作发布到strand
,然后将处理程序发布到主程序io_service
这将菊花链并服务于本地io_service
.
及其用法:
void print(unsigned int x)
{
std::cout << x << std::endl;
}
int main()
{
boost::asio::io_service io_service;
io_service.post(boost::bind(&print, 1));
clearable_strand strand(io_service);
strand.post(boost::bind(&print, 2));
strand.post(boost::bind(&print, 3));
strand.clear(); // Handler 2 and 3 deleted.
strand.post(boost::bind(&print, 4));
io_service.run();
}
运行程序会输出1
and 4
。我想强调的是,这是一个过于简化的示例,并以不复杂的方式提供线程安全性以匹配boost::asio::strand
可能是一个挑战。