Boost logo

Boost :

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?

Boost list run by bdawes at, gregod at, cpdaniel at, john at