On 22/01/2015 20:52, David Hawkins wrote:
Yep. Just be careful if you're mixing calls to read_until with calls to read -- read_until may fetch a larger amount of data into the streambuf (beyond the delimiter), while read will always wait for new data, even if the streambuf isn't empty. So you need to explicitly check the streambuf before calling read().
Of course if you're only dealing with purely delimited data then this shouldn't be an issue, as you'll only be using [async_]read_until.
That is an interesting warning. I hadn't really thought about whether I could mix the blocking and non-blocking read commands (but would have assumed I should not!). The modified chat application uses using only the async versions, i.e., async_read_until, and async_write.
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).
Ok, so here's a streambuf question for you. In my attempt to modify the chat server as much as possible, I initially modified the buffering to use a streambuf member variable ... but that fails, since a streambuf is non-copyable. My solution was to use a shared_ptr<streambuf>> - see the chat_message.hpp code below.
Given that the shared_ptr is reference counted, when the server 'delivers' a read message to multiple clients, the shared pointer reference count on a new message read from a client will increment as its copied to each of the clients connected to a session, and then decrement as each server client handler write pops the message off its write queue.
At least I assume that is what is going on (I just finished modifying the server and its working ok), I'll use the debugger and trace the server code tomorrow to check.
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). 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. :)