From 56bd079f961f5fe86c5d7d003371e2473f6d342b Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Mon, 2 Apr 2012 16:32:33 +0000 Subject: [PATCH] Thread: Added call to terminate if joinable for #6266 and #6269 [SVN r77718] --- doc/changes.qbk | 5 +++-- doc/configuration.qbk | 10 ++++++++-- doc/thread_ref.qbk | 6 +++--- include/boost/thread/detail/config.hpp | 3 ++- include/boost/thread/detail/thread.hpp | 21 +++++++++++++++++++-- src/pthread/thread.cpp | 5 +---- src/win32/thread.cpp | 5 ----- test/threads/thread/assign/move_pass.cpp | 10 ++++------ test/threads/thread/destr/dtor_pass.cpp | 7 ++++--- 9 files changed, 44 insertions(+), 28 deletions(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index 63f5dd30..24049bd4 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -23,12 +23,15 @@ New Features: * [@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 @@ The following features will be included in next releases. # 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. diff --git a/doc/configuration.qbk b/doc/configuration.qbk index 011d7aad..2936e164 100644 --- a/doc/configuration.qbk +++ b/doc/configuration.qbk @@ -117,6 +117,11 @@ which introduces a dependency on Boost.Container. This feature is provided only [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] @@ -130,8 +135,9 @@ The user can request the version 2 by defining `BOOST_THREAD_VERSION` to 2. In t * 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] diff --git a/doc/thread_ref.qbk b/doc/thread_ref.qbk index 644bf8a2..560a3c1d 100644 --- a/doc/thread_ref.qbk +++ b/doc/thread_ref.qbk @@ -462,8 +462,8 @@ This behavior is incompatible with the current Boost.Thread design, so the use o [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 @@ are copied into internal storage for access by the new thread.]]] [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.]] diff --git a/include/boost/thread/detail/config.hpp b/include/boost/thread/detail/config.hpp index bcfd2cc8..f58c27ea 100644 --- a/include/boost/thread/detail/config.hpp +++ b/include/boost/thread/detail/config.hpp @@ -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 diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index c3b4751d..c6469b56 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -208,8 +208,16 @@ namespace boost 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 @@ namespace boost 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 @@ namespace boost #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 @@ namespace boost #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; diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index d3a74105..5bc5896e 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -244,10 +244,7 @@ namespace boost } } - thread::~thread() - { - detach(); - } + detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const { diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index 84de0fbb..b7466de3 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -271,11 +271,6 @@ namespace boost } - thread::~thread() - { - detach(); - } - thread::id thread::get_id() const BOOST_NOEXCEPT { return thread::id((get_thread_info)()); diff --git a/test/threads/thread/assign/move_pass.cpp b/test/threads/thread/assign/move_pass.cpp index b3f87d7a..631f459b 100644 --- a/test/threads/thread/assign/move_pass.cpp +++ b/test/threads/thread/assign/move_pass.cpp @@ -18,6 +18,8 @@ // thread& operator=(thread&& t); +#define BOOST_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + #include #include #include @@ -69,7 +71,7 @@ bool G::op_run = false; void f1() { - std::exit(0); + std::exit(boost::report_errors()); } int main() @@ -85,19 +87,15 @@ int main() 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(); } diff --git a/test/threads/thread/destr/dtor_pass.cpp b/test/threads/thread/destr/dtor_pass.cpp index 4cce0485..5697297a 100644 --- a/test/threads/thread/destr/dtor_pass.cpp +++ b/test/threads/thread/destr/dtor_pass.cpp @@ -17,6 +17,8 @@ // ~thread(); +#define BOOST_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE + #include #include #include @@ -58,7 +60,7 @@ bool G::op_run = false; void f1() { - std::exit(0); + std::exit(boost::report_errors()); } int main() @@ -71,10 +73,9 @@ int main() #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(); }