|
Boost : |
From: Aaron W. LaFramboise (aaronrabiddog51_at_[hidden])
Date: 2004-09-12 18:53:41
Boost now contains several classes that provide abstraction for
operating system resources that are logically _waitable_. A waitable
resource is any resource for which an operation on it might not complete
immediately. Examples include threads and processes, files and the file
system, and sockets and pipes. A notification of some activity on a
waitable resource is often called an _event_.
In modern software, it is often necessary to wait for events
asynchronously. Quite often threading is a good solution for this, but
quite often it isn't. In these latter cases, it is necessary to have
some sort of _demultiplexor_ entity that handles the system-specific
mechanics of waiting for events.
In both UNIX and Windows, to wait for events relating to a resource, one
must have a handle or a descriptor associated with that resource. In
general, this must be provided by the class that maintains the
abstraction itself. If a class managing a waitable resource, through
encapsulation, allows no way for a demultiplexor to access the handle
needed for waiting, waiting is impossible. Despite having all the
functionality that a programmer may require, this class is useless to
the programmer because it can not be demultiplexed. This is unacceptable.
To solve this design deficiency, a particular Boost demultiplexor class
might be created. Boost classes that are associated with waitable
resources might provide the needed handles to the demultiplexorâperhaps
using _friend_âand so make asynchronous waiting possible.
Unfortunately, there is a problem with this approach. Resources managed
by classes outside of Boost would, in general, be incompatible with the
demultiplexor. In addition, demultiplexors other than the one provided
by Boostâthat might be able to handle these classes incompatible with
the Boost demultiplexorâwould likely be unusable. The nature of typical
demultiplexor implementations is that they monopolize control flow (for
reasons that are usually unavoidable), and may only cooperate within the
same program by using separate processes or threads, which may be
inappropriate if there is no other logical reason for such separation.
The affect is that waitable resources provided by libraries other than
Boost are useless to the Boost programmer, as they are fundamentally
incompatible. This is the mark of a conniving, conspiratorial
framework, which lures its victims in with attractive features, and then
locks them in its dungeon by preventing them from using other libraries.
This is also unacceptable.
It is the unfortunate truth that until the C++ world decides on
universal resource concepts there will always need to be some piece of
code that knows the interfaces of both the waitable resource and the
demultiplexor. However, there is no need for this dependent code to be
part of either the demultiplexor or the resource. This code might be an
adapter for the Boost thread class that allows it to be compatible with
a particular third party demultiplexor class.
In consideration of the these issues, one may conclude that there must
be a mechanism in Boost classes to allow arbitrary code to access the
encapsulated handle or descriptor that describes the underlying resource
for purposes of implementing demultiplexing. While this may, at first,
seem a potential violation of encapsulation, it might also be seen as
proper application of the Open-Closed Principle. One simple mechanism
for achieving this is presented:
class unix_thread_handle {
protected:
pthread_t handle() {
return hand;
}
private:
pthread_t hand;
};
class thread : public unix_thread_handle, public boost::noncopyable {
// ...
};
Demultiplexor adaptors are permitted to access the underlying handles by
deriving from a system-specific type and copying from an existing
resource. Such access is subject to the lifetime of the origin object
and documented constraints about the meaning of the handle.
A demultiplexor should also be designed to be compatible. The
demultiplexor must provide some mechanism to allow code outside of Boost
to obtain control flow when particular system events occur. In
addition, interoperability should be maintained not only with foreign
waitable resource classes, but with other demultiplexors, to the maximum
extent possible. For example, on a system where an event is delivered
through a chain of handlers (such as Windows hooks or UNIX sigaction),
the demultiplexor must be careful to pass on the event when appropriate.
In light of recent interest and development relating waiting and
demultiplexing, it is especially important that the above points are
considered. Writing a naïve demultiplexor that will forever plague
future programmers who use third party libraries is a temptation that
should be strenuously ignored. There are already plenty of frameworks
that have implemented this unfortunate xenophobia. If Boost is able to
offer an interface that makes its waitable resources and future
demultiplexor openly compatible with the rest of the world, it will
continue to be popular long after other libraries have outlived their
usefulness.
Any thoughtful consideration and comments would be greatly appreciated.
If there is some interest in these things for Boost, Iâd like to
prepare some proof-of-concept alterations for waitable parts of Boost.
I also have designed a cross-platform demultiplexor class, but
unfortunately it is not in a state that is immediately ready to be
shared with Boost. However, if there was interest, I would consider
polishing it up.
Aaron W. LaFramboise
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk