Boost logo

Boost :

From: Boris Schäling (boris_at_[hidden])
Date: 2002-11-27 10:03:10


> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]]On Behalf Of Hamish Mackenzie
> Sent: Wednesday, November 27, 2002 12:53 PM
> To: Boost mailing list
> Subject: RE: [boost] Re: AW: Re: AW: Sockets
>
>
> On Tue, 2002-11-26 at 17:12, Boris Schäling wrote:
> > > How does the multiplexor know what to pass to write the second time?
> >
> > The multiplexor doesn't know but the stream does. The multiplexor calls
> > stream::write() when the socket descriptor is writable. The stream calls
> > ::write() and sends all data which was saved in the stream's
> buffer because
> > of EWOULDBLOCK to the network.
> >
> > +-------------+ +--------------+ 1) +--------------+
> > | multiplexor | 2) | stream |<-------| observer |
> > | |<-------| | | |
> > | | 3) | | | |
> > | |------->| | | |
> > +-------------+ +--------------+ +--------------+
> >
> > 1) observer calls stream::writen() to send data.
> > 2) stream calls multiplexor::set_write() because of EWOULDBLOCK.
> > 3) multiplexor calls stream::write() when the socket descriptor
> is writable.
>
> I don't think you have considered the reentrancy issues with this. If
> on_connect calls writen and writen simulates blocking (and waits for
> more than just writeable on the socket in question) then a second
> on_connect (or on_read) comes in then the first on_connect cannot
> complete until the second on has.

I can't follow. An on_xxx method is always completed before another on_xxx
method is called. If on_connect() calls writen() and write() in writen()
returns EWOULDBLOCK that doesn't mean writen() blocks. on_connect() is
completed, and when the socket descriptor becomes writable the multiplexor
calls stream::write() as the stream may now ::write() what has been saved
because of EWOULDBLOCK in a buffer before.

> > > Does the caller have to load the 5GB file into memory before
> passing it
> > > to the write?
> >
> > The caller may certainly write the file in chunks. Or did I
> misunderstand
> > your question?
>
> Now things start getting really messy. If on_connect calls writen more
> than once the second call may be delayed if the an event on a different
> socket (or a read event on the same socket comes in) is processed during
> the first call to writen. You may have plenty of bandwidth but slow
> client will cause a fast one to block.

My implementation selects on all file descriptors and calls all on_xxx
methods that must be called before it selects again on all file descriptors.
An on_xxx method must complete before another one is called. As every stream
uses its own buffers, one for reading, one for writing, I still don't see
any reentrancy problem?

> writen has two possible implementations
> 1) Wait for just on writeable on the socket in question. In which case
> it is indistinguishable from a blocking call.
> 2) Wait for and process other events to and get yourself into a
> reentrancy tangle.
>
> In my opinion the only correct implementation is 1. In which case
> writen is a blocking call.

You may call writen() several times. If the stream is currently waiting for
the socket descriptor to become writable the data is saved in the stream's
buffer. But that doesn't mean writen() blocks.

Boris


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk