|
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