$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: [boost] [asio] Mixing streambuf-based async_read and async_read_until
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2013-09-11 04:20:15
I was tracing through some code today (using Boost.Asio 1.53) and 
noticed something that seems a little odd to me.
Given a boost::asio::streambuf that already contains data (typically 
from a previous read), the async_read_until operation will check the 
buffer first to see if it can find the specified delimiter already, and 
will only fetch more data from the stream if it needs to.  It does 
appear to perform at least one async_read_some per async_read_until 
call, but this will be a zero-length-read that will not actually hit the 
network/wherever.  (Could probably be optimised a little further though.)
The async_read operation however will not check the buffer.  While it 
won't destroy any existing data (it just appends) it will still fetch 
additional data from the stream up to the specified completion 
condition, ignoring however much is already in the buffer.
For example, if buf already contains 32 unconsumed bytes then 
async_read(s, buf, transfer_exactly(16), cb) will fetch 16 more bytes 
from the network, leaving 48 bytes in the buffer but only passing 16 to 
the read handler.  Of particular note is that it will wait for those 16 
bytes to be read from the network -- it's not satisfied with the data it 
already has.
The net effect of these behaviours I think is that if you're using 
async_read_until exclusively or async_read exclusively then everything 
will behave fairly normally.  If you are mixing these two operations on 
the same stream then you will either be losing data (if you use separate 
streambufs) or reading more data than you should (if you use the same 
streambuf and don't check outside of ASIO to see if it already contained 
enough data).
Maybe it's just me, but I find it surprising that async_read doesn't 
check if the supplied streambuf already satisfies the completion 
condition, given that async_read_until does and the docs for async_read 
do say that it's allowed to make zero async_read_some calls.
Is this a bug or is it expected behaviour?