Boost logo

Boost Users :

Subject: Re: [Boost-users] [iostreams] Devices and WOULD_BLOCK
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2015-01-26 16:58:32


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. :)


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net