何时取消boost :: asio处理程序的处理程序会运行?

时间:2015-03-13 21:24:08

标签: boost boost-asio

提升文档say取消了异步连接,发送和接收立即完成,取消操作的处理程序将传递boost :: asio :: error :: operation_aborted错误。

我想知道取消的处理程序是否可以运行(并查看operation_aborted错误) 之前的其他(未取消和新安排的)完成处理程序运行

以下是关注我的时间表:

acceptHandler和readHandler在同一个事件循环和同一个线程上运行。

  • time t0 - readHandler在oldConnectionSocket上运行
  • 时间t1 - acceptHandler运行
  • 时间t2 - acceptHandler调用oldConnectionSocket.cancel
  • 时间t3 - acceptHandler关闭oldConnectionSocket
  • 时间t4 - acceptHandler调用newConnectionSocket.async_read(... readHandler ...)
  • 时间t5 - 调用readHandler(从哪个上下文?)

是否可以在t5时在newConnectionSocket上下文中调用readHandler 在oldConnectionSocket上下文中使用operation_aborted错误调用它?

1 个答案:

答案 0 :(得分:4)

取消的操作将立即发布其处理程序以进行延迟调用。但是,io_service不保证处理程序的调用顺序。因此,io_service可以选择以任一顺序调用ReadHandler。目前,只有strand指定在某些条件下保证订购。

在完成处理程序中,如果目标是知道哪个I / O对象与操作相关联,那么考虑构造完成处理程序,使其具有I / O对象的显式句柄。这通常使用以下任何一项来完成:

  • 自定义函子
  • std::bind()boost::bind()
  • 一个C ++ 11 lambda

一个常见的习惯用法是让一个继承自boost::enable_shared_from_this<>的类管理I / O对象。当一个类继承自boost::enable_shared_from_this时,它提供了一个shared_from_this()成员函数,该函数将有效的shared_ptr实例返回给thisshared_ptr的副本将传递给完成处理程序,例如lambda中的捕获列表或作为实例句柄传递给boost::bind()。这允许处理程序知道执行操作的I / O对象,并使I / O对象的生命周期至少与处理程序一样长。有关使用此方法的示例,请参阅Boost.Asio asynchronous TCP daytime server教程。

class tcp_connection
  : public boost::enable_shared_from_this<tcp_connection>
{
public:

  // ...

  void start()
  {    
    boost::asio::async_write(socket_, ...,
        boost::bind(&tcp_connection::handle_write, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void handle_write(
    const boost::system::error_code& error,
    std::size_t bytes_transferred)
  {
    // I/O object is this->socket_.
  }

  tcp::socket socket_;
};

另一方面,如果目标是确定一个处理程序是否在另一个处理程序之前执行,那么:

  • 应用程序需要明确管理状态
  • 尝试管理多个相关的调用链可能会引入不必要的复杂性,并且通常表明需要重新检查设计
  • 自定义处理程序可用于优先处理执行处理程序的顺序。 Boost.Asio Invocation示例使用添加到优先级队列的自定义处理程序,然后在稍后的时间执行。