Boost logo

Boost :

From: Christopher Kohlhoff (chris_at_[hidden])
Date: 2004-09-14 06:42:15


Hi Aaron,

In your wiki article you ask us to forget about the event handling
patterns, however I think the choice is fundamental to the design and
use of such a demultiplexing API. In your discussion you seem to imply
a reactive model (i.e. "tell me when i can take action without
blocking") when you talk about things like an on_file_readable event.

In developing asio I chose to use the proactive model (i.e. "start an
operation and tell me when it's done"), aka asynchronous I/O, because I
saw it as providing numerous advantages.

One thing I am able to do with a proactive model is provide a simple
and consistent way of encapsulating and abstracting complex
asynchronous operations. For example, the fundamental mechanism asio
provides for asynchronously receiving data on a socket is the
async_recv() member function:

  class stream_socket {
    //...
    template <typename Handler>
    void async_recv(void* buf, size_t max_len, Handler h);
    //...
  };

Here the handler is a functor called to indicate completion of the
receive operation, when some data has been received on the socket and
placed in the buffer.

As you know, a socket receive will complete as soon as any data is
available, and this will often be less than the maximum length of the
buffer. Therefore within asio I compose this fundamental building block
to provide a free function async_recv_n():

  template <typename Stream, typename Handler>
  void async_recv_n(Stream& s, void* buf, size_t len, Handler h);

which will not call the handler until exactly the specified number of
bytes is received, or until an error occurs.

A similar pattern could be followed for receiving and decoding
user-defined message structures in a single asynchronous operation:

  template <typename Stream, typename Handler>
  void async_recv_MyMsg(Stream& s, MyMsg& msg, Handler h);

i.e. don't call the handler until an entire message has been received
and decoded into the supplied msg object.

Another reason I had for choosing the proactive model was that it means
asio can use native asynchronous I/O when it is available, as this is
typically the most efficient networking API on a given platform.
However, asio can use a reactive implementation internally (currently
select) if native async I/O is not available, but still present the
same async I/O interface to users.

Regards,
Chris


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