5

如何清除所有已在 a 中排队的已发布任务io_service::strand?我从 boost 文档中看不到类似的方法。

4

2 回答 2

8

我还没有找到对它的需求,因为它可以通过正确设计异步调用链来正确解决。通常,Boost.Asio API 是经过精心设计的,它可以防止复杂的应用程序在异步流程中变得复杂。

如果您已经检查了调用链,并且绝对确定重新设计它们的努力比引入清除链的复杂性在当前和未来的风险更大,那么有一种方法可以实现它。strand但是,它确实具有删除 中所有未调用的处理程序及其相关联的主要副作用io_service

当 astrand被销毁时,它的析构函数调度未调用的处理程序以延迟调用以io_service保持非并发性的保证。io_service 析构函数声明计划用于延迟调用的未调用处理程序对象被销毁。因此,通过控制 and 的生命周期strandio_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到 main 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();
}

运行程序会输出14。我想强调的是,这是一个过于简化的示例,并且以不复杂的方式提供线程安全以匹配其boost::asio::strand可能是一个挑战。

于 2013-03-05T16:54:15.877 回答
2

这是不可能的,您需要根据您的目标重新构建您的设计。如果您希望某些高优先级处理程序在低优先级处理程序之前运行,一种可能性是利用优先处理程序示例。

于 2013-03-04T21:51:39.743 回答