asio::async_write and strand

前端 未结 2 1949
感情败类
感情败类 2020-12-10 00:05
asio::async_write(m_socket, asio::buffer(buf, bytes),
                custom_alloc(m_strand.wrap(custom_alloc(_OnSend))));

Does this code guarantee

相关标签:
2条回答
  • 2020-12-10 00:37

    UPD: This answer is wrong=) For anyone interested you can check details in the tail of comments, thanks to Tanner Sansbury.


    No. This guarantees your completion handler will be called with strand lock. This not includes calls to async_write_some.

    Also boost::asio does not have something like "write queue" and you need to manage async_write calls in order to prevent writing mixed content.

    0 讨论(0)
  • 2020-12-10 00:43

    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.

    0 讨论(0)
提交回复
热议问题