[thread] Exception propagation for thread::join

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

Emil Dotchevski <emil@revergestudios.com> writes:
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?
No. You can easily write code that does this using a wrapper, as you have shown for the win32 API. The futures and packaged_task stuff that I will be merging with boost.thread soon will provide such a wrapper that also allows return values from thread functions. This provides people with a choice --- have the exception terminate the program (and allow a debugger to catch it) which is the default, or allow the exception to propagate by using a packaged_task+future. Anthony -- Author of C++ Concurrency in Action | http://www.manning.com/williams just::thread C++0x thread library | http://www.stdthread.co.uk Just Software Solutions Ltd | http://www.justsoftwaresolutions.co.uk 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

On Mon, May 18, 2009 at 3:10 AM, Anthony Williams <anthony.ajw@gmail.com> wrote:
Emil Dotchevski <emil@revergestudios.com> writes:
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?
No. You can easily write code that does this using a wrapper, as you have shown for the win32 API. The futures and packaged_task stuff that I will be merging with boost.thread soon will provide such a wrapper that also allows return values from thread functions.
The only advantage of integrating the wrapper in boost::thread is that it guarantees that you can't get a thread which doesn't have the exception catching/transporting wrapper. But now that I think about it again, I can't come up with a compelling use case so you're probably right. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Hi, I'm not sure I understood your concerns.There are a threader/joiner classes in the Boost.Async library that should already offer this functionality. As Anthony said, not only it transfer the exception when joining it but also the returned value when succeeeds. It uses the Future library from Anthony and is based on the design of Kevlin Henney. You can get it from the vault. I'd appreciate any comments. Best, Vicente ----- Original Message ----- From: "Anthony Williams" <anthony.ajw@gmail.com> To: <boost@lists.boost.org> Sent: Monday, May 18, 2009 12:10 PM Subject: Re: [boost] [thread] Exception propagation for thread::join
Emil Dotchevski <emil@revergestudios.com> writes:
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?
No. You can easily write code that does this using a wrapper, as you have shown for the win32 API. The futures and packaged_task stuff that I will be merging with boost.thread soon will provide such a wrapper that also allows return values from thread functions.
This provides people with a choice --- have the exception terminate the program (and allow a debugger to catch it) which is the default, or allow the exception to propagate by using a packaged_task+future.
Anthony -- Author of C++ Concurrency in Action | http://www.manning.com/williams just::thread C++0x thread library | http://www.stdthread.co.uk Just Software Solutions Ltd | http://www.justsoftwaresolutions.co.uk 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (4)
-
Anthony Williams
-
Emil Dotchevski
-
Emil Dotchevski
-
vicente.botet