Boost logo

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