diff --git a/example/future_then.cpp b/example/future_then.cpp index 05aa47ef..4cd86c75 100644 --- a/example/future_then.cpp +++ b/example/future_then.cpp @@ -4,8 +4,9 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) //#define BOOST_THREAD_VERSION 4 -#define BOOST_THREAD_USES_LOG -#define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +//#define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET #include #include diff --git a/include/boost/thread/future.hpp b/include/boost/thread/future.hpp index d6180726..e08f2629 100644 --- a/include/boost/thread/future.hpp +++ b/include/boost/thread/future.hpp @@ -15,6 +15,7 @@ #ifndef BOOST_NO_EXCEPTIONS +//#include #include #include #include @@ -45,7 +46,7 @@ #include #include -#include +#include #ifdef BOOST_THREAD_USES_CHRONO #include #endif @@ -66,31 +67,10 @@ namespace boost { - - //enum class future_errc - BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc) - { - broken_promise = 1, - future_already_retrieved, - promise_already_satisfied, - no_state - } - BOOST_SCOPED_ENUM_DECLARE_END(future_errc) - - namespace system - { - template <> - struct BOOST_SYMBOL_VISIBLE is_error_code_enum : public true_type {}; - - #ifdef BOOST_NO_CXX11_SCOPED_ENUMS - template <> - struct BOOST_SYMBOL_VISIBLE is_error_code_enum : public true_type { }; - #endif - } - //enum class launch BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch) { + none = 0, async = 1, deferred = 2, any = async | deferred @@ -106,26 +86,6 @@ namespace boost } BOOST_SCOPED_ENUM_DECLARE_END(future_status) - BOOST_THREAD_DECL - const system::error_category& future_category() BOOST_NOEXCEPT; - - namespace system - { - inline - error_code - make_error_code(future_errc e) BOOST_SYSTEM_NOEXCEPT - { - return error_code(underlying_cast(e), boost::future_category()); - } - - inline - error_condition - make_error_condition(future_errc e) BOOST_SYSTEM_NOEXCEPT - { - return error_condition(underlying_cast(e), future_category()); - } - } - class BOOST_SYMBOL_VISIBLE future_error : public std::logic_error { @@ -283,7 +243,7 @@ namespace boost future_object_base(): done(false), is_deferred_(false), - policy_(launch::any), + policy_(launch::none), is_constructed(false) //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS , thread_was_interrupted(false) @@ -295,8 +255,19 @@ namespace boost virtual ~future_object_base() {} - void set_deferred() {is_deferred_ = true;} - void set_launch_policy(launch policy) {policy_ = policy;} + void set_deferred() + { + is_deferred_ = true; + set_launch_policy(launch::deferred); + } + void set_async() + { + set_launch_policy(launch::async); + } + void set_launch_policy(launch policy) + { + policy_ = policy; + } waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv) { @@ -861,35 +832,41 @@ namespace boost future_object& operator=(future_object const&); }; + ///////////////////////// /// future_async_object + ///////////////////////// template struct future_async_object: future_object { typedef future_object base_type; + typedef typename base_type::move_dest_type move_dest_type; + boost::thread thr_; public: - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - explicit future_async_object(Fp&& f) - : - #else - explicit future_async_object(BOOST_THREAD_FWD_REF(Fp) f) - : - #endif - thr_(&future_async_object::run, this, boost::forward(f)) + explicit future_async_object(BOOST_THREAD_FWD_REF(Fp) f) : + thr_(&future_async_object::run, this, boost::forward(f)) { + this->set_async(); } ~future_async_object() { - thr_.join(); + if (thr_.joinable()) thr_.join(); + } + + move_dest_type get() + { + if (thr_.joinable()) thr_.join(); + // fixme Is the lock needed during the whole scope? + //this->wait(); + boost::unique_lock lock(this->mutex); + this->wait_internal(lock); + + return static_cast(*(this->result)); } -#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - static void run(future_async_object* that, Fp&& f) -#else static void run(future_async_object* that, BOOST_THREAD_FWD_REF(Fp) f) -#endif { try { @@ -912,30 +889,22 @@ namespace boost struct future_async_object: public future_object { typedef future_object base_type; + boost::thread thr_; public: - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - explicit future_async_object(Fp&& f) - : - #else - explicit future_async_object(BOOST_THREAD_FWD_REF(Fp) f) - : - #endif - thr_(&future_async_object::run, this, boost::forward(f)) + explicit future_async_object(BOOST_THREAD_FWD_REF(Fp) f) : + thr_(&future_async_object::run, this, boost::forward(f)) { + this->set_async(); } ~future_async_object() { - thr_.join(); + if (thr_.joinable()) thr_.join(); } -#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - static void run(future_async_object* that, Fp&& f) -#else static void run(future_async_object* that, BOOST_THREAD_FWD_REF(Fp) f) -#endif { try { @@ -954,7 +923,9 @@ namespace boost } } }; + ////////////////////////// /// future_deferred_object + ////////////////////////// template struct future_deferred_object: future_object { @@ -962,13 +933,8 @@ namespace boost Fp func_; public: - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - explicit future_deferred_object(Fp&& f) + explicit future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f) : func_(boost::forward(f)) - #else - explicit future_deferred_object(Fp f) - : func_(f) - #endif { this->set_deferred(); } @@ -992,13 +958,8 @@ namespace boost Fp func_; public: - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - explicit future_deferred_object(Fp&& f) + explicit future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f) : func_(boost::forward(f)) - #else - explicit future_deferred_object(Fp f) - : func_(f) - #endif { this->set_deferred(); } @@ -1396,19 +1357,11 @@ namespace boost { template BOOST_THREAD_FUTURE - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - make_future_async_object(Fp&& f); - #else make_future_async_object(BOOST_THREAD_FWD_REF(Fp) f); - #endif template BOOST_THREAD_FUTURE - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - make_future_deferred_object(Fp&& f); - #else make_future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f); - #endif } template @@ -1433,19 +1386,11 @@ namespace boost template friend BOOST_THREAD_FUTURE - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - detail::make_future_async_object(Fp&& f); - #else detail::make_future_async_object(BOOST_THREAD_FWD_REF(Fp) f); - #endif template friend BOOST_THREAD_FUTURE - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - detail::make_future_deferred_object(Fp&& f); - #else detail::make_future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f); - #endif typedef typename detail::future_traits::move_dest_type move_dest_type; @@ -2856,11 +2801,7 @@ namespace boost //////////////////////////////// template BOOST_THREAD_FUTURE - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - make_future_deferred_object(Fp&& f) - #else make_future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f) - #endif { shared_ptr > h(new future_deferred_object(boost::forward(f))); @@ -2872,11 +2813,7 @@ namespace boost //////////////////////////////// template BOOST_THREAD_FUTURE - #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES - make_future_async_object(Fp&& f) - #else make_future_async_object(BOOST_THREAD_FWD_REF(Fp) f) - #endif { shared_ptr > h(new future_async_object(boost::forward(f))); diff --git a/include/boost/thread/future_error_code.hpp b/include/boost/thread/future_error_code.hpp new file mode 100644 index 00000000..635e3457 --- /dev/null +++ b/include/boost/thread/future_error_code.hpp @@ -0,0 +1,61 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURE_ERROR_CODE_HPP +#define BOOST_THREAD_FUTURE_ERROR_CODE_HPP + +#include +#include +#include +#include + +namespace boost +{ + + //enum class future_errc + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc) + { + broken_promise = 1, + future_already_retrieved, + promise_already_satisfied, + no_state + } + BOOST_SCOPED_ENUM_DECLARE_END(future_errc) + + namespace system + { + template <> + struct BOOST_SYMBOL_VISIBLE is_error_code_enum : public true_type {}; + + #ifdef BOOST_NO_CXX11_SCOPED_ENUMS + template <> + struct BOOST_SYMBOL_VISIBLE is_error_code_enum : public true_type { }; + #endif + } // system + + BOOST_THREAD_DECL + const system::error_category& future_category() BOOST_NOEXCEPT; + + namespace system + { + inline + error_code + make_error_code(future_errc e) BOOST_SYSTEM_NOEXCEPT + { + return error_code(underlying_cast(e), boost::future_category()); + } + + inline + error_condition + make_error_condition(future_errc e) BOOST_SYSTEM_NOEXCEPT + { + return error_condition(underlying_cast(e), future_category()); + } + } // system +} // boost + +#endif // header diff --git a/src/future.cpp b/src/future.cpp index 7c76bce0..8c6b14d6 100755 --- a/src/future.cpp +++ b/src/future.cpp @@ -7,7 +7,7 @@ #ifndef BOOST_NO_EXCEPTIONS -#include +#include namespace boost { diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index 98737444..2600a940 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -395,7 +395,7 @@ namespace boost bool thread::joinable() const BOOST_NOEXCEPT { - return (get_thread_info)()!=0; + return (get_thread_info)()?true:false; } diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index 3f691e07..c5022e27 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -330,7 +330,7 @@ namespace boost bool thread::joinable() const BOOST_NOEXCEPT { - return (get_thread_info)() != 0; + return (get_thread_info)() ? true : false; } bool thread::join_noexcept() { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 474fcbb3..a212f250 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -662,11 +662,9 @@ rule thread-compile-fail ( sources : reqs * : name ) explicit ts_ ; test-suite ts_ : - [ thread-run2-noit ./sync/conditions/notify_all_at_thread_exit_pass.cpp : notify_all_at_thread_exit_p2 ] - [ thread-run2-noit ./threads/thread/members/try_join_until_pass.cpp : thread__join_until_p2 ] - [ thread-run2-noit ./threads/thread/members/try_join_for_pass.cpp : thread__join_for_p2 ] - [ thread-run2-noit ./sync/futures/async/async_pass.cpp : async__async_p2 ] + #[ thread-run2-noit ./sync/futures/future/then_pass.cpp : future__then_p ] + [ compile virtual_noexcept.cpp ] #[ thread-run test_7665.cpp ] #[ thread-run test_7666.cpp ] #[ thread-run ../example/unwrap.cpp ] diff --git a/test/sync/futures/future/get_pass.cpp b/test/sync/futures/future/get_pass.cpp index 5d6859d1..cef70818 100755 --- a/test/sync/futures/future/get_pass.cpp +++ b/test/sync/futures/future/get_pass.cpp @@ -22,6 +22,9 @@ //#define BOOST_THREAD_VERSION 3 #define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include #include #include @@ -87,49 +90,65 @@ void func6(boost::promise p) int main() { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; { typedef int T; +// { +// boost::promise p; +// boost::future f = p.get_future(); +//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +// boost::thread(func1, boost::move(p)).detach(); +//#else +// p.set_value(3); +//#endif +// BOOST_TEST(f.valid()); +// BOOST_TEST(f.get() == 3); +//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET +// BOOST_TEST(!f.valid()); +//#endif +// } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; { boost::promise p; + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; boost::future f = p.get_future(); -#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) - boost::thread(func1, boost::move(p)).detach(); -#else - p.set_value(3); -#endif - BOOST_TEST(f.valid()); - BOOST_TEST(f.get() == 3); -#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET - BOOST_TEST(!f.valid()); -#endif - } - { - boost::promise p; - boost::future f = p.get_future(); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) boost::thread(func2, boost::move(p)).detach(); #else p.set_exception(boost::make_exception_ptr(3)); #endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; try { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(f.valid()); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(f.get() == 3); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(false); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; } catch (boost::wrap const& i) { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(i.value == 3); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; } catch (...) { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(false); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; } #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(!f.valid()); #endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; } } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; { typedef int& T; { @@ -147,6 +166,7 @@ int main() BOOST_TEST(!f.valid()); #endif } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; { boost::promise p; boost::future f = p.get_future(); @@ -170,6 +190,7 @@ int main() #endif } } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; typedef void T; { @@ -186,6 +207,7 @@ int main() BOOST_TEST(!f.valid()); #endif } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; { boost::promise p; boost::future f = p.get_future(); @@ -212,6 +234,7 @@ int main() BOOST_TEST(!f.valid()); #endif } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; return boost::report_errors(); } diff --git a/test/sync/futures/future/then_pass.cpp b/test/sync/futures/future/then_pass.cpp index cb76573d..3e7d0fa8 100644 --- a/test/sync/futures/future/then_pass.cpp +++ b/test/sync/futures/future/then_pass.cpp @@ -8,10 +8,13 @@ // class future // template -// auto then(F&& func) -> BOOST_THREAD_FUTURE; +// auto then(F&& func) -> future; #define BOOST_THREAD_VERSION 4 #define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include #include #include @@ -30,23 +33,37 @@ int p2(boost::future& f) int main() { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; { boost::future f1 = boost::async(p1); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; boost::future f2 = f1.then(p2); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(f2.get()==2); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; } { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; boost::future f2 = boost::async(p1).then(p2); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(f2.get()==2); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; } { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; boost::future f1 = boost::async(p1); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; boost::future f2 = f1.then(p2).then(p2); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(f2.get()==4); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; } { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; boost::future f2 = boost::async(p1).then(p2).then(p2); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_TEST(f2.get()==4); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; } return boost::report_errors();