Boost logo

Boost :

From: Christopher Kohlhoff (chris_at_[hidden])
Date: 2005-12-19 19:33:54


Hi Arkadiy,

--- Arkadiy Vertleyb <vertleyb_at_[hidden]> wrote:
> Could you provide some (high-level) justification of why it is
> beneficial to have a socket dependency upon a demuxer?
>
> Maybe I am missing something, but IMO such a dependency is
> unnatural even for asynchronous IO.

This has not come up in the discussion thus far, but the
dependency on the demuxer is required to enable an efficient and
portable implementation of asynchronous I/O. This is one of the
primary goals of asio. The asio interface has been designed to
reflect efficient asynchronous I/O mechanisms across major
operating systems.

Let's take the specific case of Windows, where asynchronous I/O
is implemented using I/O completion ports. Once a socket is
associated with an I/O completion port it cannot be
disassociated.

In asio, the demuxer represents the I/O completion port.
The asio interface enforces this association by constructing the
socket with its associated demuxer/IO-completion-port.

>From the point of view of the library user, any asynchronous
operations started on the socket will have the completion
handler delivered through the associated demuxer (as it is with
I/O completion ports).

Separating the asynchronous I/O operations from the socket class
would no longer enforce this requirement at compile time.
(That's even leaving aside questions about where the operation
logically belongs.)

> Hiding it behind default parameter, singleton,
> etc., just masks what I believe is a design problem.
>
> If you absolutely believe this dependency is necessary for
> async IO, having two separate classes, such as sync_socket and
> async_socket would be much cleaner. But again, I can't see
> what justifies such a dependency even for async IO.

So the question is really whether there should be separate sync
and async socket classes, versus a combined class as there is
now. I believe that, on balance, separate classes would be
harmful. Let's reiterate some of the points:

- Synchronous and asynchronous operations are essentially the
  same, in that they perform the same operation and aim to
  fulfil the same contract. How they differ is simply that one
  blocks the current thread, whereas the other executes in a
  background logical thread and tells you when it is complete. I
  want there to be a clear mapping from one to the other.

- Separate classes reinforces the notion that synchronous
  operations are somehow more useful for the ordinary
  programmer, and that asynchronous is hard and best left in the
  realm of the networking guru. I do not believe that
  asynchronicity is difficult to use or understand, it is simply
  that programmers often approach sockets with preconceived
  ideas of how an API should behave. But I do believe that
  separating the classes will continue the lack of awareness of
  asynchronicity as an option, leading to the needless use of
  inferior designs.

- The greater number of classes and options will increase the
  size of the library's interface.

- I have demonstrated that there is a use case for mixed-mode
  applications. Predominantly synchronous designs can benefit
  from localised asynchronicity. Asynchronous designs can be
  simplified by selective use of synchronous calls.

- A line of reasoning has been presented which says that,
  because files already have a synchronous-only interface and
  could be given an asynchronous interface, sockets should also
  have a synchronous-only interface. However, sockets are
  inherently different to files due to the long timescales
  involved in many operations. Developers will look for some
  form of concurrency to address this, and I believe
  asynchronicity *should* be promoted over threads as a
  solution.

It is worth noting that even .NET combines the sync and async
socket operations on a single interface.

I do find that there is a compelling case for a synchronous-only
interface to sockets at the iostreams level. But that is because
of the established use and wide applicability of iostreams, not
because it is synchronous.

So let me turn the question around. Why must there be a
low-level synchronous-only interface at all? What benefits
will it bring? What use cases do you have that cannot be met by
a combined interface or an iostream interface?

Cheers,
Chris


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