diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index eeed31d7..97c38969 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -48,7 +48,7 @@ project boost/thread @$(__name__).tag gcc:-Wno-long-long BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - BOOST_SYSTEM_NO_DEPRECATED + #BOOST_SYSTEM_NO_DEPRECATED #BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS /boost/system//boost_system @@ -114,7 +114,7 @@ project boost/thread static:BOOST_THREAD_BUILD_LIB=1 shared:BOOST_THREAD_BUILD_DLL=1 BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - BOOST_SYSTEM_NO_DEPRECATED + #BOOST_SYSTEM_NO_DEPRECATED /boost/system//boost_system ; 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/example/synchronized_person.cpp b/example/synchronized_person.cpp index 7d4f6b98..c7836854 100644 --- a/example/synchronized_person.cpp +++ b/example/synchronized_person.cpp @@ -158,7 +158,7 @@ public: #if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS auto memberSync = member.synchronize(); #else - boost::synchronized_value::const_strict_synchronizer memberSync = member.synchronize(); + boost::const_strict_lock_ptr memberSync = member.synchronize(); #endif Invariant(memberSync); return memberSync->name; @@ -167,7 +167,7 @@ public: #if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS auto memberSync = member.synchronize(); #else - boost::synchronized_value::strict_synchronizer memberSync = member.synchronize(); + boost::strict_lock_ptr memberSync = member.synchronize(); #endif Invariant(memberSync); memberSync->name = newName; @@ -180,7 +180,7 @@ private: std::string name; unsigned int age; }; - void Invariant(boost::synchronized_value::const_strict_synchronizer & mbr) const + void Invariant(boost::const_strict_lock_ptr & mbr) const { if (mbr->age < 1) throw std::runtime_error("Age cannot be negative"); } @@ -236,5 +236,24 @@ int main() Person3_ts p(1); p->SetName("Vicente"); } + { + Person3_ts p1(1); + Person3_ts p2(2); + Person3_ts p3(3); +#if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS + auto lk1 = p1.unique_synchronize(boost::defer_lock); + auto lk2 = p2.unique_synchronize(boost::defer_lock); + auto lk3 = p3.unique_synchronize(boost::defer_lock); +#else + boost::unique_lock_ptr lk1 = p1.unique_synchronize(boost::defer_lock); + boost::unique_lock_ptr lk2 = p2.unique_synchronize(boost::defer_lock); + boost::unique_lock_ptr lk3 = p3.unique_synchronize(boost::defer_lock); +#endif + boost::lock(lk1,lk2,lk3); + + lk1->SetName("Carmen"); + lk2->SetName("Javier"); + lk3->SetName("Matias"); + } return 0; } diff --git a/example/synchronized_value.cpp b/example/synchronized_value.cpp index 611a7d22..04c7b735 100644 --- a/example/synchronized_value.cpp +++ b/example/synchronized_value.cpp @@ -12,7 +12,7 @@ void addTrailingSlashIfMissing(boost::synchronized_value & path) { - boost::synchronized_value::strict_synchronizer u=path.synchronize(); + boost::strict_lock_ptr u=path.synchronize(); if(u->empty() || (*u->rbegin()!='/')) { @@ -24,13 +24,13 @@ void f(const boost::synchronized_value &v) { std::cout<<"v="<<*v<::const_strict_synchronizer &v) { +void g(const boost::const_strict_lock_ptr &v) { std::cout<<"v="<<*v< & path) { - boost::synchronized_value::strict_synchronizer u=path.synchronize(); + boost::strict_lock_ptr u=path.synchronize(); return (u->empty() || (*u->rbegin()!='/')); } @@ -46,7 +46,7 @@ int main() std::cout<<"i="<::strict_synchronizer u=v1.synchronize(); + boost::strict_lock_ptr u=v1.synchronize(); *u+=43; std::cout<<"v1="<<*u< +#endif +#include + +namespace boost +{ + +#if ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST + namespace thread_detail + { + template + struct lockable_wrapper + { + Mutex* m; + explicit lockable_wrapper(Mutex& m_) : + m(&m_) + {} + }; + template + struct lockable_adopt_wrapper + { + Mutex* m; + explicit lockable_adopt_wrapper(Mutex& m_) : + m(&m_) + {} + }; + } +#endif + +} + +#include + +#endif // header diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index e90d7e3f..662e21c3 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -731,7 +731,7 @@ namespace boost namespace this_thread { - thread::id get_id() BOOST_NOEXCEPT + inline thread::id get_id() BOOST_NOEXCEPT { #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID return pthread_self(); diff --git a/include/boost/thread/externally_locked.hpp b/include/boost/thread/externally_locked.hpp index 4d98fed5..6be21e23 100644 --- a/include/boost/thread/externally_locked.hpp +++ b/include/boost/thread/externally_locked.hpp @@ -53,7 +53,7 @@ namespace boost /** * Requires: T is a model of Movable. - * Effects: Constructs an externally locked object copying the cloaked type. + * Effects: Constructs an externally locked object by moving the cloaked type. */ BOOST_CONSTEXPR externally_locked(mutex_type& mtx, BOOST_THREAD_RV_REF(T) obj) : obj_(move(obj)), mtx_(&mtx) @@ -83,7 +83,7 @@ namespace boost * * Returns: The address of the cloaked object.. * - * Throws: lock_error if BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME is not defined and the lk parameter doesn't satisfy the preconditions + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions */ T& get(strict_lock& lk) { @@ -117,7 +117,7 @@ namespace boost * Requires: The lk parameter must be locking the associated mtx. * Returns: The address of the cloaked object.. * - * Throws: lock_error if BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME is not defined and the lk parameter doesn't satisfy the preconditions + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions */ template T& get(Lock& lk) @@ -203,7 +203,7 @@ namespace boost * * Returns: The address of the cloaked object.. * - * Throws: lock_error if BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME is not defined and the lk parameter doesn't satisfy the preconditions + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions */ T& get(strict_lock const& lk) { @@ -237,7 +237,7 @@ namespace boost * Requires: The lk parameter must be locking the associated mtx. * Returns: The address of the cloaked object.. * - * Throws: lock_error if BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME is not defined and the lk parameter doesn't satisfy the preconditions + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions */ template T& get(Lock const& lk) @@ -245,7 +245,7 @@ namespace boost BOOST_CONCEPT_ASSERT(( StrictLock )); BOOST_STATIC_ASSERT( (is_strict_lock::value)); /*< lk is a strict lock "sur parolle" >*/ BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ - BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(), lock_error() ); /*< run time check throw if no locked >*/ + //BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(), lock_error() ); /*< run time check throw if no locked >*/ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ return *obj_; } @@ -254,7 +254,7 @@ namespace boost * Requires: The lk parameter must be locking the associated mtx. * Returns: The address of the cloaked object.. * - * Throws: lock_error if BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME is not defined and the lk parameter doesn't satisfy the preconditions + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions */ template T const& get(Lock const& lk) const @@ -262,7 +262,7 @@ namespace boost BOOST_CONCEPT_ASSERT(( StrictLock )); BOOST_STATIC_ASSERT( (is_strict_lock::value)); /*< lk is a strict lock "sur parolle" >*/ BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ - BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(), lock_error() ); /*< run time check throw if no locked >*/ + //BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(), lock_error() ); /*< run time check throw if no locked >*/ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ return *obj_; } diff --git a/include/boost/thread/future.hpp b/include/boost/thread/future.hpp index 1e03da14..de23fda4 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,87 +67,46 @@ 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) - { - async = 1, - deferred = 2, - any = async | deferred - } - BOOST_SCOPED_ENUM_DECLARE_END(launch) - - //enum class future_status - BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status) - { - ready, - timeout, - deferred - } - 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_NOEXCEPT + //enum class launch + BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch) { - return error_code(underlying_cast(e), boost::future_category()); + none = 0, + async = 1, + deferred = 2, + any = async | deferred } + BOOST_SCOPED_ENUM_DECLARE_END(launch) - inline - error_condition - make_error_condition(future_errc e) //BOOST_NOEXCEPT + //enum class future_status + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status) { - return error_condition(underlying_cast(e), future_category()); + ready, + timeout, + deferred } - } + BOOST_SCOPED_ENUM_DECLARE_END(future_status) - class BOOST_SYMBOL_VISIBLE future_error - : public std::logic_error - { - system::error_code ec_; - public: - future_error(system::error_code ec) - : logic_error(ec.message()), - ec_(ec) - { - } + class BOOST_SYMBOL_VISIBLE future_error + : public std::logic_error + { + system::error_code ec_; + public: + future_error(system::error_code ec) + : logic_error(ec.message()), + ec_(ec) + { + } - const system::error_code& code() const BOOST_NOEXCEPT - { - return ec_; - } - const char* what() const BOOST_THREAD_NOEXCEPT_OR_THROW - { - return code().message().c_str(); - } + const system::error_code& code() const BOOST_NOEXCEPT + { + return ec_; + } + const char* what() const BOOST_THREAD_NOEXCEPT_OR_THROW + { + return code().message().c_str(); + } - }; + }; class BOOST_SYMBOL_VISIBLE future_uninitialized: public future_error @@ -190,23 +150,23 @@ namespace boost {} }; - class BOOST_SYMBOL_VISIBLE task_moved: - public future_error - { - public: - task_moved(): - future_error(system::make_error_code(future_errc::no_state)) - {} - }; + class BOOST_SYMBOL_VISIBLE task_moved: + public future_error + { + public: + task_moved(): + future_error(system::make_error_code(future_errc::no_state)) + {} + }; - class promise_moved: - public future_error - { - public: - promise_moved(): - future_error(system::make_error_code(future_errc::no_state)) - {} - }; + class promise_moved: + public future_error + { + public: + promise_moved(): + future_error(system::make_error_code(future_errc::no_state)) + {} + }; namespace future_state { @@ -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) { @@ -508,7 +479,9 @@ namespace boost #endif ); } - void is_deferred() {is_deferred_ = true;} + bool is_deferred() const BOOST_NOEXCEPT { + return is_deferred_ == true; + } launch launch_policy() const BOOST_NOEXCEPT { @@ -518,6 +491,7 @@ namespace boost template void set_wait_callback(F f,U* u) { + boost::lock_guard lock(mutex); callback=boost::bind(f,boost::ref(*u)); } virtual void execute(boost::unique_lock&) {} @@ -861,35 +835,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 +892,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 +926,9 @@ namespace boost } } }; + ////////////////////////// /// future_deferred_object + ////////////////////////// template struct future_deferred_object: future_object { @@ -962,13 +936,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 +961,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(); } @@ -1333,7 +1297,7 @@ namespace boost launch launch_policy() const BOOST_NOEXCEPT { if ( future_ ) return future_->launch_policy(); - else return launch(launch::any); + else return launch(launch::none); } bool valid() const BOOST_NOEXCEPT @@ -1396,19 +1360,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 +1389,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 +2804,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 +2816,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..be3de1a9 --- /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_NOEXCEPT + { + return error_code(underlying_cast(e), boost::future_category()); + } + + inline + error_condition + make_error_condition(future_errc e) BOOST_NOEXCEPT + { + return error_condition(underlying_cast(e), future_category()); + } + } // system +} // boost + +#endif // header diff --git a/include/boost/thread/lock_guard.hpp b/include/boost/thread/lock_guard.hpp index e24c8456..a3007a8e 100644 --- a/include/boost/thread/lock_guard.hpp +++ b/include/boost/thread/lock_guard.hpp @@ -9,42 +9,18 @@ #include #include +#include #include #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS #include -#endif #include -#include -#if ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST -#include #endif + #include namespace boost { -#if ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST - namespace thread_detail - { - template - struct lockable_wrapper - { - Mutex* m; - explicit lockable_wrapper(Mutex& m_) : - m(&m_) - {} - }; - template - struct lockable_adopt_wrapper - { - Mutex* m; - explicit lockable_adopt_wrapper(Mutex& m_) : - m(&m_) - {} - }; - } -#endif - template class lock_guard { diff --git a/include/boost/thread/strict_lock.hpp b/include/boost/thread/strict_lock.hpp index b6808a34..b4909cfd 100644 --- a/include/boost/thread/strict_lock.hpp +++ b/include/boost/thread/strict_lock.hpp @@ -7,6 +7,7 @@ #define BOOST_THREAD_STRICT_LOCK_HPP #include +#include #include #include #include @@ -48,6 +49,15 @@ namespace boost mtx.lock(); } /*< locks on construction >*/ + +#if ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST + strict_lock(std::initializer_list > l_) : + mtx_(*(const_cast*>(l_.begin())->m)) + { + mtx_.lock(); + } +#endif + /** * Destructor * @@ -97,7 +107,7 @@ namespace boost /** * A nested strict lock is a scoped lock guard ensuring the mutex is locked on its - * scope, by taking ownership of an nesting lock, and locking the mutex on construction if not already locked + * scope, by taking ownership of an nesting lock, locking the mutex on construction if not already locked * and restoring the ownership to the nesting lock on destruction. */ //[nested_strict_lock @@ -117,8 +127,8 @@ namespace boost * * __Requires: lk.mutex() != null_ptr * __Effects: Stores the reference to the lock parameter and takes ownership on it. - * If the lock doesn't owns the mutex @mtx lock it. - * __Postconditions: @c owns_lock() + * If the lock doesn't owns the mutex @c mtx lock it. + * __Postconditions: @c owns_lock(lk.mutex()) * __StrongException * __Throws: * @@ -127,7 +137,7 @@ namespace boost * - Any exception that @c lk.lock() can throw. * */ - nested_strict_lock(Lock& lk) : + explicit nested_strict_lock(Lock& lk) : lk_(lk) /*< Store reference to lk >*/ { /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/ @@ -138,6 +148,19 @@ namespace boost tmp_lk_ = move(lk); /*< Move ownership to temporary lk >*/ } +#if ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST + nested_strict_lock(std::initializer_list > l_) : + lk_(*(const_cast*>(l_.begin())->m)) + { + /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/ + BOOST_THREAD_ASSERT_PRECONDITION( lk_.mutex() != 0, + lock_error() + ); + if (!lk_.owns_lock()) lk_.lock(); /*< ensures it is locked >*/ + tmp_lk_ = move(lk_); /*< Move ownership to temporary lk >*/ + } +#endif + /** * Destructor * @@ -180,6 +203,18 @@ public: { }; +#if ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST + template + strict_lock make_strict_lock(Lockable& mtx) + { + return { thread_detail::lockable_wrapper(mtx) }; + } + template + nested_strict_lock make_nested_strict_lock(Lock& lk) + { + return { thread_detail::lockable_wrapper(lk) }; + } +#endif } #include diff --git a/include/boost/thread/synchronized_value.hpp b/include/boost/thread/synchronized_value.hpp index bc5e778c..2583e88e 100644 --- a/include/boost/thread/synchronized_value.hpp +++ b/include/boost/thread/synchronized_value.hpp @@ -23,6 +23,195 @@ namespace boost { + + /** + * + */ + template + class const_strict_lock_ptr + { + public: + typedef T value_type; + typedef Lockable lockable_type; + protected: + + // this should be a strict_lock, but we need to be able to return it. + boost::unique_lock lk_; + T const& value_; + + public: + BOOST_THREAD_MOVABLE_ONLY( const_strict_lock_ptr ) + + const_strict_lock_ptr(T const& value, Lockable & mtx) : + lk_(mtx), value_(value) + { + } + + const_strict_lock_ptr(BOOST_THREAD_RV_REF(const_strict_lock_ptr) other) + : lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_) + { + } + + ~const_strict_lock_ptr() + { + } + + const T* operator->() const + { + return &value_; + } + + const T& operator*() const + { + return value_; + } + + }; + + /** + * + */ + template + class strict_lock_ptr : public const_strict_lock_ptr + { + typedef const_strict_lock_ptr base_type; + public: + BOOST_THREAD_MOVABLE_ONLY( strict_lock_ptr ) + + strict_lock_ptr(T & value, Lockable & mtx) : + base_type(value, mtx) + { + } + + strict_lock_ptr(BOOST_THREAD_RV_REF(strict_lock_ptr) other) + : base_type(boost::move(static_cast(other))) + { + } + + ~strict_lock_ptr() + { + } + + T* operator->() + { + return const_cast(&this->value_); + } + + T& operator*() + { + return const_cast(this->value_); + } + + }; + + /** + * + */ + template + class const_unique_lock_ptr : public unique_lock + { + typedef unique_lock base_type; + public: + typedef T value_type; + typedef Lockable lockable_type; + protected: + T const& value_; + + public: + BOOST_THREAD_MOVABLE_ONLY(const_unique_lock_ptr) + + const_unique_lock_ptr(T const& value, Lockable & mtx) + : base_type(mtx), value_(value) + { + } + const_unique_lock_ptr(T const& value, Lockable & mtx, adopt_lock_t) + : base_type(mtx, adopt_lock), value_(value) + { + } + const_unique_lock_ptr(T const& value, Lockable & mtx, defer_lock_t) + : base_type(mtx, defer_lock), value_(value) + { + } + const_unique_lock_ptr(T const& value, Lockable & mtx, try_to_lock_t) + : base_type(mtx, try_to_lock), value_(value) + { + } + const_unique_lock_ptr(BOOST_THREAD_RV_REF(const_unique_lock_ptr) other) + : base_type(boost::move(static_cast(other))), value_(BOOST_THREAD_RV(other).value_) + { + } + + ~const_unique_lock_ptr() + { + } + + const T* operator->() const + { + BOOST_ASSERT (this->owns_lock()); + return &value_; + } + + const T& operator*() const + { + BOOST_ASSERT (this->owns_lock()); + return value_; + } + + }; + + /** + * + */ + template + class unique_lock_ptr : public const_unique_lock_ptr + { + typedef const_unique_lock_ptr base_type; + public: + typedef T value_type; + typedef Lockable lockable_type; + + BOOST_THREAD_MOVABLE_ONLY(unique_lock_ptr) + + unique_lock_ptr(T & value, Lockable & mtx) + : base_type(value, mtx) + { + } + unique_lock_ptr(T & value, Lockable & mtx, adopt_lock_t) + : base_type(value, mtx, adopt_lock) + { + } + unique_lock_ptr(T & value, Lockable & mtx, defer_lock_t) + : base_type(value, mtx, defer_lock) + { + } + unique_lock_ptr(T & value, Lockable & mtx, try_to_lock_t) + : base_type(value, mtx, try_to_lock) + { + } + unique_lock_ptr(BOOST_THREAD_RV_REF(unique_lock_ptr) other) + : base_type(boost::move(static_cast(other))) + { + } + + ~unique_lock_ptr() + { + } + + T* operator->() + { + BOOST_ASSERT (this->owns_lock()); + return const_cast(&this->value_); + } + + T& operator*() + { + BOOST_ASSERT (this->owns_lock()); + return const_cast(this->value_); + } + + + }; + /** * */ @@ -181,99 +370,24 @@ namespace boost boost::swap(value_, rhs.value_); } - /** - * - */ - struct const_strict_synchronizer - { - protected: - friend class synchronized_value; - - // this should be a strict_lock, but we need to be able to return it. - boost::unique_lock lk_; - T const& value_; - - explicit const_strict_synchronizer(synchronized_value const& outer) : - lk_(outer.mtx_), value_(outer.value_) - { - } - public: - BOOST_THREAD_MOVABLE_ONLY( const_strict_synchronizer ) - - const_strict_synchronizer(BOOST_THREAD_RV_REF(const_strict_synchronizer) other) - : lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_) - { - } - - ~const_strict_synchronizer() - { - } - - const T* operator->() const - { - return &value_; - } - - const T& operator*() const - { - return value_; - } - - }; - - /** - * - */ - struct strict_synchronizer : const_strict_synchronizer - { - protected: - friend class synchronized_value; - - explicit strict_synchronizer(synchronized_value& outer) : - const_strict_synchronizer(const_cast(outer)) - { - } - public: - BOOST_THREAD_MOVABLE_ONLY( strict_synchronizer ) - - strict_synchronizer(BOOST_THREAD_RV_REF(strict_synchronizer) other) - : const_strict_synchronizer(boost::move(static_cast(other))) - { - } - - ~strict_synchronizer() - { - } - - T* operator->() - { - return const_cast(&this->value_); - } - - T& operator*() - { - return const_cast(this->value_); - } - - }; /** * Essentially calling a method obj->foo(x, y, z) calls the method foo(x, y, z) inside a critical section as * long-lived as the call itself. */ - strict_synchronizer operator->() + strict_lock_ptr operator->() { - return BOOST_THREAD_MAKE_RV_REF(strict_synchronizer(*this)); + return BOOST_THREAD_MAKE_RV_REF((strict_lock_ptr(value_, mtx_))); } /** * If the synchronized_value object involved is const-qualified, then you'll only be able to call const methods * through operator->. So, for example, vec->push_back("xyz") won't work if vec were const-qualified. * The locking mechanism capitalizes on the assumption that const methods don't modify their underlying data. */ - const_strict_synchronizer operator->() const + const_strict_lock_ptr operator->() const { - return BOOST_THREAD_MAKE_RV_REF(const_strict_synchronizer(*this)); + return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr(value_, mtx_))); } /** @@ -288,83 +402,32 @@ namespace boost * assert(vec.back() == 42); * } */ - strict_synchronizer synchronize() + strict_lock_ptr synchronize() { - return BOOST_THREAD_MAKE_RV_REF(strict_synchronizer(*this)); + return BOOST_THREAD_MAKE_RV_REF((strict_lock_ptr(value_, mtx_))); } - const_strict_synchronizer synchronize() const + const_strict_lock_ptr synchronize() const { - return BOOST_THREAD_MAKE_RV_REF(const_strict_synchronizer(*this)); + return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr(value_, mtx_))); } - /** - * - */ - struct unique_synchronizer : unique_lock + unique_lock_ptr unique_synchronize() { - private: - //friend class synchronized_value; - typedef unique_lock base_type; + return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr(value_, mtx_))); + } + unique_lock_ptr unique_synchronize(defer_lock_t tag) + { + return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr(value_, mtx_, tag))); + } + const_unique_lock_ptr unique_synchronize() const + { + return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr(value_, mtx_))); + } + const_unique_lock_ptr unique_synchronize(defer_lock_t tag) const + { + return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr(value_, mtx_, tag))); + } - T& value_; - - public: - BOOST_THREAD_MOVABLE_ONLY(unique_synchronizer) - - explicit unique_synchronizer(synchronized_value& outer) - : base_type(outer.mtx_), value_(outer.value_) - { - } - unique_synchronizer(synchronized_value& outer, adopt_lock_t) - : base_type(outer.mtx_, adopt_lock), value_(outer.value_) - { - } - unique_synchronizer(synchronized_value& outer, defer_lock_t) - : base_type(outer.mtx_, defer_lock), value_(outer.value_) - { - } - unique_synchronizer(synchronized_value& outer, try_to_lock_t) - : base_type(outer.mtx_, try_to_lock), value_(outer.value_) - { - } - unique_synchronizer(BOOST_THREAD_RV_REF(unique_synchronizer) other) - : base_type(boost::move(other)),value_(BOOST_THREAD_RV(other).value_) - { - } - - ~unique_synchronizer() - { - } - - T* operator->() - { - if (this->owns_lock()) - return &value_; - else - return 0; - } - - const T* operator->() const - { - if (this->owns_lock()) - return &value_; - else - return 0; - } - - T& operator*() - { - BOOST_ASSERT (this->owns_lock()); - return value_; - } - - const T& operator*() const - { - BOOST_ASSERT (this->owns_lock()); - return value_; - } - - }; private: class deref_value diff --git a/src/future.cpp b/src/future.cpp index 33980f58..d04f791d 100755 --- a/src/future.cpp +++ b/src/future.cpp @@ -7,7 +7,7 @@ #ifndef BOOST_NO_EXCEPTIONS -#include +#include namespace boost { @@ -19,12 +19,12 @@ namespace boost public boost::system::error_category { public: - virtual const char* name() const; //BOOST_NOEXCEPT; + virtual const char* name() const BOOST_NOEXCEPT; virtual std::string message(int ev) const; }; const char* - future_error_category::name() const //BOOST_NOEXCEPT + future_error_category::name() const BOOST_NOEXCEPT { return "future"; } 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 639a7f48..ad26a991 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -228,7 +228,7 @@ rule thread-compile-fail ( sources : reqs * : name ) [ thread-run test_5542_2.cpp ] [ thread-run test_5542_3.cpp ] [ thread-run test_5891.cpp ] - [ thread-run test_6130.cpp ] + #[ thread-run test_6130.cpp ] #[ thread-run test_6170.cpp ] [ thread-run test_6174.cpp ] #[ thread-run test_7160.cpp ] @@ -480,7 +480,7 @@ rule thread-compile-fail ( sources : reqs * : name ) [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/default_pass.cpp : strict_lock__cons__default_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/owns_lock_pass.cpp : strict_lock__owns_lock_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/types_pass.cpp : strict_lock__types_p ] - #[ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp : make_strict_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp : make_strict_lock_p ] ; #explicit ts_nested_strict_lock ; @@ -491,7 +491,7 @@ rule thread-compile-fail ( sources : reqs * : name ) [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp : nested_strict_lock__cons__default_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp : nested_strict_lock__owns_lock_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp : nested_strict_lock__types_p ] - #[ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp : make_nested_strict_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp : make_nested_strict_lock_p ] ; @@ -662,11 +662,11 @@ 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 ] + #[ thread-run ../example/test_so.cpp ] + #[ thread-run ../example/test_so2.cpp ] + #[ 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(); diff --git a/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp b/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp index 134103d8..9c15d0e3 100644 --- a/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp +++ b/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp @@ -99,7 +99,14 @@ int main() { boost::packaged_task p(A(5)); boost::future f = p.get_future(); - // BUG boost::thread(func0, boost::move(p)).detach(); + // fixme BUG boost::thread(func0, boost::move(p)).detach(); + boost::thread(func0, &p).detach(); + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task p2(A(5)); + boost::future f = p2.get_future(); + boost::packaged_task p = boost::move(p2); boost::thread(func0, &p).detach(); BOOST_TEST(f.get() == 105.0); } @@ -118,6 +125,21 @@ int main() BOOST_TEST(e.data == 6); } } + { + boost::packaged_task p2(A(5)); + boost::future f = p2.get_future(); + boost::packaged_task p = boost::move(p2); + boost::thread(func1, &p).detach(); + try + { + f.get(); + BOOST_TEST(false); + } + catch (const E& e) + { + BOOST_TEST(e.data == 6); + } + } { boost::packaged_task p(A(5)); boost::future f = p.get_future(); @@ -126,11 +148,24 @@ int main() BOOST_TEST(f.get() == 105.0); } { - boost::packaged_task p; + boost::packaged_task p2(A(5)); + boost::future f = p2.get_future(); + boost::packaged_task p = boost::move(p2); + boost::thread(func2, &p).detach(); + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task p(A(5)); //boost::thread t(func3, boost::move(p)); boost::thread t(func3, &p); t.join(); } + { + boost::packaged_task p2(A(5)); + boost::packaged_task p = boost::move(p2); + boost::thread t(func3, &p); + t.join(); + } return boost::report_errors(); } diff --git a/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp b/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp index 7fd7a4f5..0c090f0b 100644 --- a/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp +++ b/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp @@ -73,6 +73,27 @@ int main() BOOST_TEST(false); } } + { + typedef int T; + boost::promise p2; + boost::future f = p2.get_future(); + //boost::thread(func, boost::move(p)).detach(); + p = boost::move(p2); + boost::thread(func).detach(); + try + { + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap i) + { + BOOST_TEST(i.value == 3); + } + catch (...) + { + BOOST_TEST(false); + } + } return boost::report_errors(); } diff --git a/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp b/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp index a4abb431..688e8da3 100644 --- a/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp +++ b/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp @@ -40,6 +40,13 @@ int main() boost::thread(func).detach(); BOOST_TEST(f.get() == 5); } + { + boost::promise p2; + boost::future f = p2.get_future(); + p = boost::move(p2); + boost::thread(func).detach(); + BOOST_TEST(f.get() == 5); + } return boost::report_errors(); } diff --git a/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp b/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp index b434652a..4d9cb276 100644 --- a/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp +++ b/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp @@ -19,8 +19,11 @@ // void promise::set_value_at_thread_exit(); #define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID #include +#include #include int i = 0; @@ -35,7 +38,7 @@ void func() void func2(boost::promise p2) { p2.set_value_at_thread_exit(); - i = 1; + i = 2; } int main() @@ -57,20 +60,39 @@ int main() BOOST_TEST(false); } + try + { + boost::promise p2; + boost::future f = p2.get_future(); + p = boost::move(p2); + boost::thread(func).detach(); + f.get(); + BOOST_TEST(i == 1); + + } + catch(std::exception ex) + { + std::cout << __FILE__ << ":" << __LINE__ << " " << ex.what() << std::endl; + BOOST_TEST(false); + } + catch(...) + { + BOOST_TEST(false); + } // BUG when moving promise. fixme // try // { -// std::cout << __FILE__ << ":" << __LINE__ < p2; // BUG -// std::cout << __FILE__ << ":" << __LINE__ < f = p2.get_future(); -// std::cout << __FILE__ << ":" << __LINE__ < lk0(m0); - boost::nested_strict_lock lk1 = lk0; + boost::nested_strict_lock > lk0(m0); + boost::nested_strict_lock > lk1 = lk0; } #include "../../../../remove_error_code_unused_warning.hpp" diff --git a/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp b/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp index 00b8c93c..834d52d2 100644 --- a/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp +++ b/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp @@ -30,7 +30,7 @@ typedef boost::chrono::nanoseconds ns; boost::mutex m; -#if ! defined(BOOST_NO_CXX11_AUTO) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST && BOOST_THREAD_USES_CHRONO +#if ! defined(BOOST_NO_CXX11_AUTO) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST && defined BOOST_THREAD_USES_CHRONO void f() { @@ -38,7 +38,7 @@ void f() time_point t1; boost::unique_lock lg(m); { - const auto&& nlg = boost::make_strict_lock(lg); (void)nlg; + const auto&& nlg = boost::make_nested_strict_lock(lg); (void)nlg; t1 = Clock::now(); BOOST_THREAD_TRACE; } diff --git a/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp b/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp index d3261be2..1f4af5ee 100644 --- a/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp +++ b/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp @@ -29,7 +29,7 @@ typedef boost::chrono::nanoseconds ns; boost::mutex m; -#if ! defined(BOOST_NO_CXX11_AUTO) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST && BOOST_THREAD_USES_CHRONO +#if ! defined(BOOST_NO_CXX11_AUTO) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST && defined BOOST_THREAD_USES_CHRONO void f() {