|
Boost : |
From: Dale Peakall (dale.peakall_at_[hidden])
Date: 2002-08-12 05:42:57
Having read all the posts on this subject in a more or less neutral fashion
(my opinion has changed several times over the course of the discussion) I'm
going to attempt to sum up some of the issues and suggest a course where
action can take the place of argument.
When it comes down to it the matter of debate is: What should happen when an
uncaught exception is thrown in a thread?
The answer is suitably ambiguous (otherwise there wouldn't be a debate) and
is: Depends what the thread was created to do, who created the thread, and
how the caller interacts with it.
Just about the only agreement here (well no-one's argued against it), is that
fully asychronous exceptions will not solve the problems at hand and will
cause many more problems.
OK, so here are the scenarios and desired behaviour:
If the thread is an asynchronous function call, then the correct behaviour is
to propogate the exception when the caller calls join. If the caller doesn't
call join then it's probably not a problem.
If the thread is a worker from a pool, then the correct behaviour is to catch
the exception and restart the thread.
If the thread is part of a monitor (or similar), then the correct behaviour
is to terminate - no graceful recovery is possible.
Proposed Solutions:
1) thread<void> threads call terminate(), thread<XXX> threads propogate the
exception when join is called.
2) as above, but with a policy object to allow the default to be over-ridden
3) threads call terminate(), if you want other behaviour you provide a wrapper
4) threads call thread_terminate() which can do the right thing
1 is just a sub-set of 2 and I haven't seen any objections to the concept
that adding a policy (if it defaults) is inherently a problem.
4 is flawed because the thread in which main is executed IS DIFFERENT
(whether we like it or not). It's created by the OS, has constraints placed
on it by the C++ standard (which is relevent as compilers generally rely on
it). Providing a default main which calls an appropriate wrapper causes
contentions with other frameworks that do the same and creates problems for
library writers.
This leaves us with 2 & 3 as viable solutions.
Since both are viable, both solve the problems, and both have proponents and
opponents, we're left in a sticky situation. Concensus is not going to be
achieved by arguing the technical merits of the case. In the end, it's going
to come down to opinion. Here's mine:
Have the default beviour be for threads to terminate on uncaught exceptions.
I base this simply on my opinion that a thread() is different from an
async-call and that the thread library has tried to remain a low-level
library that provides us the tools for writing higher-level abstractions
(which is why it doesn't provide monitor classes etc).
This leaves us with an opportunity for someone to introduce an async-call
framework. Perhaps a simple-library for now (that solves the problems that
people want from the thread library), but perhaps being sufficiently
extensible that you can plug in support for remoting etc.
- Dale.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk