Boost logo

Boost Users :

Subject: Re: [Boost-users] [iostreams] Devices and WOULD_BLOCK
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2015-01-21 23:54:36

On 22/01/2015 12:56, David Hawkins wrote:
> In theory the filtering_stream 'filter' and 'device' layers should
> pass characters, EOF, and WOULD_BLOCK. Unfortunately the code snippet
> I posted suppresses the propagation of the WOULD_BLOCK return value
> from the 'device' layer to the 'filter' layer.

Generally I would recommend using only blocking or async code.
Non-blocking is a holdover from when async didn't really exist yet, and
with ASIO you shouldn't have that excuse.

> The Boost chat client/server has similar features to my problem,
> i.e., it involves encoding/decoding messages. The encoding/decoding
> is different than my case, since the chat protocol adds a
> header with the message length. This simplifies the socket read
> code, since you can read the fixed-length header, then read the
> now known) message length, i.e., each call to read has a fixed
> length parameter. In my case, the message length is unknown, and
> depends on the content of the message (since data can be escaped).
> The data stream is generated by a field-programmable gate array
> (FPGA), and adding a buffer to determine the message length before
> sending the response would use too many resources, so the encoding
> protocol cannot easily be changed.

My point is that theoretically this shouldn't be a problem, as long as
the lowest level (actual device reading) behaves as described earlier.

When you read(buffer, 512) it would block until the device provides some
data; perhaps it sends a 28 byte packet, of which the driver eagerly
grabs the first 8 bytes and so read() returns 8; you look at that data,
decide it's not a complete message yet, so you stash it into a separate
buffer and call read(buffer, 512) again. (There are other approaches if
you want zero-copy.) This time the driver already had the remaining 20
bytes queued up and so read() immediately returns 20. You tack those
bytes onto the end of your prior stash, parse the whole thing, and now
you've got a message you can return to a higher layer, and then go back
to reading. Async works similarly, you just break the code up a little
more so that it can return while it's waiting.

(Just remember that it might also return a few bytes from the start of
the *next* message, so you need to strip exactly one message out of the
stash and keep accumulating bytes for the next message.)

Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at