When do handlers for cancelled boost::asio handlers get to run?

后端 未结 1 1772
旧时难觅i
旧时难觅i 2020-12-30 18:54

The boost docs say that cancelled async connect, send and receive finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::op

相关标签:
1条回答
  • 2020-12-30 19:17

    Cancelled operations will immediately post their handlers for deferred invocation. However, the io_service makes no guarantees on the invocation order of handlers. Thus, the io_service could choose to invoke the ReadHandlers in either order. Currently, only a strand specifies guaranteed ordering under certain conditions.

    Within a completion handler, if the goal is to know which I/O object was associated with the operation, then consider constructing the completion handler so that it has an explicit handle to the I/O object. This is often accomplished using any of the following:

    • a custom functor
    • std::bind() or boost::bind()
    • a C++11 lambda

    One common idiom is to have the I/O object be managed by a single class that inherits from boost::enable_shared_from_this<>. When a class inherits from boost::enable_shared_from_this, it provides a shared_from_this() member function that returns a valid shared_ptr instance to this. A copy of the shared_ptr is passed to completion handlers, such as a capture-list in lambdas or passed as the instance handle to boost::bind(). This allows for the handlers to know the I/O object on which the operation was performed, and causes the lifetime of the I/O object to be extended to at least as long as the handler. See the Boost.Asio asynchronous TCP daytime server tutorial for an example using this approach.

    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_;
    };
    

    On the other hand, if the goal is to determine if one handler has executed before the other, then:

    • the application will need to explicitly manage the state
    • trying to manage multiple dependent call chains may be introducing unnecessary complexity and often indicates a need to reexamine the design
    • custom handlers could be used to prioritize the order in which handlers are executed. The Boost.Asio Invocation example uses custom handlers that are added to a priority queue, which are then executed at a later point in time.
    0 讨论(0)
提交回复
热议问题