title: how to use boost::asio::defer() in composing function?
body: <p>On Boost 1.66, Asio have <a href="https://www.boost.org/doc/libs/1_67_0/doc/html/boost_asio/net_ts.html" rel="nofollow noreferrer">deprecated</a> the <code>asio_handler_is_continuation</code> hook function, promoting usage of <code>defer</code> function. <a href="http://boost.2283326.n4.nabble.com/Boost-Asio-defer-dispatch-and-post-differences-td4700883.html" rel="nofollow noreferrer">It seems that</a> <code>defer</code> function is behaving exactly the same as <code>post</code> when asio_handler_is_continuation==true. However, the way of using <code>defer</code> is different from the way of using <code>asio_handler_is_continuation</code>, and I am not sure how to properly use <code>defer</code>.</p>
  
  <p><strong>EDIT</strong>: I think the sample below is too verbose to clearly express what i mean. Here's shorter example:</p>
  
  <pre><code>async_read_until(stream, read_buffer, "\r\n", 
      [](boost::system::error_code ec, std::size_t bytes_transferred)
      {
          if(!ec)
              async_write(stream, write_buffer, some_handler);
      })
  </code></pre>
  
  <p>Now when <code>async_read_until</code> is completed, the lambda handler passed will be invoked using some means equivalent to <code>boost::asio::post</code>. But <code>async_write</code> inside the lambda handler is continuation from last async task, So I want to invoke the lambda handler using <code>defer</code> to take adventage of optimization. </p>
  
  <p>Is there any way to use <code>defer</code> (instead of <code>post</code>) to invoke the lambda handler in above example?</p>
  
  <p><strong>ORIGINAL POST</strong>: I am trying to write a simple initating function <code>async_echo</code> similar to the one in <a href="https://www.boost.org/doc/libs/1_67_0/libs/beast/doc/html/beast/using_io/writing_composed_operations.html" rel="nofollow noreferrer">beast document</a>, except that the part that calls <code>boost::asio::async_write</code> will be called as a continuation. To achieve this, prior intermediate operation <code>boost::asio::async_read_until</code> must call the handler <code>*this</code> as a continuation.</p>
  
  <p>This is the part that I am referring in the async_echo example of the beast document:</p>
  
  <pre><code>template&lt;class AsyncStream, class Handler&gt;
  void echo_op&lt;AsyncStream, Handler&gt;::
  operator()(boost::beast::error_code ec, std::size_t bytes_transferred)
  {
      // Store a reference to our state. The address of the state won't
      // change, and this solves the problem where dereferencing the
      // data member is undefined after a move.
      auto&amp; p = *p_;
  
      // Now perform the next step in the state machine
      switch(ec ? 2 : p.step)
      {
          // initial entry
          case 0:
              // read up to the first newline
              p.step = 1;
              return boost::asio::async_read_until(p.stream, p.buffer, "\r", std::move(*this));
  
          case 1:
              // write everything back
              p.step = 2;
              // async_read_until could have read past the newline,
              // use buffers_prefix to make sure we only send one line
              return boost::asio::async_write(p.stream,
                  boost::beast::buffers_prefix(bytes_transferred, p.buffer.data()), std::move(*this));
  
          case 2:
              p.buffer.consume(bytes_transferred);
              break;
      }
  
      // Invoke the final handler. The implementation of `handler_ptr`
      // will deallocate the storage for the state before the handler
      // is invoked. This is necessary to provide the
      // destroy-before-invocation guarantee on handler memory
      // customizations.
      //
      // If we wanted to pass any arguments to the handler which come
      // from the `state`, they would have to be moved to the stack
      // first or else undefined behavior results.
      //
      p_.invoke(ec);
      return;
  }
  </code></pre>
  
  <p>On pre-1.66 days, I could simply hook the function as follows:</p>
  
  <pre><code>template &lt;Function, Handler&gt;
  friend bool asio_handler_is_continuation(echo_op&lt;Function, Handler&gt;* handler)
  {
      using boost::asio::asio_handler_is_continuation;
      return handler.p_-&gt;step == 1 || 
          asio_handler_is_continuation(std::addressof(handler.p_-&gt;handler()));
  }
  </code></pre>
  
  <p>inside the declaration of <code>echo_op</code>.</p>
  
  <p>Starting from Boost 1.66, the code above is not likely to have any effect (without <code>BOOST_ASIO_NO_DEPRECATION</code> macro). So I should be using <code>defer</code>. </p>
  
  <p>But since <code>boost::asio::async_read_until</code> has <a href="https://www.boost.org/doc/libs/1_67_0/doc/html/boost_asio/reference/async_read_until/overload1.html" rel="nofollow noreferrer">a guarantee</a> that "Invocation of the handler will be performed in a manner equivalent to using boost::asio::io_context::post().", <code>*this</code> will not be invoked using <code>defer</code>, that is, as a continuation.</p>
  
  <p>Is there any workaround that makes <code>boost::asio::async_read_until</code> invoke the handler using <code>defer</code>? And is there any good examples that utilize <code>defer</code> function?</p>