|
Boost : |
From: Branko Èibej (branko.cibej_at_[hidden])
Date: 2000-06-06 08:58:28
Beman Dawes wrote:
> >My gut reaction is to stay away from signals in threaded code.
> >The behaviour of signals differs widely, even between different
> >Unix platforms; on Win32, signals are just at thin layer on top
> >of SEH (structured exception handling), which works within a
> >single thread only.
>
> Sorry, poor choice of words on my part. I meant signal as in
> pthreads "signal a condition variable", not a <signal.h> signal.
Ah ...
> Note that "Programming with POSIX Threads" also says that by
> carefully using the term signal and qualifying it when necessary, "we
> are unlikely to cause anyone severe discomfort."
>
> Since I already failed the "careful" test, I suggest that boost not
> call it a multithreading "signal" but rather "event" or some other
> name.
... Yes, "event" would be a good choice. We really don't need
misunderstandings of this kind :-)
> >Anyway, I see several ways to go:
> >
> > 1. If an exception is thrown in a thread, and there's no handler
> > registered within the thread, call unexpected().
> >
> > 2. Put a catch-all handler in the thread start-up function. When
> > an exception is caught there, terminate the thread normally,
> but
> > throw an exception when another thread calls join().
> >
> > 3. Like 2, but just put the thread object in an "exception caught"
> > state, then let the programmer do whatever she wants with that
> > (including throwing an exception).
> >
> >Personally I'd go for 1., because it's closest to current standard
> >behaviour. Besides, it's the most flexible -- both 2. and 3. can
> >be implemented on top of it.
>
> Let me make sure I understand (1). Are you saying that the apparent
> thread startup function is actually called from a private library
> startup function which wraps the call to the apparent startup
> function in a try...catch? Hum. That does seem like a good idea!
Yes -- that would be necessary for all three scenarios.
Even without exception support, it makes sense to wrap the call to the
startup function like that. I was thinking about something like this
(e.g., for 2 -- not tested):
class thread
{
public:
thread()
: exception_thrown(false),
self(invalid_thread)
{}
virtual ~thread() {}
void run() {
self = create_thread(start_thread, this);
}
void join() throw(runtime_error) {
wait_for_thread(self);
self = invalid_thread;
if (exception_thrown)
throw runtime_error("unhandled exception in thread");
}
virtual void main() = 0;
private:
bool exception_thrown;
thread_handle_t self;
static void start_thread(void* arg) {
thread* thr = dynamic_cast<thread*>(arg);
// This cast should always succeed, right?
exception_thrown = false;
try {
thr->main();
}
catch(...) {
thr->exception_thrown = true;
}
}
};
(With appropriate locks to protect the class' internal data.)
Brane
-- Branko Èibej <branko.cibej_at_[hidden]> HERMES SoftLab, Litijska 51, 1000 Ljubljana, Slovenia voice: (+386 1) 586 53 49 fax: (+386 1) 586 52 70
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk