From e294e6bcc88df97d0032d7bb5ba1040e9370bca1 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Sun, 21 Apr 2013 07:34:19 +0000 Subject: [PATCH] Thread fix #8451. [SVN r83995] --- doc/changes.qbk | 4 +- doc/scoped_thread.qbk | 43 +++++++++++++++++++- example/scoped_thread.cpp | 18 +++++++++ include/boost/thread/scoped_thread.hpp | 56 ++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index 31362f94..d02c0d97 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -49,8 +49,8 @@ * [@http://svn.boost.org/trac/boost/ticket/8323 #8323] boost::thread::try_join_for/try_join_until may block indefinitely due to a combination of problems in Boost.Thread and Boost.Chrono * [@http://svn.boost.org/trac/boost/ticket/8337 #8337] The internal representation of "std::string(this->code()->message())" escapes, but is destroyed when it exits scope. * [@http://svn.boost.org/trac/boost/ticket/8371 #8371] C++11 once_flag enabled when constexpr is not available - - +* [@http://svn.boost.org/trac/boost/ticket/8443 #8443] Header file inclusion order may cause crashes +* [@http://svn.boost.org/trac/boost/ticket/8451 #8451] Mmissing documented function 'boost::scoped_thread::joinable' [heading Version 4.0.0 - boost 1.53] diff --git a/doc/scoped_thread.qbk b/doc/scoped_thread.qbk index 8a95237e..43572112 100644 --- a/doc/scoped_thread.qbk +++ b/doc/scoped_thread.qbk @@ -105,6 +105,8 @@ The difference between strict_scoped_thread and scoped_thread is that the strict strict_scoped_thread& operator=(strict_scoped_thread const&) = delete; explicit strict_scoped_thread(thread&& t) noexcept; + template + explicit strict_scoped_thread(F&&, Args&&...); ~strict_scoped_thread(); @@ -125,7 +127,7 @@ This wrapper can be used to join the thread before destroying it seems a natural boost::strict_scoped_thread<> t((boost::thread(F))); -[section:default_constructor Default Constructor] +[section:default_constructor Constructor from a __thread] explicit strict_scoped_thread(thread&& t) noexcept; @@ -139,6 +141,24 @@ This wrapper can be used to join the thread before destroying it seems a natural [endsect] + +[section:call_constructor Move Constructor from a Callable] + + template + explicit strict_scoped_thread(F&&, Args&&...); + +[variablelist + +[[Effects:] [Construct a internal thread in place.]] + +[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]] + +[[Throws:] [Any exception the thread construction can throw.]] + +] + +[endsect] + [section:destructor Destructor] ~strict_scoped_thread(); @@ -149,7 +169,6 @@ This wrapper can be used to join the thread before destroying it seems a natural [[Throws:] [Nothing: The `CallableThread()(t_)` should not throw when joining the thread as the scoped variable is on a scope outside the thread function.]] - ] [endsect] @@ -160,6 +179,7 @@ This wrapper can be used to join the thread before destroying it seems a natural #include + template class scoped_thread { thread t_; // for exposition purposes only @@ -169,6 +189,8 @@ This wrapper can be used to join the thread before destroying it seems a natural scoped_thread& operator=(const scoped_thread&) = delete; explicit scoped_thread(thread&& th) noexcept; + template + explicit strict_scoped_thread(F&&, Args&&...); ~scoped_thread(); @@ -298,6 +320,23 @@ any) to `*this`. [endsect] +[section:call_constructor Move Constructor from a Callable] + + template + explicit strict_scoped_thread(F&&, Args&&...); + +[variablelist + +[[Effects:] [Construct a internal thread in place.]] + +[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]] + +[[Throws:] [Any exception the thread construction can throw.]] + +] + +[endsect] + [section:destructor Destructor] diff --git a/example/scoped_thread.cpp b/example/scoped_thread.cpp index a6d8814f..ec2ca81f 100644 --- a/example/scoped_thread.cpp +++ b/example/scoped_thread.cpp @@ -64,6 +64,24 @@ int main() // do_something_in_current_thread(); // do_something_with_current_thread(boost::thread(g)); // } + { + int some_local_state; + boost::scoped_thread<> t( (boost::thread(func(some_local_state)))); + + if (t.joinable()) + t.join(); + else + do_something_in_current_thread(); + } + { + int some_local_state; + boost::thread t(( func(some_local_state) )); + boost::scoped_thread<> g( (boost::move(t)) ); + t.detach(); + + do_something_in_current_thread(); + } + return 0; } diff --git a/include/boost/thread/scoped_thread.hpp b/include/boost/thread/scoped_thread.hpp index faf4039c..3f43d469 100644 --- a/include/boost/thread/scoped_thread.hpp +++ b/include/boost/thread/scoped_thread.hpp @@ -38,10 +38,35 @@ namespace boost class strict_scoped_thread { thread t_; + struct dummy; public: BOOST_THREAD_NO_COPYABLE( strict_scoped_thread) /// non copyable + /* + * + */ +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args, + typename disable_if::type, thread>, dummy* >::type=0) : + t_(boost::forward(f), boost::forward(args)...) {} +#else + template + explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, + typename disable_if::type, thread>, dummy* >::type=0) : + t_(boost::forward(f)) {} + template + strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) : + t_(boost::forward(f), boost::forward(a1)) {} + template + strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) : + t_(boost::forward(f), boost::forward(a1), boost::forward(a2)) {} + template + strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) : + t_(boost::forward(f), boost::forward(a1), boost::forward(a2), boost::forward(a3)) {} +#endif + /** * Constructor from the thread to own. * @@ -91,6 +116,7 @@ namespace boost class scoped_thread { thread t_; + struct dummy; public: typedef thread::id id; @@ -107,6 +133,31 @@ namespace boost { } + /** + * + */ + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args, + typename disable_if::type, thread>, dummy* >::type=0) : + t_(boost::forward(f), boost::forward(args)...) {} +#else + template + explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, + typename disable_if::type, thread>, dummy* >::type=0) : + t_(boost::forward(f)) {} + template + scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) : + t_(boost::forward(f), boost::forward(a1)) {} + template + scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) : + t_(boost::forward(f), boost::forward(a1), boost::forward(a2)) {} + template + scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) : + t_(boost::forward(f), boost::forward(a1), boost::forward(a2), boost::forward(a3)) {} + +#endif /** * Constructor from the thread to own. * @@ -195,6 +246,11 @@ namespace boost return t_.native_handle(); } + bool joinable() const BOOST_NOEXCEPT + { + return t_.joinable(); + } + #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void interrupt() {