Index: boost/thread/detail/config.hpp =================================================================== --- boost/thread/detail/config.hpp (revision 77687) +++ boost/thread/detail/config.hpp (working copy) @@ -45,7 +45,6 @@ #define BOOST_THREAD_SHARED_MUTEX_GENERIC #endif - // Don't provided by default in version 1. #if defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION #define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION explicit @@ -64,6 +63,8 @@ #endif #if BOOST_THREAD_VERSION==2 +#define BOOST_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE +#define BOOST_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE #define BOOST_THREAD_USES_FUTURE #define BOOST_THREAD_FUTURE_USES_ALLOCATORS #define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION Index: boost/thread/detail/thread.hpp =================================================================== --- boost/thread/detail/thread.hpp (revision 77687) +++ boost/thread/detail/thread.hpp (working copy) @@ -208,8 +208,16 @@ thread(const volatile thread&); #endif thread() BOOST_NOEXCEPT; - ~thread(); - + ~thread() + { + #if defined BOOST_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) { + std::terminate(); + } + #else + detach(); + #endif + } #ifndef BOOST_NO_RVALUE_REFERENCES template < class F @@ -239,6 +247,9 @@ thread& operator=(thread&& other) BOOST_NOEXCEPT { +#if defined BOOST_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) std::terminate(); +#endif thread_info=other.thread_info; other.thread_info.reset(); return *this; @@ -354,6 +365,9 @@ #if defined BOOST_THREAD_USES_MOVE thread& operator=(boost::rv& x) BOOST_NOEXCEPT { +#if defined BOOST_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) std::terminate(); +#endif thread new_thread(boost::move(x)); swap(new_thread); return *this; @@ -361,6 +375,9 @@ #else thread& operator=(detail::thread_move_t x) BOOST_NOEXCEPT { +#if defined BOOST_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) std::terminate(); +#endif thread new_thread(x); swap(new_thread); return *this; Index: libs/thread/test/threads/thread/destr/dtor_pass.cpp =================================================================== --- libs/thread/test/threads/thread/destr/dtor_pass.cpp (revision 77702) +++ libs/thread/test/threads/thread/destr/dtor_pass.cpp (working copy) @@ -17,6 +17,8 @@ // ~thread(); +#define BOOST_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE + #include #include #include @@ -58,7 +60,7 @@ void f1() { - std::exit(0); + std::exit(boost::report_errors()); } int main() @@ -71,10 +73,9 @@ #if defined BOOST_THREAD_USES_CHRONO boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); #endif + BOOST_TEST(t.joinable()); } -#if 0 BOOST_TEST(false); -#endif return boost::report_errors(); } Index: libs/thread/test/threads/thread/assign/move_pass.cpp =================================================================== --- libs/thread/test/threads/thread/assign/move_pass.cpp (revision 77702) +++ libs/thread/test/threads/thread/assign/move_pass.cpp (working copy) @@ -18,6 +18,8 @@ // thread& operator=(thread&& t); +#define BOOST_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + #include #include #include @@ -69,7 +71,7 @@ void f1() { - std::exit(0); + std::exit(boost::report_errors()); } int main() @@ -85,19 +87,15 @@ BOOST_TEST(t1.get_id() == id); BOOST_TEST(t0.get_id() == boost::thread::id()); t1.join(); -#if 0 - BOOST_TEST(G::n_alive == 0); -#endif BOOST_TEST(G::op_run); } + BOOST_TEST(G::n_alive == 0); { boost::thread t0(G(), 5, 5.5); boost::thread::id id = t0.get_id(); boost::thread t1; t0 = boost::move(t1); -#if 0 BOOST_TEST(false); -#endif } return boost::report_errors(); } Index: libs/thread/doc/thread_ref.qbk =================================================================== --- libs/thread/doc/thread_ref.qbk (revision 77687) +++ libs/thread/doc/thread_ref.qbk (working copy) @@ -462,8 +462,8 @@ [variablelist [[Effects:] [Transfers ownership of the thread managed by `other` (if -any) to `*this`. If there was a thread previously associated with -`*this` then that thread is detached.]] +any) to `*this`. Version 1: If there was a thread previously associated with +`*this` then that thread is detached, version 2: If the thread is joinable calls to std::terminate.]] [[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]] @@ -620,7 +620,7 @@ [variablelist -[[Effects:] [If `*this` has an associated thread of execution, calls __detach__. Destroys `*this`.]] +[[Effects:] [Version 1: If `*this` has an associated thread of execution, calls __detach__, Version 2: If the thread is joinable calls to std::terminate. Destroys `*this`.]] [[Throws:] [Nothing.]] Index: libs/thread/doc/configuration.qbk =================================================================== --- libs/thread/doc/configuration.qbk (revision 77704) +++ libs/thread/doc/configuration.qbk (working copy) @@ -117,8 +117,13 @@ [endsect] +[section:terminate Call to terminate if joinable] +C++11 has a different semantic for the thread destructor and the move assignment. Instead of detaching the thread, calls to terminate() if the thread was joinable. When `BOOST_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE` and `BOOST_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE` is defined Boost.Thread provides the C++ semantic. +[endsect] + + [section:version `BOOST_THREAD_VERSION` Version] `BOOST_THREAD_VERSION` defines the Boost.Thread version. @@ -130,9 +135,10 @@ * Breaking change `BOOST_THREAD_USES_FUTURE` * Uniformity `BOOST_THREAD_SHARED_MUTEX_GENERIC` * Extension `BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION` -* Extension `BOOST_THREAD_FUTURE_USES_ALLOCATORS` +* Conformity `BOOST_THREAD_FUTURE_USES_ALLOCATORS` +* Breaking change BOOST_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE +* Breaking change BOOST_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE - [endsect] [endsect] \ No newline at end of file Index: libs/thread/doc/changes.qbk =================================================================== --- libs/thread/doc/changes.qbk (revision 77704) +++ libs/thread/doc/changes.qbk (working copy) @@ -23,12 +23,15 @@ * [@http://svn.boost.org/trac/boost/ticket/6226 #6226] c++11 compliance: Add explicit bool conversion from locks. * [@http://svn.boost.org/trac/boost/ticket/6228 #6228] Add promise constructor with allocator following the standard c++11. * [@http://svn.boost.org/trac/boost/ticket/6230 #6230] c++11 compliance: Follows the exception reporting mechanism as defined in the c++11. +* [@http://svn.boost.org/trac/boost/ticket/6266 #6266] Breaking change: thread destructor should call terminate if joinable. +* [@http://svn.boost.org/trac/boost/ticket/6269 #6269] Breaking change: thread move assignment should call terminate if joinable. * [@http://svn.boost.org/trac/boost/ticket/6272 #6272] c++11 compliance: Add thread::id hash specialization. * [@http://svn.boost.org/trac/boost/ticket/6273 #6273] c++11 compliance: Add cv_status enum class and use it on the conditions wait functions. * [@http://svn.boost.org/trac/boost/ticket/6231 #6231] Add BasicLockable requirements in the documentation to follow c++11. * [@http://svn.boost.org/trac/boost/ticket/6671 #6671] upgrade_lock: missing mutex and release functions. * [@http://svn.boost.org/trac/boost/ticket/6672 #6672] upgrade_lock:: missing constructors from time related types. * [@http://svn.boost.org/trac/boost/ticket/6675 #6675] upgrade_lock:: missing non-member swap. + Fixed Bugs: @@ -176,8 +179,6 @@ # Complete the C++11 missing features, in particular * [@http://svn.boost.org/trac/boost/ticket/4710 #4710] Missing async(). - * [@http://svn.boost.org/trac/boost/ticket/6266 #6266] Breaking change: thread destructor should call terminate if joinable. - * [@http://svn.boost.org/trac/boost/ticket/6269 #6269] Breaking change: thread move assignment should call terminate if joinable. * [@http://svn.boost.org/trac/boost/ticket/6342 #6342] Breaking change: Adapt the one_flag and call_once to the c++11 interface. * [@http://svn.boost.org/trac/boost/ticket/6227 #6227] Use of variadic templates on Generic Locking Algorithms on compilers providing them. Index: libs/thread/src/win32/thread.cpp =================================================================== --- libs/thread/src/win32/thread.cpp (revision 77687) +++ libs/thread/src/win32/thread.cpp (working copy) @@ -271,11 +271,6 @@ } - thread::~thread() - { - detach(); - } - thread::id thread::get_id() const BOOST_NOEXCEPT { return thread::id((get_thread_info)()); Index: libs/thread/src/pthread/thread.cpp =================================================================== --- libs/thread/src/pthread/thread.cpp (revision 77687) +++ libs/thread/src/pthread/thread.cpp (working copy) @@ -244,11 +244,8 @@ } } - thread::~thread() - { - detach(); - } + detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const { return thread_info;