How to stop boost::asio async reads from getting mixed up?
<p>I am using <code>boost::asio::ip::tcp::socket</code> to receive data. I need an interface which allows me to specify a buffer and call a completion handler once this buffer is filled asynchronously.</p>

<p>When reading from sockets, we can use the <a href="http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/basic_stream_socket/async_read_some.html" rel="nofollow"><code>async_read_some</code></a> method.
However, the <code>async_read_some</code>  method may read less than the requested number of bytes, so it must call itself with the rest of the buffer if this happens. Here is my current approach:</p>

<pre><code>template&lt;typename CompletionHandler&gt;
void read(boost::asio::ip::tcp::socket* sock, char* target, size_t size, CompletionHandler completionHandler){

   struct ReadHandler {
      boost::asio::ip::tcp::socket* sock;
      char* target;
      size_t size;
      CompletionHandler completionHandler;

      ReadHandler(ip::tcp::socket* sock, char* target, size_t size, CompletionHandler completionHandler)
      : sock(sock),target(target),size(size),completionHandler(completionHandler){}
      // either request the remaining bytes or call the completion handler
      void operator()(const boost::system::error_code&amp; error, std::size_t bytes_transferred){
         if(error){
            return;
         }

        if(bytes_transferred  &lt; size){
           // Read incomplete
           char* newTarg =target+bytes_transferred;
           size_t newSize = size-bytes_transferred;
           sock-&gt;async_read_some(boost::asio::buffer(newTarg, newSize), ReadHandler(sock,newTarg,newSize,completionHandler));
           return;
        } else {
           // Read complete, call handler
           completionHandler();
        }
      }
   };

   // start first read
   sock-&gt;async_read_some(boost::asio::buffer(target, size), ReadHandler(this,target,size,completionHandler));
}
</code></pre>

<p>So basically, we call <code>async_read_some</code> until the whole buffer is filled, then we call the completion handler. So far so good. However, I think that things get mixed up once I call this method more than once before the first call finishes a receive:</p>

<pre><code>void thisMayFail(boost::asio::ip::tcp::socket* sock){
   char* buffer1 = new char[128];
   char* buffer2 = new char[128];
   read(sock, buffer1, 128,[](){std::cout &lt;&lt; "Buffer 1 filled";});
   read(sock, buffer2, 128,[](){std::cout &lt;&lt; "Buffer 2 filled";});
}
</code></pre>

<p>of course, the first 128 received bytes should go into the first buffer and the second 128 should go into the second. But in my understanding, it may be the case that this does not happen here:</p>

<p>Suppose the first <code>async_read_some</code> returns only 70 bytes, then it would issue a second <code>async_read_some</code> with the remaining 58 bytes. However, this read will be queued behind the second 128 byte read(!), so the first buffer will receive the first 70 bytes, the next 128 will go into the second buffer and the final 50 go into the first. <strong>I.e., in this case the second buffer would even be filled before the first is filled completely.</strong> This may not happen.</p>

<p>How to solve this? I know there is the <a href="http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/async_read/overload1.html" rel="nofollow"><code>async_read</code></a> method, but its documentation says it is simply implemented by calling <code>async_read_some</code> multiple times, so it is basically the same as my <code>read</code> implementation and will not fix the problem.</p>