Hi Gavin,
I wasn't talking about mixing async with non-async (although you can do that as long as you're careful to not have concurrent operations, it's rarely-to-never useful to do so in practice). I was talking about mixing the two types of read calls ("read", which reads up to a specified number of bytes, and "read_until", which reads up to a specified termination value/sequence).
Thanks for correcting me :)
Do you see anything wrong with using a shared_ptr<streambuf> member variable? I wanted to use a streambuf so that I could pass it directly to the async_read_until and async_write functions (saving the buffer() conversions used in the original code).
There are negative performance consequences to copying a shared_ptr (ie. incrementing or decrementing its refcount). *Most* applications don't need to care about this (it's very small) but sometimes it's worthy of note, and there's no harm in avoiding copies in silly places (which is why I thwack people that pass a shared_ptr as a value parameter).
In the case of the original chat example, the chat message class contained a char array. I added a std::cout message in the constructor copy constructor and destructor, and could see that the message was copied numerous times inside the bind command sequence, so figured a shared_ptr<> was a lighter-weight way to do. I then made sure to pass a reference to a shared_ptr<> where ever I could to avoid a head "thwack" :)
Personally, though, I use a streambuf only in the connection-management class, which isn't copyable, so I've never had that problem. Messages themselves are copied out of the streambuf into a std::string or some dedicated message data type, and then copies of these can be made reasonably freely.
Of course, copying data is also a negative performance consequence, so it's a matter of picking the right tradeoff for your particular application and workload. :)
It turns out that my use of a streambuf was not suitable for use within the message class, since the message can be sent to multiple connected clients - sending to the first client "consumes" the streambuf within the shared message, so the next client sees an empty streambuf - oops! The solution was as you point out, to pass around a message object (containing a char array or std::string), and copy the message into or out of a streambuf as needed. My modified chat client/server now works with the modified protocol. I've modified the client code to work with a serial port, so that I can connect two clients using two USB-to-Serial ports and a cross-over cable. For some strange reason the async_read_until calls work fine under Cygwin but not Linux, so I'm in the process of tracking that down :) Thanks again. Cheers, Dave