Boost logo

Boost :

From: Darryl Green (darryl.green_at_[hidden])
Date: 2004-09-15 06:26:25


Christopher Kohlhoff <chris <at> kohlhoff.com> writes:
> --- "Aaron W. LaFramboise" <aaronrabiddog51 <at> aaronwl.com> wrote:
> > If a demultiplexor
> > library espoused one particular paradigm, it would be come useless to
> > other incompatible paradigms.
>
> Perhaps, but my experience in using asio (as opposed to writing it) has
> been that:
>
> - A proactive interface is all that I have needed for sockets.
> - Other reactive or even blocking interfaces can generally be
> efficiently wrapped by proactive ones.

Thats fine as far as it goes. But I also think Aarons points re many factors
affecting the choice of paradigm are equally valid.

> But should that not be sufficient, I should point out that the demuxer
> in asio is extensible using a similar idea to std::locale's facets. So
> it is possible to override the implementation of a socket, or to even
> include a entirely new reactive-based resource.

It isn't clear to me how this is better than Aarons separation of the
(de)multiplexor and the socket (or whatever) object, with the binding to a
demultiplexor being relatively late. A proactive socket could easily enough be
written to work with a proactive demultiplexor.

The end effect, if I understand Aaron's proposal correctly, is a very flexible
and easily extended design, that doesn't in any way preclude anything that your
library implements (in fact I would think most of the implementation could be
retained?).

>
> > In particular, it is up to objects themselves to implement the
> > 'hooks'
> > that their users may use, which might be proactive, reactive, or
> > something else.
>
> It is my feeling that attempting to define a demultiplexing interface
> in such a way is drawing the line of abstraction too low. However
> perhaps we are talking about different things :)

I think the demultiplexor (please can we use a better name for this when it is
really so generic - maybe just "notifier") must have no idea what it is
notifying the handler of if it is to be possible to make this truly generic.

The fact that a notifier for proactor/aio may be almost invisible (built into
the system) doesn't make all of this irrelevant. The binding of the handler to
the notifier is still relevant - if only for cancellation.

To implement proactor, there needs to be some way to convey to a handler what it
was that just completed. But I don't see that as being any different to the
other higher-level notifications Aaron suggest can be implemented by layering.

That is, at the lowest layer, the notifier itself simply knows that some wrapped
system object has notified. The handler for the system object (eg a signal
handler) is then responsible for mapping this to the higher level interface.
Because something like an async read request only makes sense for certain
objects, it is a member function in Aarons model (if I'm understanding
correctly). Something like (very sketchy, generics left out):

class aio_rd_req; // encapsulates messy aio request context stuff

socket::async_read(char *buf, size_t len, handler h)
{
  aio_read(aio_rd_req::make(this,buf,len,h).iocbp());
}

aio_rd_req::handle_completion()
{
  m_handler(m_iocb.aio_buf, aio_return(&m_iocp));
  delete this;
}

Is that so bad or so vastly different to how asio does it?

Side note on names: Here asio stands for Australian Security Intelligence
Organisation - sort of like the CIA :-)

>
> My focus in asio has been on defining a C++ interface for using sockets
> or other OS objects asynchronously, but while leaving maximum freedom
> for the implementor (i.e. me until now) to use the best mechanism for a
> particular platform by default, whether that be native async I/O or a
> reactor-based solution.

Do you assume one or the other must be the best on a platform, or do you allow a
"mix and match" approach? Platform quirks that result in aio working for some
types of objects, and select/poll for others, plus the issue of whether
proactive or reactive style makes sense in a given app may mean that the goals
of efficieincy and portability fight each other. An approach where the code will
fail to compile because there is no specialisation for a particular event source
(eg socket) using notifier type X (eg aio) is not a bad thing. The ability to
chose between notifiers that are portable but possibly inefficient on some
platforms and those that will simply refuse to work if they are not efficeintly
implementable is a nice feature. Extending the model to support a wider variety
of event sources is bound to introduce further portability issues in terms of
which event sources even exist on some platforms, as well as which notifiers
work with them. Clearly some uber-notifier allowing a wide mix of event types
(this is likely to be quite inefficient even without considering portability)
should be provided for in the design, but it shouldn't be the only choice.

Regards
Darryl.


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