
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?