|
Boost : |
From: bill_kempf (williamkempf_at_[hidden])
Date: 2002-01-15 12:57:25
--- In boost_at_y..., Wil Evers <Wil_Evers_at_d...> wrote:
> Hi,
>
> A few weeks ago, a posting by Beman Dawes to comp.lang.c++.moderated
> caught my attention. The posting said that Boost.threads had been
> submitted to the Committee for their upcoming C++ Standard Library
> Technical Report, and that the initial response from the Committee
had
> been favorable.
>
> Since I'm always looking for ways to do portable multi-threading in
C++,
> I checked the library's documentation to see how some of the more
> difficult C++/MT issues had been addressed, only to find out that
> Boost.threads doesn't address them at all. I expressed my
> disappointment in a few postings to comp.std.c++ and
> comp.lang.c++.moderated, which triggered an email by David Abrahams,
> who wrote:
Saying that Boost.Threads doesn't address them isn't quite accurate.
Most of these have been addressed in some form, even if the library
doesn't have an implementation that addresses it. Some problems
simply can't be addressed by a library implementation (at least in a
portable manner), and we're trying to document these things for
discussion and possible inclusion in the standard. Other problems
are addressable in library code (such as cancellation), at least to
some extent. However, they are complex enough that they aren't in
the current library (the current library addresses what's required by
library authors for writing thread-safe code, mostly). They have
been discusssed, however, and are planned for future versions of the
library.
That said, your input on things you find lacking are very valuable.
Even in the cases where we can't provide a solution today.
> > Have you told us (boost) what you need that threads doesn't
provide?
> > A post to the boost list would be appreciated.
>
> Before I go on, please keep in mind that I haven't been following
the
> discussions on the Boost mailing list; what I'm about to say must
have
> been discussed before here. On other hand, I guess my reaction is
> fairly typical for a programmer who's simply looking for a way to
write
> reasonably substantial, portable multi-threaded C++ programs. In my
> opinion, a standard C++ multi-threading library should allow me to
do
> that without having to deal too much with platform-specific APIs and
> other implementation details.
Absolutely. Boost.Threads hopes to allow at least a large portion of
such applications to be written portably today (and I hope even in
this first revision it does that), but in the end it's going to
require some changes in the standard for true portability to exist.
What we can't do portably today needs to be documented and well
thought out in order to propose solutions to the C++ Standards
Committee. At best Boost.Threads is a small speck of light at the
end of the tunnel. Lots of effort still needs to be made and
acceptance of this (or some other library) by the standard is going
to be required for what you and I both want.
> So here are the main points on my wish list, along with some
> suggestions for a possible approach:
>
> (*) Cancellation support
>
> This must be the most frequently requested feature. Without
support for
> cancellation, it is very awkward to implement a proper program
> shutdown. In the past, I've had to implement an entire layer on
top of
> POSIX's condition variables (and their home-made Win32 substitute)
just
> to get to the point where a cancellation request is translated into
a
> C++ exception, and believe me, this is something you only want to do
> once.
I totally agree. Have you followed the recent thread on this? Your
input may be of help in the design. How you coded a solution might
also be helpful.
> There are some tough design decisions to take: should cancellation
be
> asynchronous (no, the exception should be thrown from a set of known
> cancellation points), should an attempt to lock a mutex be a
> cancellation point (no, but waiting on a condition variable, or for
I/O,
> should), what happens if a thread completely handles a cancellation
> request without dying (unappreciated behavior, i.e. another thread
> attempting to join it will remain blocked).
These have all been discussed, and I'm mostly leaning towards the
conclusions you have above. Asynchronous cancellation is a sticky
one, and I may recommend for inclusion in the standard (and the
committee will then have to weigh the pros and cons I present and
decide). There are some compelling arguments for its inclusion,
despite the dangers and hassles it presents. However, Boost.Threads
won't include asynchronous exceptions simply because I have no idea
how you could possibly implement it portably.
> Come to think of it: a cancellation request is just one of the
things
> that can interrupt an unsuspecting thread. Certain types of
signals,
> such as SIGINT, SIGTERM and SIGHUP, could also be mapped to a C++
> exception thrown from a cancellation point.
I've not even begun to consider signals. They are a foreign beast to
me. We'll have to consider them, at least to some extent, before
formal proposal to the committee, however.
> (*) Inter-thread problem notification
>
> What should happen when one of two threads with a producer/consumer
> relation dies unexpectedly because of an exception (say, a
bad_alloc)?
> The peer must be notified, or it will wait forever.
> There are, of course, more complex scenarios where certain threads
> dynamically enter and leave a state that only makes sense when other
> threads are still alive and behaving as expected.
>
> So far, the approach I'm using is to totally hide the use of
condition
> variables and replace them with reference-counted I/O channels that
> behave much like UNIX pipes: a thread attempting to read from a
channel
> without any living writers will get some end-of-file notification,
and a
> thread attempting write to a channel without any living readers
gets the
> C++-exception equivalent of a SIGPIPE.
This is a higher level threading concept then is being addressed by
Boost.Threads. This is actually quite in tune with CSP and in many
ways is a safer MT mechanism. However, such higher level concepts
are built on the lower level primitives. I want us to be able to
walk before we fly. Portable primitives will allow for the
development of higher level concepts.
> (*) Event multiplexing
>
> This issue relates both to inter-thread communication (semaphores,
> condition variables, etc,.) as well as inter-process communication
> (shared memory, local pipes and networking).
>
> Some programs spawn a separate thread (or even a process) for each
peer
> entity they communicate with, while other programs use only a single
> thread that iteratively handles all peer communication. The optimal
> distribution of a number of peer conversations (which could be other
> threads in the same process, other processes on the same host, or
other
> hosts on the network) over a certain number of threads, processes
and
> hosts is highly application-, hardware- and OS-dependent,
> hard to design up front, and can often only be determined through
> careful experimentation. In addition, it is sometimes appropriate
to
> 'move' a certain service from some distinct host or process into a
> thread which is part of the same process as its peers, or vice
versa.
This is truly a seperate concept from Boost.Threads. We need
mechanisms like this, and maybe such mechanisms should even be
considered for the standard, but they are simply outside the scope
that we're dealing with in Boost.Threads.
> For maximum flexibility, we need (1) a portable library facility
that
> allows us to wait for the first of a number of events to happen and
(2)
> an interface that unifies the exchange of messages between peers,
> wherever they live. This requires at least some support from a
standard
> multi-threading library, because it must be able to represent a
blocking
> point (a condition variable or semaphore) as something that can be
> waited on while also monitoring network events and timer alarms.
This isn't necessarily true. There are ways to wait for all of
these "events" with out tight coupling to the synchronization
primitives of the thread library.
> As I said in comp.std.c++, Hoare's Communicating Sequential
Processes
> (CSP) contains a good example of a high-level syntax to express such
> selection constructs. So far, my low-level approach is to use event
> handles on Win32; for Unix, I use a pipe (which has a file
descriptor,
> and can thus be selected on) to express the state of something that
> resembles a condition variable.
I think an exciting prospect for Boost would be a higher level
library giving CSP mechanisms built on top of the Boost.Threads
primitives. In fact, the documentation for Boost.Threads suggests
this.
Thanks for your comments.
Bill Kempf
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk