Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asio::async_write and strand

asio::async_write(m_socket, asio::buffer(buf, bytes),
                custom_alloc(m_strand.wrap(custom_alloc(_OnSend))));

Does this code guarantee that all asynchronous operation handlers(calls to async_write_some) inside async_write are called through strand? (or it's just for my_handler?)

like image 637
Iwa Avatar asked Dec 10 '22 17:12

Iwa


1 Answers

With the following code:

asio::async_write(stream, ..., custom_alloc(m_strand.wrap(...)));

For this composed operation, all calls to stream.async_write_some() will be invoked within m_strand if all of the following conditions are true:

  • The initiating async_write(...) call is running within m_strand():

    assert(m_strand.running_in_this_thread());
    asio::async_write(stream, ..., custom_alloc(m_strand.wrap(...)));
    
  • The return type from custom_alloc is either:

    • the exact type returned from strand::wrap()

      template <typename Handler> 
      Handler custom_alloc(Handler) { ... }
      
    • a custom handler that appropriate chains invocations of asio_handler_invoke():

      template <class Handler>
      class custom_handler
      {
      public:
        custom_handler(Handler handler)
          : handler_(handler)
        {}
      
        template <class... Args>
        void operator()(Args&&... args)
        {
          handler_(std::forward<Args>(args)...);
        }
      
        template <typename Function>
        friend void asio_handler_invoke(
          Function intermediate_handler,
          custom_handler* my_handler)
        {
          // Support chaining custom strategies incase the wrapped handler
          // has a custom strategy of its own.
          using boost::asio::asio_handler_invoke;
          asio_handler_invoke(intermediate_handler, &my_handler->handler_);
        }
      
      private:
        Handler handler_;
      };
      
      template <typename Handler>
      custom_handler<Handler> custom_alloc(Handler handler)
      {
        return {handler};
      }
      

See this answer for more details on strands, and this answer for details on asio_handler_invoke.

like image 157
Tanner Sansbury Avatar answered Jan 11 '23 07:01

Tanner Sansbury