Boost logo

Boost :

Subject: [boost] [thread] Exception propagation for thread::join
From: Emil Dotchevski (emil_at_[hidden])
Date: 2009-05-17 17:52:43


When joining a thread, in case the thread has exited, I find it
convenient to have any exception the thread function throws propagated
to the caller of join(). Just as an illustration of what I'm talking
about, below is my Win32 implementation of a similar interface. An
interesting design decision is what to do if a detached thread throws
an exception. Note the line marked with (1) -- I've decided to assert
in this case (instead of ignoring the exception, which would be the
alternative behavior.)

Would something similar be a good addition to Boost Thread?

struct
windows_thread_info
        {
        DWORD id;
        boost::shared_ptr<HANDLE const> h;
        boost::function<void()> f;
        mutable boost::exception_ptr e;
        boost::shared_ptr<windows_thread_info> self;
        ~windows_thread_info()
                {
                assert(!e);
                }
        };

namespace
        {
        DWORD WINAPI
        thread_proc_fwd( void * p )
                {
                assert(p!=0);
                boost::weak_ptr<windows_thread_info> w;
                boost::function<void()> f;
                        {
                        boost::shared_ptr<windows_thread_info> wti;
                        static_cast<windows_thread_info *>(p)->self.swap(wti);
                        assert(wti);
                        f=wti->f;
                        assert(f);
                        w=wti;
                        }
                try
                        {
                        f();
                        }
                catch( ... )
                        {
                        boost::shared_ptr<windows_thread_info> wti=w.lock();
                        assert(wti); //(1)
                        wti->e=boost::current_exception();
                        }
                return 0;
                }
        }

boost::shared_ptr<windows_thread_info const>
win_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T
dwStackSize, boost::function<void()> const & f, DWORD dwCreationFlags
)
        {
        assert(f);
        boost::shared_ptr<windows_thread_info> wti(new windows_thread_info);
        wti->f=f;
        wti->self=wti;
        if( HANDLE h=CreateThread(lpThreadAttributes,dwStackSize,thread_proc_fwd,wti.get(),dwCreationFlags,&wti->id)
)
                {
                make_handle(h,CloseHandle).swap(wti->h);
                return wti;
                }
        else
                {
                wti->self.reset();
                BOOST_THROW_EXCEPTION(x_system() <<
xi_win_last_error(GetLastError()) << xi_function("CreateThread"));
                }
        }

void
join( windows_thread_info const & wti )
        {
        (void) win_WaitForSingleObject(*wti.h,INFINITE);
        boost::exception_ptr e;
                {
        using std::swap;
        swap(e,wti.e);
                }
        if( e )
                boost::rethrow_exception(e);
        }

--
Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk