diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-06 10:33:54 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-06 10:36:09 +0900 |
commit | d9ec475d945d3035377a0d89ed42e382d8988891 (patch) | |
tree | 34aff2cee4b209906243ab5499d61f3edee2982f /boost/thread | |
parent | 71d216b90256936a9638f325af9bc69d720e75de (diff) | |
download | boost-d9ec475d945d3035377a0d89ed42e382d8988891.tar.gz boost-d9ec475d945d3035377a0d89ed42e382d8988891.tar.bz2 boost-d9ec475d945d3035377a0d89ed42e382d8988891.zip |
Imported Upstream version 1.60.0
Change-Id: Ie709530d6d5841088ceaba025cbe175a4ef43050
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost/thread')
30 files changed, 1167 insertions, 828 deletions
diff --git a/boost/thread/concurrent_queues/sync_queue.hpp b/boost/thread/concurrent_queues/sync_queue.hpp index 7183c9cad8..1dbbef05dd 100644 --- a/boost/thread/concurrent_queues/sync_queue.hpp +++ b/boost/thread/concurrent_queues/sync_queue.hpp @@ -10,6 +10,7 @@ // See http://www.boost.org/libs/thread for documentation. // ////////////////////////////////////////////////////////////////////////////// +#include <iostream> #include <boost/thread/detail/config.hpp> #include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp> @@ -150,13 +151,19 @@ namespace concurrent template <class ValueType, class Container> queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk) { + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; if (super::empty(lk)) { + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; if (super::closed(lk)) return queue_op_status::closed; } + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; bool has_been_closed = super::wait_until_not_empty_or_closed(lk); + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; if (has_been_closed) return queue_op_status::closed; + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; pull(elem, lk); + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; return queue_op_status::success; } diff --git a/boost/thread/concurrent_queues/sync_timed_queue.hpp b/boost/thread/concurrent_queues/sync_timed_queue.hpp index 8f24f43ecd..36223d8715 100644 --- a/boost/thread/concurrent_queues/sync_timed_queue.hpp +++ b/boost/thread/concurrent_queues/sync_timed_queue.hpp @@ -235,7 +235,7 @@ namespace detail if (super::closed(lk)) return true; super::not_empty_.wait(lk); } - return false; + //return false; } /////////////////////////// diff --git a/boost/thread/csbl/devector.hpp b/boost/thread/csbl/devector.hpp index c11ad29ba1..c2bc0bbe99 100644 --- a/boost/thread/csbl/devector.hpp +++ b/boost/thread/csbl/devector.hpp @@ -21,8 +21,8 @@ namespace boost template <class T> class devector { - typedef vector<T> vector_type; - vector<T> data_; + typedef csbl::vector<T> vector_type; + vector_type data_; std::size_t front_index_; BOOST_COPYABLE_AND_MOVABLE(devector) @@ -58,7 +58,9 @@ namespace boost } devector& operator=(BOOST_RV_REF(devector) x) - BOOST_NOEXCEPT_IF(vector<T>::allocator_traits_type::propagate_on_container_move_assignment::value) +#if defined BOOST_THREAD_USES_BOOST_VECTOR + BOOST_NOEXCEPT_IF(vector_type::allocator_traits_type::propagate_on_container_move_assignment::value) +#endif { data_ = boost::move(x.data_); front_index_ = x.front_index_; diff --git a/boost/thread/detail/invoker.hpp b/boost/thread/detail/invoker.hpp index 7ab3b33990..9f38e9798d 100644 --- a/boost/thread/detail/invoker.hpp +++ b/boost/thread/detail/invoker.hpp @@ -72,13 +72,21 @@ namespace boost BOOST_SYMBOL_VISIBLE invoker& operator=(BOOST_THREAD_RV_REF(invoker) f) { - f_ = boost::move(BOOST_THREAD_RV(f).f_); + if (this != &f) + { + f_ = boost::move(BOOST_THREAD_RV(f).f_); + } + return *this; } BOOST_SYMBOL_VISIBLE invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f) { - f_ = f.f_; + if (this != &f) + { + f_ = f.f_; + } + return *this; } result_type operator()() @@ -91,7 +99,7 @@ namespace boost result_type execute(tuple_indices<Indices...>) { - return invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...); + return detail::invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...); } }; @@ -128,7 +136,7 @@ namespace boost result_type execute(tuple_indices<Indices...>) { - return invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...); + return detail::invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...); } }; //BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END @@ -182,7 +190,7 @@ namespace boost {} \ \ result_type operator()() { \ - return invoke(boost::move(fp_) \ + return detail::invoke(boost::move(fp_) \ BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \ ); \ } \ @@ -307,7 +315,7 @@ namespace boost result_type operator()() { - return invoke(boost::move(fp_) + return detail::invoke(boost::move(fp_) , boost::move(v0_) , boost::move(v1_) , boost::move(v2_) @@ -373,7 +381,7 @@ namespace boost result_type operator()() { - return invoke(boost::move(fp_) + return detail::invoke(boost::move(fp_) , boost::move(v0_) , boost::move(v1_) , boost::move(v2_) @@ -434,7 +442,7 @@ namespace boost result_type operator()() { - return invoke(boost::move(fp_) + return detail::invoke(boost::move(fp_) , boost::move(v0_) , boost::move(v1_) , boost::move(v2_) @@ -490,7 +498,7 @@ namespace boost result_type operator()() { - return invoke(boost::move(fp_) + return detail::invoke(boost::move(fp_) , boost::move(v0_) , boost::move(v1_) , boost::move(v2_) @@ -541,7 +549,7 @@ namespace boost result_type operator()() { - return invoke(boost::move(fp_) + return detail::invoke(boost::move(fp_) , boost::move(v0_) , boost::move(v1_) , boost::move(v2_) @@ -587,7 +595,7 @@ namespace boost result_type operator()() { - return invoke(boost::move(fp_) + return detail::invoke(boost::move(fp_) , boost::move(v0_) , boost::move(v1_) , boost::move(v2_) @@ -628,7 +636,7 @@ namespace boost result_type operator()() { - return invoke(boost::move(fp_) + return detail::invoke(boost::move(fp_) , boost::move(v0_) , boost::move(v1_) , boost::move(v2_) @@ -664,7 +672,7 @@ namespace boost result_type operator()() { - return invoke(boost::move(fp_) + return detail::invoke(boost::move(fp_) , boost::move(v0_) , boost::move(v1_) ); @@ -695,7 +703,7 @@ namespace boost result_type operator()() { - return invoke(boost::move(fp_) + return detail::invoke(boost::move(fp_) , boost::move(v0_) ); } diff --git a/boost/thread/detail/move.hpp b/boost/thread/detail/move.hpp index 611557093e..26e4f9dc6d 100644 --- a/boost/thread/detail/move.hpp +++ b/boost/thread/detail/move.hpp @@ -94,6 +94,11 @@ namespace boost template <typename T> \ struct enable_move_utility_emulation_dummy_specialization< +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ + namespace detail { \ + template <typename T1, typename T2> \ + struct enable_move_utility_emulation_dummy_specialization< + #define BOOST_THREAD_DCL_MOVABLE_END > \ : integral_constant<bool, false> \ {}; \ @@ -115,6 +120,11 @@ namespace boost template <typename T> \ struct enable_move_utility_emulation_dummy_specialization< +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ + namespace detail { \ + template <typename T1, typename T2> \ + struct enable_move_utility_emulation_dummy_specialization< + #define BOOST_THREAD_DCL_MOVABLE_END > \ : integral_constant<bool, false> \ {}; \ @@ -136,6 +146,11 @@ namespace boost template <typename T> \ struct enable_move_utility_emulation_dummy_specialization< +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ + namespace detail { \ + template <typename T1, typename T2> \ + struct enable_move_utility_emulation_dummy_specialization< + #define BOOST_THREAD_DCL_MOVABLE_END > \ : integral_constant<bool, false> \ {}; \ @@ -161,6 +176,10 @@ struct enable_move_utility_emulation< TYPE > \ template <typename T> \ struct enable_move_utility_emulation< +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ +template <typename T1, typename T2> \ +struct enable_move_utility_emulation< + #define BOOST_THREAD_DCL_MOVABLE_END > \ { \ static const bool value = false; \ diff --git a/boost/thread/detail/nullary_function.hpp b/boost/thread/detail/nullary_function.hpp index a0e9fd456a..b3989cf682 100644 --- a/boost/thread/detail/nullary_function.hpp +++ b/boost/thread/detail/nullary_function.hpp @@ -228,7 +228,7 @@ namespace boost }; } - //BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END + BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END } #endif // header diff --git a/boost/thread/detail/thread.hpp b/boost/thread/detail/thread.hpp index b80eacfa1b..9e7e8b8f5e 100644 --- a/boost/thread/detail/thread.hpp +++ b/boost/thread/detail/thread.hpp @@ -72,7 +72,7 @@ namespace boost void run2(tuple_indices<Indices...>) { - invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...); + detail::invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...); } void run() { @@ -173,7 +173,6 @@ namespace boost private: bool start_thread_noexcept(); bool start_thread_noexcept(const attributes& attr); - //public: void start_thread() { if (!start_thread_noexcept()) @@ -355,6 +354,8 @@ namespace boost #if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE if (joinable()) std::terminate(); +#else + detach(); #endif thread_info=BOOST_THREAD_RV(other).thread_info; BOOST_THREAD_RV(other).thread_info.reset(); @@ -485,9 +486,9 @@ namespace boost bool try_join_until(const chrono::time_point<Clock, Duration>& t) { using namespace chrono; - system_clock::time_point s_now = system_clock::now(); bool joined= false; do { + system_clock::time_point s_now = system_clock::now(); typename Clock::duration d = ceil<nanoseconds>(t-Clock::now()); if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached joined = try_join_until(s_now + d); diff --git a/boost/thread/detail/thread_group.hpp b/boost/thread/detail/thread_group.hpp index 69ce991e78..4105c73468 100644 --- a/boost/thread/detail/thread_group.hpp +++ b/boost/thread/detail/thread_group.hpp @@ -6,6 +6,7 @@ // (C) Copyright 2007-9 Anthony Williams #include <list> +#include <boost/thread/csbl/memory/unique_ptr.hpp> #include <boost/thread/shared_mutex.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/lock_guard.hpp> @@ -75,7 +76,7 @@ namespace boost thread* create_thread(F threadfunc) { boost::lock_guard<shared_mutex> guard(m); - std::auto_ptr<thread> new_thread(new thread(threadfunc)); + boost::csbl::unique_ptr<thread> new_thread(new thread(threadfunc)); threads.push_back(new_thread.get()); return new_thread.release(); } diff --git a/boost/thread/executors/basic_thread_pool.hpp b/boost/thread/executors/basic_thread_pool.hpp index 64ba1e90e0..e0d4df2c76 100644 --- a/boost/thread/executors/basic_thread_pool.hpp +++ b/boost/thread/executors/basic_thread_pool.hpp @@ -13,7 +13,7 @@ #include <boost/thread/detail/config.hpp> #include <boost/thread/detail/delete.hpp> #include <boost/thread/detail/move.hpp> -#include <boost/thread/scoped_thread.hpp> +#include <boost/thread/thread.hpp> #include <boost/thread/concurrent_queues/sync_queue.hpp> #include <boost/thread/executors/work.hpp> #include <boost/thread/csbl/vector.hpp> @@ -30,15 +30,14 @@ namespace executors /// type-erasure to store the works to do typedef executors::work work; private: - /// the kind of stored threads are scoped threads to ensure that the threads are joined. + typedef thread thread_t; /// A move aware vector type - typedef scoped_thread<> thread_t; typedef csbl::vector<thread_t> thread_vector; - /// the thread safe work queue - concurrent::sync_queue<work > work_queue; /// A move aware vector thread_vector threads; + /// the thread safe work queue + concurrent::sync_queue<work > work_queue; public: /** @@ -61,7 +60,7 @@ namespace executors catch (...) { std::terminate(); - return false; + //return false; } } /** @@ -88,7 +87,9 @@ namespace executors { work task; queue_op_status st = work_queue.wait_pull(task); - if (st == queue_op_status::closed) return; + if (st == queue_op_status::closed) { + return; + } task(); } } @@ -222,7 +223,8 @@ namespace executors { // signal to all the worker threads that there will be no more submissions. close(); - // joins all the threads as the threads were scoped_threads + // joins all the threads before destroying the thread pool resources (e.g. the queue). + join(); } /** @@ -264,23 +266,28 @@ namespace executors * \b Throws: \c sync_queue_is_closed if the thread pool is closed. * Whatever exception that can be throw while storing the closure. */ + void submit(BOOST_THREAD_RV_REF(work) closure) { + work_queue.push(boost::move(closure)); + } #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template <typename Closure> void submit(Closure & closure) { - work_queue.push(work(closure)); + submit(work(closure)); } #endif void submit(void (*closure)()) { - work_queue.push(work(closure)); + submit(work(closure)); } template <typename Closure> - void submit(BOOST_THREAD_RV_REF(Closure) closure) + void submit(BOOST_THREAD_FWD_REF(Closure) closure) { - work_queue.push(work(boost::forward<Closure>(closure))); + //submit(work(boost::forward<Closure>(closure))); + work w((boost::forward<Closure>(closure))); + submit(boost::move(w)); } /** diff --git a/boost/thread/executors/executor.hpp b/boost/thread/executors/executor.hpp index 1075bce733..96198201f0 100644 --- a/boost/thread/executors/executor.hpp +++ b/boost/thread/executors/executor.hpp @@ -99,9 +99,10 @@ namespace boost } template <typename Closure> - void submit(BOOST_THREAD_RV_REF(Closure) closure) + void submit(BOOST_THREAD_FWD_REF(Closure) closure) { - work w = boost::move(closure); + //submit(work(boost::forward<Closure>(closure))); + work w((boost::forward<Closure>(closure))); submit(boost::move(w)); } diff --git a/boost/thread/executors/executor_adaptor.hpp b/boost/thread/executors/executor_adaptor.hpp index ebe4e3476c..ca1a35f2d9 100644 --- a/boost/thread/executors/executor_adaptor.hpp +++ b/boost/thread/executors/executor_adaptor.hpp @@ -98,9 +98,6 @@ namespace executors void submit(BOOST_THREAD_RV_REF(work) closure) { return ex.submit(boost::move(closure)); } -// void submit(work & closure) { -// return ex.submit(closure); -// } #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template <typename Closure> @@ -115,9 +112,11 @@ namespace executors } template <typename Closure> - void submit(BOOST_THREAD_RV_REF(Closure) closure) + void submit(BOOST_THREAD_FWD_REF(Closure) closure) { - submit(work(boost::forward<Closure>(closure))); + //submit(work(boost::forward<Closure>(closure))); + work w((boost::forward<Closure>(closure))); + submit(boost::move(w)); } /** diff --git a/boost/thread/executors/generic_executor_ref.hpp b/boost/thread/executors/generic_executor_ref.hpp index 57609c91f0..de270bcfed 100644 --- a/boost/thread/executors/generic_executor_ref.hpp +++ b/boost/thread/executors/generic_executor_ref.hpp @@ -121,11 +121,6 @@ namespace boost */ bool closed() { return ex->closed(); } - void submit(BOOST_THREAD_RV_REF(work) closure) - { - ex->submit(boost::forward<work>(closure)); - } - /** * \par Requires * \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible. @@ -142,24 +137,31 @@ namespace boost * Whatever exception that can be throw while storing the closure. */ + void submit(BOOST_THREAD_RV_REF(work) closure) + { + ex->submit(boost::move(closure)); + } + #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template <typename Closure> void submit(Closure & closure) { - work w ((closure)); - submit(boost::move(w)); + //work w ((closure)); + //submit(boost::move(w)); + submit(work(closure)); } #endif void submit(void (*closure)()) { work w ((closure)); submit(boost::move(w)); + //submit(work(closure)); } template <typename Closure> - void submit(BOOST_THREAD_RV_REF(Closure) closure) + void submit(BOOST_THREAD_FWD_REF(Closure) closure) { - work w = boost::move(closure); + work w((boost::forward<Closure>(closure))); submit(boost::move(w)); } diff --git a/boost/thread/executors/loop_executor.hpp b/boost/thread/executors/loop_executor.hpp index e9eadadf9e..b08ff76f57 100644 --- a/boost/thread/executors/loop_executor.hpp +++ b/boost/thread/executors/loop_executor.hpp @@ -54,7 +54,7 @@ namespace executors catch (...) { std::terminate(); - return false; + //return false; } } private: @@ -138,23 +138,29 @@ namespace executors * \b Throws: \c sync_queue_is_closed if the thread pool is closed. * Whatever exception that can be throw while storing the closure. */ + void submit(BOOST_THREAD_RV_REF(work) closure) { + work_queue.push(boost::move(closure)); + } #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template <typename Closure> void submit(Closure & closure) { - work_queue.push(work(closure)); - } + submit(work(closure)); + } #endif + void submit(void (*closure)()) { - work_queue.push(work(closure)); + submit(work(closure)); } template <typename Closure> - void submit(BOOST_THREAD_RV_REF(Closure) closure) + void submit(BOOST_THREAD_FWD_REF(Closure) closure) { - work_queue.push(work(boost::forward<Closure>(closure))); + //work_queue.push(work(boost::forward<Closure>(closure))); + work w((boost::forward<Closure>(closure))); + submit(boost::move(w)); } /** diff --git a/boost/thread/executors/serial_executor.hpp b/boost/thread/executors/serial_executor.hpp index 6f4266668f..6d7ed9be97 100644 --- a/boost/thread/executors/serial_executor.hpp +++ b/boost/thread/executors/serial_executor.hpp @@ -82,7 +82,7 @@ namespace executors catch (...) { std::terminate(); - return false; + //return false; } } private: @@ -165,23 +165,28 @@ namespace executors * \b Throws: \c sync_queue_is_closed if the thread pool is closed. * Whatever exception that can be throw while storing the closure. */ + void submit(BOOST_THREAD_RV_REF(work) closure) + { + work_queue.push(boost::move(closure)); + } #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template <typename Closure> void submit(Closure & closure) { - work_queue.push(work(closure)); + submit(work(closure)); } #endif void submit(void (*closure)()) { - work_queue.push(work(closure)); + submit(work(closure)); } template <typename Closure> - void submit(BOOST_THREAD_RV_REF(Closure) closure) + void submit(BOOST_THREAD_FWD_REF(Closure) closure) { - work_queue.push(work(boost::forward<Closure>(closure))); + work w((boost::forward<Closure>(closure))); + submit(boost::move(w)); } /** diff --git a/boost/thread/executors/serial_executor_cont.hpp b/boost/thread/executors/serial_executor_cont.hpp index 1c4cc14aad..91087890be 100644 --- a/boost/thread/executors/serial_executor_cont.hpp +++ b/boost/thread/executors/serial_executor_cont.hpp @@ -153,7 +153,7 @@ namespace executors } template <typename Closure> - void submit(BOOST_THREAD_RV_REF(Closure) closure) + void submit(BOOST_THREAD_FWD_REF(Closure) closure) { lock_guard<mutex> lk(mtx_); if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); diff --git a/boost/thread/executors/thread_executor.hpp b/boost/thread/executors/thread_executor.hpp index a8cd5c212f..c9f49a7b62 100644 --- a/boost/thread/executors/thread_executor.hpp +++ b/boost/thread/executors/thread_executor.hpp @@ -17,6 +17,7 @@ #include <boost/thread/thread_only.hpp> #include <boost/thread/scoped_thread.hpp> #include <boost/thread/csbl/vector.hpp> +#include <boost/thread/concurrent_queues/queue_op_status.hpp> #include <boost/config/abi_prefix.hpp> diff --git a/boost/thread/experimental/parallel/v2/task_region.hpp b/boost/thread/experimental/parallel/v2/task_region.hpp index 3a278c500f..e4a5833115 100755 --- a/boost/thread/experimental/parallel/v2/task_region.hpp +++ b/boost/thread/experimental/parallel/v2/task_region.hpp @@ -53,7 +53,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2) throw; } #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED - catch (task_canceled_exception& ex) + catch (task_canceled_exception&) { } #endif diff --git a/boost/thread/future.hpp b/boost/thread/future.hpp index 28239c4aa3..0ec484c2bf 100644 --- a/boost/thread/future.hpp +++ b/boost/thread/future.hpp @@ -13,6 +13,9 @@ // boost::thread::future requires exception handling // due to boost::exception::exception_ptr dependency +//#define BOOST_THREAD_CONTINUATION_SYNC +#define BOOST_THREAD_FUTURE_BLOCKING + #ifndef BOOST_NO_EXCEPTIONS #include <boost/thread/condition_variable.hpp> @@ -33,6 +36,8 @@ #include <boost/thread/mutex.hpp> #include <boost/thread/thread_only.hpp> #include <boost/thread/thread_time.hpp> +#include <boost/thread/executor.hpp> +#include <boost/thread/executors/generic_executor_ref.hpp> #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL #include <boost/optional.hpp> @@ -53,6 +58,7 @@ #include <boost/next_prior.hpp> #include <boost/scoped_array.hpp> #include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> #include <boost/throw_exception.hpp> #include <boost/type_traits/conditional.hpp> #include <boost/type_traits/decay.hpp> @@ -88,8 +94,28 @@ namespace boost { + template <class T> + shared_ptr<T> static_shared_from_this(T* that) + { + return static_pointer_cast<T>(that->shared_from_this()); + } + template <class T> + shared_ptr<T const> static_shared_from_this(T const* that) + { + return static_pointer_cast<T const>(that->shared_from_this()); + } + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS +#else + namespace executors { + class executor; + } +#endif + typedef shared_ptr<executor> executor_ptr_type; + namespace detail { + struct relocker { boost::unique_lock<boost::mutex>& lock_; @@ -127,7 +153,6 @@ namespace boost bool is_valid_; bool is_deferred_; bool is_constructed; - std::size_t cnt_; launch policy_; mutable boost::mutex mutex; boost::condition_variable waiters; @@ -135,9 +160,10 @@ namespace boost boost::function<void()> callback; // This declaration should be only included conditionally, but is included to maintain the same layout. continuations_type continuations; + executor_ptr_type ex; // This declaration should be only included conditionally, but is included to maintain the same layout. - virtual void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base>) + virtual void launch_continuation() { } @@ -146,16 +172,46 @@ namespace boost is_valid_(true), is_deferred_(false), is_constructed(false), - cnt_(0), policy_(launch::none), - continuations() + continuations(), + ex() + {} + + shared_state_base(exceptional_ptr const& ex): + exception(ex.ptr_), + done(true), + is_valid_(true), + is_deferred_(false), + is_constructed(false), + policy_(launch::none), + continuations(), + ex() {} + + virtual ~shared_state_base() { - BOOST_ASSERT(cnt_==0); } - virtual void block_if_needed(boost::unique_lock<boost::mutex>&) - {} + executor_ptr_type get_executor() + { + return ex; + } + + void set_executor_policy(executor_ptr_type aex) + { + set_executor(); + ex = aex; + } + void set_executor_policy(executor_ptr_type aex, boost::lock_guard<boost::mutex>&) + { + set_executor(); + ex = aex; + } + void set_executor_policy(executor_ptr_type aex, boost::unique_lock<boost::mutex>&) + { + set_executor(); + ex = aex; + } bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; } bool valid() { @@ -173,16 +229,6 @@ namespace boost validate(lk); } - void inc(boost::unique_lock<boost::mutex>&) { ++cnt_; } - void inc() { boost::unique_lock<boost::mutex> lk(this->mutex); inc(lk); } - - void dec(boost::unique_lock<boost::mutex>& lk) { - if (--cnt_ == 0) { - block_if_needed(lk); - } - } - void dec() { boost::unique_lock<boost::mutex> lk(this->mutex); dec(lk); } - void set_deferred() { is_deferred_ = true; @@ -199,6 +245,10 @@ namespace boost is_deferred_ = false; policy_ = launch::executor; } +#else + void set_executor() + { + } #endif notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv) { @@ -221,8 +271,7 @@ namespace boost continuations.clear(); relocker rlk(lock); for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { - boost::unique_lock<boost::mutex> cont_lock((*it)->mutex); - (*it)->launch_continuation(cont_lock, *it); + (*it)->launch_continuation(); } } } @@ -407,7 +456,7 @@ namespace boost return policy_; } - future_state::state get_state(boost::unique_lock<boost::mutex>& lk) const + future_state::state get_state(boost::unique_lock<boost::mutex>&) const { if(!done) { @@ -483,9 +532,14 @@ namespace boost shared_state(): result() {} + shared_state(exceptional_ptr const& ex): + detail::shared_state_base(ex), result() + {} + ~shared_state() - {} + { + } void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) { @@ -624,6 +678,10 @@ namespace boost result(0) {} + shared_state(exceptional_ptr const& ex): + detail::shared_state_base(ex), result(0) + {} + ~shared_state() { } @@ -687,6 +745,10 @@ namespace boost shared_state() {} + shared_state(exceptional_ptr const& ex): + detail::shared_state_base(ex) + {} + void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock) { mark_finished_internal(lock); @@ -741,33 +803,39 @@ namespace boost { typedef shared_state<Rp> base_type; protected: +#ifdef BOOST_THREAD_FUTURE_BLOCKING boost::thread thr_; void join() { + if (this_thread::get_id() == thr_.get_id()) + { + thr_.detach(); + return; + } if (thr_.joinable()) thr_.join(); } +#endif public: future_async_shared_state_base() { this->set_async(); } - virtual void block_if_needed(boost::unique_lock<boost::mutex>& lk) - { - this->wait(lk, false); - } - ~future_async_shared_state_base() { +#ifdef BOOST_THREAD_FUTURE_BLOCKING join(); +#endif } virtual void wait(boost::unique_lock<boost::mutex>& lk, bool rethrow) { +#ifdef BOOST_THREAD_FUTURE_BLOCKING { relocker rlk(lk); join(); } +#endif this->base_type::wait(lk, rethrow); } }; @@ -784,13 +852,15 @@ namespace boost void init(BOOST_THREAD_FWD_REF(Fp) f) { - shared_ptr<boost::detail::shared_state_base> that = this->shared_from_this(); - this->thr_ = thread(&future_async_shared_state::run, that, boost::forward<Fp>(f)); +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f)); +#else + thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f)).detach(); +#endif } - static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f) + static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f) { - future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get()); try { that->mark_finished_with_result(f()); @@ -807,12 +877,15 @@ namespace boost { void init(BOOST_THREAD_FWD_REF(Fp) f) { - this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f)); +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)); +#else + thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach(); +#endif } - static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f) + static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f) { - future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get()); try { f(); @@ -830,12 +903,15 @@ namespace boost { void init(BOOST_THREAD_FWD_REF(Fp) f) { - this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f)); +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)); +#else + thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach(); +#endif } - static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f) + static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f) { - future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get()); try { that->mark_finished_with_result(f()); @@ -934,9 +1010,10 @@ namespace boost class future_waiter { - struct registered_waiter; + public: typedef std::vector<int>::size_type count_type; - + private: + struct registered_waiter; struct registered_waiter { boost::shared_ptr<detail::shared_state_base> future_; @@ -1075,7 +1152,7 @@ namespace boost #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES template<typename F1,typename F2> - typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2) + typename boost::enable_if<is_future_type<F1>,typename detail::future_waiter::count_type>::type wait_for_any(F1& f1,F2& f2) { detail::future_waiter waiter; waiter.add(f1); @@ -1084,7 +1161,7 @@ namespace boost } template<typename F1,typename F2,typename F3> - unsigned wait_for_any(F1& f1,F2& f2,F3& f3) + typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3) { detail::future_waiter waiter; waiter.add(f1); @@ -1094,7 +1171,7 @@ namespace boost } template<typename F1,typename F2,typename F3,typename F4> - unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4) + typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4) { detail::future_waiter waiter; waiter.add(f1); @@ -1105,7 +1182,7 @@ namespace boost } template<typename F1,typename F2,typename F3,typename F4,typename F5> - unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) + typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) { detail::future_waiter waiter; waiter.add(f1); @@ -1117,7 +1194,8 @@ namespace boost } #else template<typename F1, typename... Fs> - typename boost::enable_if<is_future_type<F1>, unsigned>::type wait_for_any(F1& f1, Fs&... fs) + typename boost::enable_if<is_future_type<F1>, typename detail::future_waiter::count_type>::type + wait_for_any(F1& f1, Fs&... fs) { detail::future_waiter waiter; waiter.add(f1, fs...); @@ -1150,16 +1228,7 @@ namespace boost static //BOOST_CONSTEXPR future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) { - promise<R> p; - p.set_exception(ex.ptr_); - return p.get_future().future_; - } - - void set_exceptional_if_invalid() { - if (valid()) return; - promise<R> p; - p.set_exception(future_uninitialized()); - future_ = p.get_future().future_; + return future_ptr(new detail::shared_state<R>(ex)); } future_ptr future_; @@ -1167,7 +1236,6 @@ namespace boost basic_future(future_ptr a_future): future_(a_future) { - if (a_future) a_future->inc(); } public: @@ -1181,11 +1249,9 @@ namespace boost basic_future(exceptional_ptr const& ex) : future_(make_exceptional_future_ptr(ex)) { - future_->inc(); } ~basic_future() { - if (future_) future_->dec(); } basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT: @@ -1195,9 +1261,6 @@ namespace boost } basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT { - if (this->future_) { - this->future_->dec(); - } future_=BOOST_THREAD_RV(other).future_; BOOST_THREAD_RV(other).future_.reset(); return *this; @@ -1249,6 +1312,15 @@ namespace boost else return launch(launch::none); } + launch launch_policy() const + { + if ( future_ ) { + boost::unique_lock<boost::mutex> lk(this->future_->mutex); + return future_->launch_policy(lk); + } + else return launch(launch::none); + } + exception_ptr get_exception_ptr() { return future_ @@ -1538,7 +1610,8 @@ namespace boost BOOST_THREAD_FUTURE(exceptional_ptr const& ex): base_type(ex) {} - ~BOOST_THREAD_FUTURE() {} + ~BOOST_THREAD_FUTURE() { + } BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) @@ -1795,7 +1868,8 @@ namespace boost BOOST_THREAD_FUTURE(exceptional_ptr const& ex): base_type(ex) {} - ~BOOST_THREAD_FUTURE() {} + ~BOOST_THREAD_FUTURE() { + } BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) @@ -1964,12 +2038,6 @@ namespace boost shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other) { - if (other.future_) { - other.future_->inc(); - } - if (this->future_) { - this->future_->dec(); - } this->future_ = other.future_; return *this; } @@ -2129,6 +2197,18 @@ namespace boost std::swap(future_obtained,other.future_obtained); } +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + void set_executor(executor_ptr_type aex) + { + lazy_init(); + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + boost::lock_guard<boost::mutex> lk(future_->mutex); + future_->set_executor_policy(aex, lk); + } +#endif // Result retrieval BOOST_THREAD_FUTURE<R> get_future() { @@ -2867,7 +2947,7 @@ namespace boost private: task_shared_state(task_shared_state&); #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) - typedef R (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... ); + typedef R (*CallableType)(ArgTypes ... ); #else typedef R (*CallableType)(); #endif @@ -3098,7 +3178,7 @@ namespace boost private: task_shared_state(task_shared_state&); #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) - typedef void (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes)...); + typedef void (*CallableType)(ArgTypes...); #else typedef void (*CallableType)(); #endif @@ -3389,9 +3469,18 @@ namespace boost return *this; } +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + void set_executor(executor_ptr_type aex) + { + if (!valid()) + boost::throw_exception(task_moved()); + boost::lock_guard<boost::mutex> lk(task->mutex); + task->set_executor_policy(aex, lk); + } +#endif void reset() { if (!valid()) - throw future_error(system::make_error_code(future_errc::no_state)); + boost::throw_exception(future_error(system::make_error_code(future_errc::no_state))); // As if *this = packaged_task(task->callable()); @@ -3421,7 +3510,7 @@ namespace boost // execution #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) - void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args) { + void operator()(ArgTypes... args) { if(!task) { boost::throw_exception(task_moved()); } @@ -3533,8 +3622,8 @@ namespace detail )); } else { std::terminate(); - BOOST_THREAD_FUTURE<R> ret; - return ::boost::move(ret); + //BOOST_THREAD_FUTURE<R> ret; + //return ::boost::move(ret); } } @@ -3557,12 +3646,12 @@ namespace detail return ::boost::move(ret); } else if (underlying_cast<int>(policy) & int(launch::deferred)) { std::terminate(); - BOOST_THREAD_FUTURE<R> ret; - return ::boost::move(ret); + //BOOST_THREAD_FUTURE<R> ret; + //return ::boost::move(ret); } else { std::terminate(); - BOOST_THREAD_FUTURE<R> ret; - return ::boost::move(ret); + //BOOST_THREAD_FUTURE<R> ret; + //return ::boost::move(ret); } } #endif @@ -3575,9 +3664,6 @@ namespace detail typename decay<ArgTypes>::type... )>::type> async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { - typedef typename boost::result_of<typename decay<F>::type( - typename decay<ArgTypes>::type... - )>::type R; typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; typedef typename BF::result_type Rp; @@ -3597,8 +3683,8 @@ namespace detail )); } else { std::terminate(); - BOOST_THREAD_FUTURE<R> ret; - return ::boost::move(ret); + //BOOST_THREAD_FUTURE<R> ret; + //return ::boost::move(ret); } } @@ -3622,8 +3708,8 @@ namespace detail return ::boost::move(ret); } else if (underlying_cast<int>(policy) & int(launch::deferred)) { std::terminate(); - BOOST_THREAD_FUTURE<R> ret; - return ::boost::move(ret); + //BOOST_THREAD_FUTURE<R> ret; + //return ::boost::move(ret); // return boost::detail::make_future_deferred_shared_state<Rp>( // BF( // thread_detail::decay_copy(boost::forward<F>(f)) @@ -3631,27 +3717,31 @@ namespace detail // ); } else { std::terminate(); - BOOST_THREAD_FUTURE<R> ret; - return ::boost::move(ret); + //BOOST_THREAD_FUTURE<R> ret; + //return ::boost::move(ret); } } #endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) #ifdef BOOST_THREAD_PROVIDES_EXECUTORS namespace detail { + ///////////////////////// /// shared_state_nullary_task ///////////////////////// template<typename Rp, typename Fp> struct shared_state_nullary_task { - shared_state<Rp>* that; + + typedef shared_ptr<shared_state_base > storage_type; + storage_type that; Fp f_; public: - shared_state_nullary_task(shared_state<Rp>* st, BOOST_THREAD_FWD_REF(Fp) f) + shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f) : that(st), f_(boost::move(f)) {}; + #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT @@ -3669,36 +3759,42 @@ namespace detail { shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT : that(x.that), f_(boost::move(x.f_)) { - x.that=0; + x.that.reset(); } shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT { if (this != &x) { that=x.that; f_=boost::move(x.f_); - x.that=0; + x.that.reset(); } return *this; } #endif void operator()() { + shared_ptr<shared_state<Rp> > that_ = static_pointer_cast<shared_state<Rp> >(that); try { - that->mark_finished_with_result(f_()); + that_->mark_finished_with_result(f_()); } catch(...) { - that->mark_exceptional_finish(); + that_->mark_exceptional_finish(); } } + ~shared_state_nullary_task() + { + } }; template<typename Fp> struct shared_state_nullary_task<void, Fp> { - shared_state<void>* that; + typedef shared_ptr<shared_state_base > storage_type; + storage_type that; Fp f_; public: - shared_state_nullary_task(shared_state<void>* st, BOOST_THREAD_FWD_REF(Fp) f) + shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f) : that(st), f_(boost::move(f)) {}; + #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT @@ -3716,91 +3812,51 @@ namespace detail { shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT : that(x.that), f_(boost::move(x.f_)) { - x.that=0; + x.that.reset(); } shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { if (this != &x) { that=x.that; f_=boost::move(x.f_); - x.that=0; + x.that.reset(); } return *this; } #endif void operator()() { + shared_ptr<shared_state<void> > that_ = static_pointer_cast<shared_state<void> >(that); try { f_(); - that->mark_finished_with_result(); + that_->mark_finished_with_result(); } catch(...) { - that->mark_exceptional_finish(); + that_->mark_exceptional_finish(); } } }; - template<typename Rp, typename Fp> - struct shared_state_nullary_task<Rp&, Fp> - { - shared_state<Rp&>* that; - Fp f_; - public: - shared_state_nullary_task(shared_state<Rp&>* st, BOOST_THREAD_FWD_REF(Fp) f) - : that(st), f_(boost::move(f)) - {} -#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) - shared_state_nullary_task(shared_state_nullary_task const& x) BOOST_NOEXCEPT - : that(x.that), f_(x.f_) {} - - shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { - if (this != &x){ - that=x.that; - f_=x.f_; - } - return *this; - } - // move - shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT - : that(x.that), f_(boost::move(x.f_)) - { - x.that=0; - } - shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { - if (this != &x) { - that=x.that; - f_=boost::move(x.f_); - x.that=0; - } - return *this; - } -#endif - void operator()() { - try { - that->mark_finished_with_result(f_()); - } catch(...) { - that->mark_exceptional_finish(); - } - } - }; +} + BOOST_THREAD_DCL_MOVABLE_BEG2(R,F) detail::shared_state_nullary_task<R,F> BOOST_THREAD_DCL_MOVABLE_END +namespace detail { ///////////////////////// /// future_executor_shared_state_base ///////////////////////// - template<typename Rp, typename Executor> + template<typename Rp> struct future_executor_shared_state: shared_state<Rp> { typedef shared_state<Rp> base_type; protected: public: - template<typename Fp> - future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { - this->set_executor(); - shared_state_nullary_task<Rp,Fp> t(this, boost::forward<Fp>(f)); - ex.submit(boost::move(t)); + future_executor_shared_state() { } - virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) + template <class Fp, class Executor> + void init(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { - this->wait(lk, false); + typedef typename decay<Fp>::type Cont; + this->set_executor_policy(executor_ptr_type(new executor_ref<Executor>(ex))); + shared_state_nullary_task<Rp,Cont> t(this->shared_from_this(), boost::forward<Fp>(f)); + ex.submit(boost::move(t)); } ~future_executor_shared_state() {} @@ -3812,8 +3868,9 @@ namespace detail { template <class Rp, class Fp, class Executor> BOOST_THREAD_FUTURE<Rp> make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { - shared_ptr<future_executor_shared_state<Rp, Executor> > - h(new future_executor_shared_state<Rp, Executor>(ex, boost::forward<Fp>(f))); + shared_ptr<future_executor_shared_state<Rp> > + h(new future_executor_shared_state<Rp>()); + h->init(ex, boost::forward<Fp>(f)); return BOOST_THREAD_FUTURE<Rp>(h); } @@ -4092,12 +4149,6 @@ namespace detail { } #endif - template <typename T> - BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) { - promise<T> p; - p.set_exception(ex); - return BOOST_THREAD_MAKE_RV_REF(p.get_future()); - } template <typename T> BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) { @@ -4119,16 +4170,9 @@ namespace detail { p.set_exception(boost::current_exception()); return BOOST_THREAD_MAKE_RV_REF(p.get_future()); } - - template <typename T> - BOOST_THREAD_FUTURE<T> make_exceptional_future_if_invalid(BOOST_THREAD_FWD_REF(BOOST_THREAD_FUTURE<T>) fut) { - fut.set_exceptional_if_invalid(); - return boost::move(fut); - } template <typename T> - shared_future<T> make_exceptional_future_if_invalid(shared_future<T> fut) { - fut.set_exceptional_if_invalid(); - return fut; + BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) { + return make_exceptional_future<T>(ex); } #if 0 @@ -4165,234 +4209,261 @@ namespace detail { // detail::future_async_continuation_shared_state //////////////////////////////// #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION -namespace detail -{ - ///////////////////////// - /// future_async_continuation_shared_state - ///////////////////////// +#if defined BOOST_THREAD_CONTINUATION_SYNC +#define continuation_shared_state_base shared_state +#else +#define continuation_shared_state_base future_async_shared_state_base +#endif - template<typename F, typename Rp, typename Fp> - struct future_async_continuation_shared_state: future_async_shared_state_base<Rp> +namespace detail +{ + ////////////////////// + // detail::continuation_shared_state + ////////////////////// + template<typename F, typename Rp, typename Fp, class ShSt=shared_state<Rp> > + struct continuation_shared_state: ShSt { F parent; Fp continuation; - shared_ptr<shared_state_base> centinel; public: - future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) : parent(boost::move(f)), - continuation(boost::move(c)), - centinel(parent.future_) { + continuation(boost::move(c)) + { } - - void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) { - this->thr_ = thread(&future_async_continuation_shared_state::run, that); + void init(boost::unique_lock<boost::mutex> &lock) + { + parent.future_->set_continuation_ptr(this->shared_from_this(), lock); } - static void run(shared_ptr<boost::detail::shared_state_base> that_) { - future_async_continuation_shared_state* that = dynamic_cast<future_async_continuation_shared_state*>(that_.get()); + void call() { try { - that->mark_finished_with_result(that->continuation(boost::move(that->parent))); + this->mark_finished_with_result(this->continuation(boost::move(this->parent))); } catch(...) { - that->mark_exceptional_finish(); + this->mark_exceptional_finish(); } + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); } - ~future_async_continuation_shared_state() { - } - }; + void call(boost::unique_lock<boost::mutex>& lck) { + try { + relocker relock(lck); - template<typename F, typename Fp> - struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void> - { - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; + // neither continuation nor parent are protected by the lock - call() must only + // be called once, and no one else must modify it. + Rp res = this->continuation(boost::move(this->parent)); - public: - future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) - : parent(boost::move(f)), - continuation(boost::move(c)), - centinel(parent.future_) { - } + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); - void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) { - this->thr_ = thread(&future_async_continuation_shared_state::run, that); - } + relock.lock(); - static void run(shared_ptr<boost::detail::shared_state_base> that_) { - future_async_continuation_shared_state* that = dynamic_cast<future_async_continuation_shared_state*>(that_.get()); - try { - that->continuation(boost::move(that->parent)); - that->mark_finished_with_result(); - } catch(...) { - that->mark_exceptional_finish(); + this->mark_finished_with_result_internal(boost::move(res), lck); + } catch (...) { + this->mark_exceptional_finish_internal(current_exception(), lck); + + // make sure parent is really cleared to prevent memory "leaks" + relocker relock(lck); + this->parent = F(); } } - ~future_async_continuation_shared_state() {} - - }; - - ///////////////////////// - /// future_executor_continuation_shared_state - ///////////////////////// -#ifdef BOOST_THREAD_PROVIDES_EXECUTORS - - template <typename FutureExecutorContinuationSharedState> - struct run_it { - shared_ptr<boost::detail::shared_state_base> that_; - - run_it(shared_ptr<boost::detail::shared_state_base> that) : that_ (that) {} - void operator()() + static void run(shared_ptr<boost::detail::shared_state_base> that_) { - FutureExecutorContinuationSharedState* that = dynamic_cast<FutureExecutorContinuationSharedState*>(that_.get()); - that->run(that_); + continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get()); + that->call(); } + + ~continuation_shared_state() {} }; - template<typename Ex, typename F, typename Rp, typename Fp> - struct future_executor_continuation_shared_state: shared_state<Rp> + template<typename F, typename Fp, class ShSt> + struct continuation_shared_state<F, void, Fp, ShSt>: ShSt { - Ex* ex; F parent; Fp continuation; - shared_ptr<shared_state_base> centinel; public: - future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) - : ex(&ex), parent(boost::move(f)), - continuation(boost::move(c)), - centinel(parent.future_) { - this->set_executor(); + continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : parent(boost::move(f)), + continuation(boost::move(c)) + { } - void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that ) { - relocker relock(lck); - run_it<future_executor_continuation_shared_state> fct(that); - ex->submit(fct); + void init(boost::unique_lock<boost::mutex> &lock) + { + parent.future_->set_continuation_ptr(this->shared_from_this(), lock); } - static void run(shared_ptr<boost::detail::shared_state_base> that_) { - future_executor_continuation_shared_state* that = dynamic_cast<future_executor_continuation_shared_state*>(that_.get()); + void call() + { try { - that->mark_finished_with_result(that->continuation(boost::move(that->parent))); + this->continuation(boost::move(this->parent)); + this->mark_finished_with_result(); } catch(...) { - that->mark_exceptional_finish(); + this->mark_exceptional_finish(); + } + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + } + + void call(boost::unique_lock<boost::mutex>& lck) { + try { + { + relocker relock(lck); + // neither continuation nor parent are protected by the lock - call() must only + // be called once, and no one else must modify it. + this->continuation(boost::move(this->parent)); + + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + } + this->mark_finished_with_result_internal(lck); + } catch (...) { + this->mark_exceptional_finish_internal(current_exception(), lck); + + // make sure parent is really cleared to prevent memory "leaks" + relocker relock(lck); + this->parent = F(); } } - virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) + static void run(shared_ptr<boost::detail::shared_state_base> that_) { - this->wait(lk, false); + continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get()); + that->call(); } - ~future_executor_continuation_shared_state() {} + ~continuation_shared_state() {} }; + ///////////////////////// + /// future_async_continuation_shared_state + ///////////////////////// - template<typename Ex, typename F, typename Fp> - struct future_executor_continuation_shared_state<Ex, F, void, Fp>: public shared_state<void> + template<typename F, typename Rp, typename Fp> + struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > { - Ex* ex; - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; - + typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > base_type; public: - future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) - : ex(&ex), parent(boost::move(f)), - continuation(boost::move(c)), - centinel(parent.future_) { - this->set_executor(); + future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward<Fp>(c)) + { } + + void launch_continuation() { +#if defined BOOST_THREAD_CONTINUATION_SYNC + this->call(); +#elif defined BOOST_THREAD_FUTURE_BLOCKING + boost::lock_guard<boost::mutex> lk(this->mutex); + this->thr_ = thread(&future_async_continuation_shared_state::run, static_shared_from_this(this)); +#else + thread(&future_async_continuation_shared_state::run, static_shared_from_this(this)).detach(); +#endif } + }; - void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that ) { - relocker relock(lck); - run_it<future_executor_continuation_shared_state> fct(that); - ex->submit(fct); - } + ///////////////////////// + /// future_executor_continuation_shared_state + ///////////////////////// +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS - static void run(shared_ptr<boost::detail::shared_state_base> that_) { - future_executor_continuation_shared_state* that = dynamic_cast<future_executor_continuation_shared_state*>(that_.get()); - try { - that->continuation(boost::move(that->parent)); - that->mark_finished_with_result(); - } catch(...) { - that->mark_exceptional_finish(); + template <typename FutureExecutorContinuationSharedState> + struct run_it { + shared_ptr<FutureExecutorContinuationSharedState> that_; + +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_THREAD_COPYABLE_AND_MOVABLE(run_it) + run_it(run_it const& x) //BOOST_NOEXCEPT + : that_(x.that_) + {} + run_it& operator=(BOOST_THREAD_COPY_ASSIGN_REF(run_it) x) //BOOST_NOEXCEPT + { + if (this != &x) { + that_=x.that_; + } + return *this; } - } + // move + run_it(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT + : that_(x.that_) + { + x.that_.reset(); + } + run_it& operator=(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT { + if (this != &x) { + that_=x.that; + x.that_.reset(); + } + return *this; + } +#endif + run_it(shared_ptr<FutureExecutorContinuationSharedState> that) : that_ (that) {} - virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) + void operator()() { - this->wait(lk, false); + that_->run(that_); } - - ~future_executor_continuation_shared_state() {} }; -#endif - ///////////////////////// - /// shared_future_async_continuation_shared_state - ///////////////////////// +} + BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::run_it<F> BOOST_THREAD_DCL_MOVABLE_END + +namespace detail { template<typename F, typename Rp, typename Fp> - struct shared_future_async_continuation_shared_state: future_async_shared_state_base<Rp> + struct future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp> { - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; + typedef continuation_shared_state<F,Rp,Fp> base_type; public: - shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) - : parent(f), - continuation(boost::move(c)), - centinel(parent.future_) { + future_executor_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward<Fp>(c)) + { } - void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) { - this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that); + template <class Ex> + void init(boost::unique_lock<boost::mutex> &lk, Ex& ex) + { + this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk); + this->base_type::init(lk); } - static void run(shared_ptr<boost::detail::shared_state_base> that_) { - shared_future_async_continuation_shared_state* that = dynamic_cast<shared_future_async_continuation_shared_state*>(that_.get()); - try { - that->mark_finished_with_result(that->continuation(that->parent)); - } catch(...) { - that->mark_exceptional_finish(); - } + void launch_continuation() { + run_it<base_type> fct(static_shared_from_this(this)); + this->get_executor()->submit(boost::move(fct)); } - ~shared_future_async_continuation_shared_state() {} + ~future_executor_continuation_shared_state() {} }; +#endif + + ///////////////////////// + /// shared_future_async_continuation_shared_state + ///////////////////////// - template<typename F, typename Fp> - struct shared_future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void> + template<typename F, typename Rp, typename Fp> + struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > { - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; + typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > base_type; public: shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) - : parent(f), - continuation(boost::move(c)), - centinel(parent.future_) { - } - - void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) { - this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that); + : base_type(boost::move(f), boost::forward<Fp>(c)) + { } - static void run(shared_ptr<boost::detail::shared_state_base> that_) { - shared_future_async_continuation_shared_state* that = dynamic_cast<shared_future_async_continuation_shared_state*>(that_.get()); - try { - that->continuation(that->parent); - that->mark_finished_with_result(); - } catch(...) { - that->mark_exceptional_finish(); - } + void launch_continuation() { +#if defined BOOST_THREAD_CONTINUATION_SYNC + this->call(); +#elif defined BOOST_THREAD_FUTURE_BLOCKING + boost::lock_guard<boost::mutex> lk(this->mutex); + this->thr_ = thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this)); +#else + thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this)).detach(); +#endif } ~shared_future_async_continuation_shared_state() {} @@ -4403,234 +4474,77 @@ namespace detail ///////////////////////// #ifdef BOOST_THREAD_PROVIDES_EXECUTORS - template<typename Ex, typename F, typename Rp, typename Fp> - struct shared_future_executor_continuation_shared_state: shared_state<Rp> + template<typename F, typename Rp, typename Fp> + struct shared_future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp> { - Ex* ex; - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; + typedef continuation_shared_state<F,Rp,Fp> base_type; public: - shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c) - : ex(&ex), parent(f), - continuation(boost::move(c)), - centinel(parent.future_) { - this->set_executor(); - } - - void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that) { - relocker relock(lck); - run_it<shared_future_executor_continuation_shared_state> fct(that); - ex->submit(fct); - } - - static void run(shared_ptr<boost::detail::shared_state_base> that_) { - shared_future_executor_continuation_shared_state* that = dynamic_cast<shared_future_executor_continuation_shared_state*>(that_.get()); - try { - that->mark_finished_with_result(that->continuation(that->parent)); - } catch(...) { - that->mark_exceptional_finish(); - } - } - virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) + shared_future_executor_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward<Fp>(c)) { - this->wait(lk, false); - } - - ~shared_future_executor_continuation_shared_state() {} - }; - - template<typename Ex, typename F, typename Fp> - struct shared_future_executor_continuation_shared_state<Ex, F, void, Fp>: public shared_state<void> - { - Ex* ex; - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; - - public: - shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c) - : ex(&ex), parent(f), - continuation(boost::move(c)), - centinel(parent.future_) { - } - - void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that) { - relocker relock(lck); - run_it<shared_future_executor_continuation_shared_state> fct(that); - ex->submit(fct); } - static void run(shared_ptr<boost::detail::shared_state_base> that_) { - shared_future_executor_continuation_shared_state* that = dynamic_cast<shared_future_executor_continuation_shared_state*>(that_.get()); - try { - that->continuation(that->parent); - that->mark_finished_with_result(); - } catch(...) { - that->mark_exceptional_finish(); - } + template <class Ex> + void init(boost::unique_lock<boost::mutex> &lk, Ex& ex) + { + this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk); + this->base_type::init(lk); } - virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk) - { - this->wait(lk, false); + void launch_continuation() { + run_it<base_type> fct(static_shared_from_this(this)); + this->get_executor()->submit(boost::move(fct)); } ~shared_future_executor_continuation_shared_state() {} }; + #endif ////////////////////////// /// future_deferred_continuation_shared_state ////////////////////////// template<typename F, typename Rp, typename Fp> - struct future_deferred_continuation_shared_state: shared_state<Rp> - { - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; - - public: - future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) - : parent(boost::move(f)), - continuation(boost::move(c)), - centinel(parent.future_) { - this->set_deferred(); - } - - virtual void launch_continuation(boost::unique_lock<boost::mutex>&lk, shared_ptr<shared_state_base> ) { - if (this->is_deferred_) { - this->is_deferred_=false; - this->execute(lk); - } - } - - virtual void execute(boost::unique_lock<boost::mutex>& lck) { - try { - Fp local_fuct=boost::move(continuation); - F ftmp = boost::move(parent); - relocker relock(lck); - Rp res = local_fuct(boost::move(ftmp)); - relock.lock(); - this->mark_finished_with_result_internal(boost::move(res), lck); - } catch (...) { - this->mark_exceptional_finish_internal(current_exception(), lck); - } - } - }; - - template<typename F, typename Fp> - struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void> + struct future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp> { - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; - + typedef continuation_shared_state<F,Rp,Fp> base_type; public: future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) - : parent(boost::move(f)), - continuation(boost::move(c)), - centinel(parent.future_) { + : base_type(boost::move(f), boost::forward<Fp>(c)) + { this->set_deferred(); } - ~future_deferred_continuation_shared_state() { - } - virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) { - if (this->is_deferred_) { - this->is_deferred_=false; - this->execute(lk); - } + virtual void execute(boost::unique_lock<boost::mutex>& lk) { + this->parent.wait(); + this->call(lk); } - virtual void execute(boost::unique_lock<boost::mutex>& lck) { - try { - Fp local_fuct=boost::move(continuation); - F ftmp = boost::move(parent); - relocker relock(lck); - local_fuct(boost::move(ftmp)); - relock.lock(); - this->mark_finished_with_result_internal(lck); - } catch (...) { - this->mark_exceptional_finish_internal(current_exception(), lck); - } - } + virtual void launch_continuation() { } }; ////////////////////////// /// shared_future_deferred_continuation_shared_state ////////////////////////// template<typename F, typename Rp, typename Fp> - struct shared_future_deferred_continuation_shared_state: shared_state<Rp> + struct shared_future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp> { - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; + typedef continuation_shared_state<F,Rp,Fp> base_type; public: shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) - : parent(f), - continuation(boost::move(c)), - centinel(parent.future_) { - this->set_deferred(); - } - - virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) { - if (this->is_deferred_) { - this->is_deferred_=false; - this->execute(lk); - } - } - - virtual void execute(boost::unique_lock<boost::mutex>& lck) { - try { - Fp local_fuct=boost::move(continuation); - F ftmp = parent; - relocker relock(lck); - Rp res = local_fuct(ftmp); - relock.lock(); - this->mark_finished_with_result_internal(boost::move(res), lck); - } catch (...) { - this->mark_exceptional_finish_internal(current_exception(), lck); - } - } - }; - - template<typename F, typename Fp> - struct shared_future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void> - { - F parent; - Fp continuation; - shared_ptr<shared_state_base> centinel; - - public: - shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) - : parent(f), - continuation(boost::move(c)), - centinel(parent.future_) { + : base_type(boost::move(f), boost::forward<Fp>(c)) + { this->set_deferred(); } - virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) { - if (this->is_deferred_) { - this->is_deferred_=false; - this->execute(lk); - } + virtual void execute(boost::unique_lock<boost::mutex>& lk) { + this->parent.wait(); + this->call(lk); } - virtual void execute(boost::unique_lock<boost::mutex>& lck) { - try { - Fp local_fuct=boost::move(continuation); - F ftmp = parent; - relocker relock(lck); - local_fuct(ftmp); - relock.lock(); - this->mark_finished_with_result_internal(lck); - } catch (...) { - this->mark_exceptional_finish_internal(current_exception(), lck); - } - } + virtual void launch_continuation() { } }; //////////////////////////////// @@ -4641,11 +4555,10 @@ namespace detail make_future_deferred_continuation_shared_state( boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) { - shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> > - h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); - lock.lock(); - h->parent.future_->set_continuation_ptr(h, lock); - lock.unlock(); + typedef typename decay<Fp>::type Cont; + shared_ptr<future_deferred_continuation_shared_state<F, Rp, Cont> > + h(new future_deferred_continuation_shared_state<F, Rp, Cont>(boost::move(f), boost::forward<Fp>(c))); + h->init(lock); return BOOST_THREAD_FUTURE<Rp>(h); } @@ -4657,11 +4570,10 @@ namespace detail make_future_async_continuation_shared_state( boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) { - shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> > - h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); - lock.lock(); - h->parent.future_->set_continuation_ptr(h, lock); - lock.unlock(); + typedef typename decay<Fp>::type Cont; + shared_ptr<future_async_continuation_shared_state<F,Rp, Cont> > + h(new future_async_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c))); + h->init(lock); return BOOST_THREAD_FUTURE<Rp>(h); } @@ -4676,11 +4588,10 @@ namespace detail make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) { - shared_ptr<future_executor_continuation_shared_state<Ex,F,Rp, Fp> > - h(new future_executor_continuation_shared_state<Ex, F,Rp, Fp>(ex, boost::move(f), boost::forward<Fp>(c))); - lock.lock(); - h->parent.future_->set_continuation_ptr(h, lock); - lock.unlock(); + typedef typename decay<Fp>::type Cont; + shared_ptr<future_executor_continuation_shared_state<F,Rp, Cont> > + h(new future_executor_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c))); + h->init(lock, ex); return BOOST_THREAD_FUTURE<Rp>(h); } @@ -4694,11 +4605,10 @@ namespace detail make_shared_future_deferred_continuation_shared_state( boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c) { - shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Fp> > - h(new shared_future_deferred_continuation_shared_state<F, Rp, Fp>(f, boost::forward<Fp>(c))); - lock.lock(); - h->parent.future_->set_continuation_ptr(h, lock); - lock.unlock(); + typedef typename decay<Fp>::type Cont; + shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Cont> > + h(new shared_future_deferred_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c))); + h->init(lock); return BOOST_THREAD_FUTURE<Rp>(h); } @@ -4710,11 +4620,10 @@ namespace detail make_shared_future_async_continuation_shared_state( boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c) { - shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Fp> > - h(new shared_future_async_continuation_shared_state<F,Rp, Fp>(f, boost::forward<Fp>(c))); - lock.lock(); - h->parent.future_->set_continuation_ptr(h, lock); - lock.unlock(); + typedef typename decay<Fp>::type Cont; + shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Cont> > + h(new shared_future_async_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c))); + h->init(lock); return BOOST_THREAD_FUTURE<Rp>(h); } @@ -4727,11 +4636,10 @@ namespace detail make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c) { - shared_ptr<shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp> > - h(new shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp>(ex, f, boost::forward<Fp>(c))); - lock.lock(); - h->parent.future_->set_continuation_ptr(h, lock); - lock.unlock(); + typedef typename decay<Fp>::type Cont; + shared_ptr<shared_future_executor_continuation_shared_state<F, Rp, Cont> > + h(new shared_future_executor_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c))); + h->init(lock, ex); return BOOST_THREAD_FUTURE<Rp>(h); } @@ -4740,9 +4648,8 @@ namespace detail //////////////////////////////// // template<typename F> - // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + // auto future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; //////////////////////////////// - template <typename R> template <typename F> inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> @@ -4750,26 +4657,63 @@ namespace detail typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); - boost::unique_lock<boost::mutex> lock(this->future_->mutex); + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + if (underlying_cast<int>(policy) & int(launch::async)) { - lock.unlock(); - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( lock, boost::move(*this), boost::forward<F>(func) ))); } else if (underlying_cast<int>(policy) & int(launch::deferred)) { - this->future_->wait_internal(lock); - lock.unlock(); - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( lock, boost::move(*this), boost::forward<F>(func) ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); +#endif + } else if (underlying_cast<int>(policy) & int(launch::inherit)) { + + launch policy = this->launch_policy(lock); + if (underlying_cast<int>(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } else if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); +#endif + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } } else { - lock.unlock(); - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( lock, boost::move(*this), boost::forward<F>(func) ))); } } #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + //////////////////////////////// + // template<typename Ex, typename F> + // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// template <typename R> template <typename Ex, typename F> inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> @@ -4777,45 +4721,52 @@ namespace detail typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); - boost::unique_lock<boost::mutex> lock(this->future_->mutex); - lock.unlock(); - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type, F>(ex, + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, lock, boost::move(*this), boost::forward<F>(func) ))); } #endif + //////////////////////////////// + // template<typename F> + // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// template <typename R> template <typename F> inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) { + +#ifndef BOOST_THREAD_CONTINUATION_SYNC + return this->then(this->launch_policy(), boost::forward<F>(func)); +#else typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); - boost::unique_lock<boost::mutex> lock(this->future_->mutex); - if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) { - lock.unlock(); - return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( - lock, boost::move(*this), boost::forward<F>(func) - ); - } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) { - this->future_->wait_internal(lock); - lock.unlock(); - return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( - lock, boost::move(*this), boost::forward<F>(func) - ); + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + + launch policy = this->launch_policy(lock); + if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); } else { - lock.unlock(); - return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( - lock, boost::move(*this), boost::forward<F>(func) - ); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); } +#endif + } //////////////////////////////// // template<typename F> - // auto future<future<R2>>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + // auto future<future<R2> >::then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; //////////////////////////////// - template <typename R2> template <typename F> inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type> @@ -4824,22 +4775,64 @@ namespace detail typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); - boost::unique_lock<boost::mutex> lock(this->future_->mutex); + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + if (underlying_cast<int>(policy) & int(launch::async)) { - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( lock, boost::move(*this), boost::forward<F>(func) ))); } else if (underlying_cast<int>(policy) & int(launch::deferred)) { - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( lock, boost::move(*this), boost::forward<F>(func) ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); +#endif + } else if (underlying_cast<int>(policy) & int(launch::inherit)) { + launch policy = this->launch_policy(lock); + + if (underlying_cast<int>(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } else if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); +#endif + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } } else { - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( lock, boost::move(*this), boost::forward<F>(func) ))); } } + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + //////////////////////////////// + // template<typename Ex, typename F> + // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// template <typename R2> template <typename Ex, typename F> inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type> @@ -4848,42 +4841,54 @@ namespace detail typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); - boost::unique_lock<boost::mutex> lock(this->future_->mutex); - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type, F>(ex, + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, lock, boost::move(*this), boost::forward<F>(func) ))); } #endif + + //////////////////////////////// + // template<typename F> + // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// template <typename R2> template <typename F> inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type> BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) { + +#ifndef BOOST_THREAD_CONTINUATION_SYNC + return this->then(this->launch_policy(), boost::forward<F>(func)); +#else typedef BOOST_THREAD_FUTURE<R2> R; typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); - boost::unique_lock<boost::mutex> lock(this->future_->mutex); - if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) { - return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( - lock, boost::move(*this), boost::forward<F>(func) - ); - } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) { - this->future_->wait_internal(lock); - return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( - lock, boost::move(*this), boost::forward<F>(func) - ); + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + + launch policy = this->launch_policy(lock); + + if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); } else { - return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( - lock, boost::move(*this), boost::forward<F>(func) - ); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + lock, boost::move(*this), boost::forward<F>(func) + ))); } +#endif } //////////////////////////////// // template<typename F> - // auto shared_future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + // auto shared_future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; //////////////////////////////// - template <typename R> template <typename F> inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> @@ -4894,24 +4899,57 @@ namespace detail boost::unique_lock<boost::mutex> lock(this->future_->mutex); if (underlying_cast<int>(policy) & int(launch::async)) { - lock.unlock(); - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>( + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>( lock, *this, boost::forward<F>(func) ))); } else if (underlying_cast<int>(policy) & int(launch::deferred)) { - this->future_->wait_internal(lock); - lock.unlock(); - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>( lock, *this, boost::forward<F>(func) ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex, + lock, *this, boost::forward<F>(func) + ))); +#endif + } else if (underlying_cast<int>(policy) & int(launch::inherit)) { + + launch policy = this->launch_policy(lock); + if (underlying_cast<int>(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>( + lock, *this, boost::forward<F>(func) + ))); + } else if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>( + lock, *this, boost::forward<F>(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex, + lock, *this, boost::forward<F>(func) + ))); +#endif + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>( + lock, *this, boost::forward<F>(func) + ))); + } + } else { - lock.unlock(); - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>( + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>( lock, *this, boost::forward<F>(func) ))); } } #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + //////////////////////////////// + // template<typename Ex, typename F> + // auto shared_future<R>::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// template <typename R> template <typename Ex, typename F> inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> @@ -4921,36 +4959,38 @@ namespace detail BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); boost::unique_lock<boost::mutex> lock(this->future_->mutex); - lock.unlock(); - return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type, F>(ex, + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex, lock, *this, boost::forward<F>(func) ))); } #endif + //////////////////////////////// + // template<typename F> + // auto shared_future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// template <typename R> template <typename F> inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const { +#ifndef BOOST_THREAD_CONTINUATION_SYNC + return this->then(this->launch_policy(), boost::forward<F>(func)); +#else typedef typename boost::result_of<F(shared_future<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); boost::unique_lock<boost::mutex> lock(this->future_->mutex); - if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) { - lock.unlock(); - return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>( - lock, *this, boost::forward<F>(func)); - } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) { - this->future_->wait_internal(lock); - lock.unlock(); - return boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( - lock, *this, boost::forward<F>(func)); + launch policy = this->launch_policy(lock); + if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>( + lock, *this, boost::forward<F>(func) + ))); } else { - lock.unlock(); - return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>( - lock, *this, boost::forward<F>(func)); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>( + lock, *this, boost::forward<F>(func) + ))); } +#endif } namespace detail @@ -5013,32 +5053,81 @@ namespace detail template<typename F, typename Rp> struct future_unwrap_shared_state: shared_state<Rp> { - F parent; + F wrapped; + typename F::value_type unwrapped; public: explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f) - : parent(boost::move(f)) {} - - typename F::value_type parent_value(boost::unique_lock<boost::mutex>& ) { - typename F::value_type r = parent.get(); - r.set_exceptional_if_invalid(); - return boost::move(r); + : wrapped(boost::move(f)) { } - virtual void wait(boost::unique_lock<boost::mutex>& lk, bool ) { // todo see if rethrow must be used - parent_value(lk).wait(); + void launch_continuation() + { + boost::unique_lock<boost::mutex> lk(this->mutex); + // assert(wrapped.is_ready()); + if (! unwrapped.valid() ) + { + if (wrapped.has_exception()) { + this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk); + } else { + unwrapped = wrapped.get(); + if (unwrapped.valid()) + { + lk.unlock(); + boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex); + unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2); + } else { + this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk); + } + } + } else { + // assert(unwrapped.is_ready()); + if (unwrapped.has_exception()) { + this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk); + } else { + this->mark_finished_with_result_internal(unwrapped.get(), lk); + } + } } - virtual Rp get(boost::unique_lock<boost::mutex>& lk) { - return parent_value(lk).get(); + }; + + template<typename F> + struct future_unwrap_shared_state<F,void>: shared_state<void> + { + F wrapped; + typename F::value_type unwrapped; + public: + explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f) + : wrapped(boost::move(f)) { } -#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION - typedef shared_ptr<shared_state_base> continuation_ptr_type; - virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock) + void launch_continuation() { - boost::unique_lock<boost::mutex> lk(parent.future_->mutex); - parent.future_->set_continuation_ptr(continuation, lk); + boost::unique_lock<boost::mutex> lk(this->mutex); + // assert(wrapped.is_ready()); + if (! unwrapped.valid() ) + { + if (wrapped.has_exception()) { + this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk); + } else { + unwrapped = wrapped.get(); + if (unwrapped.valid()) + { + lk.unlock(); + boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex); + unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2); + } else { + this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk); + } + } + } else { + // assert(unwrapped.is_ready()); + if (unwrapped.has_exception()) { + this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk); + } else { + this->mark_finished_with_result_internal(lk); + } + } } -#endif }; template <class F, class Rp> @@ -5046,9 +5135,8 @@ namespace detail make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) { shared_ptr<future_unwrap_shared_state<F, Rp> > h(new future_unwrap_shared_state<F, Rp>(boost::move(f))); - lock.lock(); - h->parent.future_->set_continuation_ptr(h, lock); - lock.unlock(); + h->wrapped.future_->set_continuation_ptr(h, lock); + return BOOST_THREAD_FUTURE<Rp>(h); } } @@ -5062,8 +5150,11 @@ namespace detail BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap() { BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); - boost::unique_lock<boost::mutex> lock(this->future_->mutex); - lock.unlock(); + + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this)); } #endif @@ -5091,7 +5182,7 @@ namespace detail vector_type vec_; static void run(shared_ptr<boost::detail::shared_state_base> that_) { - future_when_all_vector_shared_state* that = dynamic_cast<future_when_all_vector_shared_state*>(that_.get()); + future_when_all_vector_shared_state* that = static_cast<future_when_all_vector_shared_state*>(that_.get()); try { boost::wait_for_all(that->vec_.begin(), that->vec_.end()); that->mark_finished_with_result(boost::move(that->vec_)); @@ -5116,7 +5207,11 @@ namespace detail future_when_all_vector_shared_state::run(this->shared_from_this()); return; } +#ifdef BOOST_THREAD_FUTURE_BLOCKING this->thr_ = thread(&future_when_all_vector_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_all_vector_shared_state::run, this->shared_from_this()).detach(); +#endif } public: @@ -5158,7 +5253,7 @@ namespace detail static void run(shared_ptr<boost::detail::shared_state_base> that_) { - future_when_any_vector_shared_state* that = dynamic_cast<future_when_any_vector_shared_state*>(that_.get()); + future_when_any_vector_shared_state* that = static_cast<future_when_any_vector_shared_state*>(that_.get()); try { boost::wait_for_any(that->vec_.begin(), that->vec_.end()); that->mark_finished_with_result(boost::move(that->vec_)); @@ -5183,7 +5278,11 @@ namespace detail return; } +#ifdef BOOST_THREAD_FUTURE_BLOCKING this->thr_ = thread(&future_when_any_vector_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_any_vector_shared_state::run, this->shared_from_this()).detach(); +#endif } public: @@ -5256,7 +5355,7 @@ namespace detail typedef typename make_tuple_indices<1+sizeof...(T)>::type Index; static void run(shared_ptr<boost::detail::shared_state_base> that_) { - future_when_all_tuple_shared_state* that = dynamic_cast<future_when_all_tuple_shared_state*>(that_.get()); + future_when_all_tuple_shared_state* that = static_cast<future_when_all_tuple_shared_state*>(that_.get()); try { // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor()); that->wait_for_all(Index()); @@ -5286,8 +5385,12 @@ namespace detail future_when_all_tuple_shared_state::run(this->shared_from_this()); return; } - +#ifdef BOOST_THREAD_FUTURE_BLOCKING this->thr_ = thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()).detach(); +#endif + } public: template< typename F, typename ...Fs> @@ -5325,7 +5428,7 @@ namespace detail static void run(shared_ptr<boost::detail::shared_state_base> that_) { - future_when_any_tuple_shared_state* that = dynamic_cast<future_when_any_tuple_shared_state*>(that_.get()); + future_when_any_tuple_shared_state* that = static_cast<future_when_any_tuple_shared_state*>(that_.get()); try { // TODO make use of apply(that->tup_, wait_for_any_fctr); that->wait_for_any(Index()); @@ -5353,7 +5456,11 @@ namespace detail return; } +#ifdef BOOST_THREAD_FUTURE_BLOCKING this->thr_ = thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()).detach(); +#endif } public: diff --git a/boost/thread/futures/launch.hpp b/boost/thread/futures/launch.hpp index b457020aaa..8eed42cf4d 100644 --- a/boost/thread/futures/launch.hpp +++ b/boost/thread/futures/launch.hpp @@ -22,6 +22,7 @@ namespace boost #ifdef BOOST_THREAD_PROVIDES_EXECUTORS executor = 4, #endif + inherit = 8, any = async | deferred } BOOST_SCOPED_ENUM_DECLARE_END(launch) diff --git a/boost/thread/latch.hpp b/boost/thread/latch.hpp index 8fa9d963de..dc921e68fe 100644 --- a/boost/thread/latch.hpp +++ b/boost/thread/latch.hpp @@ -72,6 +72,7 @@ namespace boost void wait() { boost::unique_lock<boost::mutex> lk(mutex_); + if (count_ == 0) return; std::size_t generation(generation_); cond_.wait(lk, detail::not_equal(generation, generation_)); } @@ -89,6 +90,7 @@ namespace boost cv_status wait_for(const chrono::duration<Rep, Period>& rel_time) { boost::unique_lock<boost::mutex> lk(mutex_); + if (count_ == 0) return cv_status::no_timeout; std::size_t generation(generation_); return cond_.wait_for(lk, rel_time, detail::not_equal(generation, generation_)) ? cv_status::no_timeout @@ -101,6 +103,7 @@ namespace boost cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) { boost::unique_lock<boost::mutex> lk(mutex_); + if (count_ == 0) return cv_status::no_timeout; std::size_t generation(generation_); return cond_.wait_until(lk, abs_time, detail::not_equal(generation, generation_)) ? cv_status::no_timeout diff --git a/boost/thread/poly_lockable.hpp b/boost/thread/poly_lockable.hpp index 7346188116..fffcbce133 100644 --- a/boost/thread/poly_lockable.hpp +++ b/boost/thread/poly_lockable.hpp @@ -31,7 +31,7 @@ namespace boost //] //[poly_lockable - class poly_lockable : public basic_poly_lockable<Lockable> + class poly_lockable : public basic_poly_lockable { public: @@ -41,7 +41,7 @@ namespace boost //] //[timed_poly_lockable - class timed_poly_lockable: public poly_lockable<TimedLock> + class timed_poly_lockable: public poly_lockable { public: virtual ~timed_poly_lockable()=0; diff --git a/boost/thread/pthread/condition_variable.hpp b/boost/thread/pthread/condition_variable.hpp index b30d37f9b0..a603351591 100644 --- a/boost/thread/pthread/condition_variable.hpp +++ b/boost/thread/pthread/condition_variable.hpp @@ -68,17 +68,14 @@ namespace boost #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + pthread_mutex_t* the_mutex = &internal_mutex; guard.activate(m); - do { - res = pthread_cond_wait(&cond,&internal_mutex); - } while (res == EINTR); #else - //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); pthread_mutex_t* the_mutex = m.mutex()->native_handle(); +#endif do { res = pthread_cond_wait(&cond,the_mutex); } while (res == EINTR); -#endif } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); @@ -99,18 +96,17 @@ namespace boost boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned")); } #endif - thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; int cond_res; { #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + pthread_mutex_t* the_mutex = &internal_mutex; guard.activate(m); - cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); #else - //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); pthread_mutex_t* the_mutex = m.mutex()->native_handle(); - cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout); #endif + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout); } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); @@ -156,11 +152,11 @@ namespace boost { boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init")); } - int const res2=pthread_cond_init(&cond,NULL); + int const res2 = detail::monotonic_pthread_cond_init(cond); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); - boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init")); + boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init")); } } ~condition_variable_any() @@ -178,7 +174,7 @@ namespace boost #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS detail::interruption_checker check_for_interruption(&internal_mutex,&cond); #else - boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); + boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); #endif guard.activate(m); res=pthread_cond_wait(&cond,&internal_mutex); @@ -240,6 +236,8 @@ namespace boost return timed_wait(m,get_system_time()+wait_duration,pred); } #endif +#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + #ifdef BOOST_THREAD_USES_CHRONO template <class lock_type,class Duration> cv_status @@ -268,22 +266,6 @@ namespace boost return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } - template <class lock_type, class Clock, class Duration, class Predicate> - bool - wait_until( - lock_type& lock, - const chrono::time_point<Clock, Duration>& t, - Predicate pred) - { - while (!pred()) - { - if (wait_until(lock, t) == cv_status::timeout) - return pred(); - } - return true; - } - - template <class lock_type, class Rep, class Period> cv_status wait_for( @@ -299,28 +281,64 @@ namespace boost } + template <class lock_type> + cv_status wait_until( + lock_type& lk, + chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif +#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#ifdef BOOST_THREAD_USES_CHRONO - template <class lock_type, class Rep, class Period, class Predicate> - bool - wait_for( - lock_type& lock, - const chrono::duration<Rep, Period>& d, - Predicate pred) + template <class lock_type, class Duration> + cv_status + wait_until( + lock_type& lock, + const chrono::time_point<chrono::steady_clock, Duration>& t) { - return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + using namespace chrono; + typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + return steady_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } -// while (!pred()) -// { -// if (wait_for(lock, d) == cv_status::timeout) -// return pred(); -// } -// return true; + template <class lock_type, class Clock, class Duration> + cv_status + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + steady_clock::time_point s_now = steady_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } - template <class lock_type> - cv_status wait_until( - lock_type& lk, - chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) + template <class lock_type, class Rep, class Period> + cv_status + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, c_now + ceil<nanoseconds>(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + inline cv_status wait_until( + unique_lock<mutex>& lk, + chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp) { using namespace chrono; nanoseconds d = tp.time_since_epoch(); @@ -328,6 +346,35 @@ namespace boost if (do_wait_until(lk, ts)) return cv_status::no_timeout; else return cv_status::timeout; } + +#endif +#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + template <class lock_type, class Clock, class Duration, class Predicate> + bool + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + template <class lock_type, class Rep, class Period, class Predicate> + bool + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + } #endif void notify_one() BOOST_NOEXCEPT @@ -354,7 +401,7 @@ namespace boost #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS detail::interruption_checker check_for_interruption(&internal_mutex,&cond); #else - boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); + boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); #endif guard.activate(m); res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); @@ -372,8 +419,6 @@ namespace boost } return true; } - - }; } diff --git a/boost/thread/pthread/condition_variable_fwd.hpp b/boost/thread/pthread/condition_variable_fwd.hpp index e18030fd5f..1255eac59b 100644 --- a/boost/thread/pthread/condition_variable_fwd.hpp +++ b/boost/thread/pthread/condition_variable_fwd.hpp @@ -28,6 +28,26 @@ namespace boost { + namespace detail { + inline int monotonic_pthread_cond_init(pthread_cond_t& cond) { + +#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + pthread_condattr_t attr; + int res = pthread_condattr_init(&attr); + if (res) + { + return res; + } + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + res=pthread_cond_init(&cond,&attr); + pthread_condattr_destroy(&attr); + return res; +#else + return pthread_cond_init(&cond,NULL); +#endif + + } + } class condition_variable { @@ -56,19 +76,19 @@ namespace boost condition_variable() { #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - int const res=pthread_mutex_init(&internal_mutex,NULL); + int res=pthread_mutex_init(&internal_mutex,NULL); if(res) { boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init")); } #endif - int const res2=pthread_cond_init(&cond,NULL); - if(res2) + res = detail::monotonic_pthread_cond_init(cond); + if (res) { #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); #endif - boost::throw_exception(thread_resource_error(res2, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init")); + boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init")); } } ~condition_variable() @@ -94,7 +114,6 @@ namespace boost while(!pred()) wait(m); } - #if defined BOOST_THREAD_USES_DATETIME inline bool timed_wait( unique_lock<mutex>& m, @@ -120,6 +139,15 @@ namespace boost unique_lock<mutex>& m, duration_type const& wait_duration) { + if (wait_duration.is_pos_infinity()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + return true; + } + if (wait_duration.is_special()) + { + return true; + } return timed_wait(m,get_system_time()+wait_duration); } @@ -149,10 +177,24 @@ namespace boost unique_lock<mutex>& m, duration_type const& wait_duration,predicate_type pred) { + if (wait_duration.is_pos_infinity()) + { + while (!pred()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + } + return true; + } + if (wait_duration.is_special()) + { + return pred(); + } return timed_wait(m,get_system_time()+wait_duration,pred); } #endif +#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + #ifdef BOOST_THREAD_USES_CHRONO template <class Duration> @@ -182,20 +224,6 @@ namespace boost return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } - template <class Clock, class Duration, class Predicate> - bool - wait_until( - unique_lock<mutex>& lock, - const chrono::time_point<Clock, Duration>& t, - Predicate pred) - { - while (!pred()) - { - if (wait_until(lock, t) == cv_status::timeout) - return pred(); - } - return true; - } template <class Rep, class Period> @@ -213,6 +241,90 @@ namespace boost } + inline cv_status wait_until( + unique_lock<mutex>& lk, + chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif + +#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<chrono::steady_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + return steady_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class Clock, class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + steady_clock::time_point s_now = steady_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template <class Rep, class Period> + cv_status + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, c_now + ceil<nanoseconds>(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + inline cv_status wait_until( + unique_lock<mutex>& lk, + chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif + +#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration, class Predicate> + bool + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } template <class Rep, class Period, class Predicate> bool @@ -222,13 +334,6 @@ namespace boost Predicate pred) { return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); - -// while (!pred()) -// { -// if (wait_for(lock, d) == cv_status::timeout) -// return pred(); -// } -// return true; } #endif @@ -242,18 +347,7 @@ namespace boost void notify_one() BOOST_NOEXCEPT; void notify_all() BOOST_NOEXCEPT; -#ifdef BOOST_THREAD_USES_CHRONO - inline cv_status wait_until( - unique_lock<mutex>& lk, - chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) - { - using namespace chrono; - nanoseconds d = tp.time_since_epoch(); - timespec ts = boost::detail::to_timespec(d); - if (do_wait_until(lk, ts)) return cv_status::no_timeout; - else return cv_status::timeout; - } -#endif + }; BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); diff --git a/boost/thread/pthread/once_atomic.hpp b/boost/thread/pthread/once_atomic.hpp index 923f07bd90..c54a35c541 100644 --- a/boost/thread/pthread/once_atomic.hpp +++ b/boost/thread/pthread/once_atomic.hpp @@ -214,7 +214,7 @@ namespace boost thread_detail::commit_once_region(flag); } } - +#if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130)) template<typename Function> inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) { @@ -302,7 +302,7 @@ namespace boost } } - +#endif // __SUNPRO_CC #endif } diff --git a/boost/thread/shared_mutex.hpp b/boost/thread/shared_mutex.hpp index b968f2ac10..ce5d6d1bfb 100644 --- a/boost/thread/shared_mutex.hpp +++ b/boost/thread/shared_mutex.hpp @@ -28,6 +28,7 @@ namespace boost { + typedef shared_mutex shared_timed_mutex; namespace sync { #ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES diff --git a/boost/thread/v2/thread.hpp b/boost/thread/v2/thread.hpp index 181661a34e..53560610e2 100644 --- a/boost/thread/v2/thread.hpp +++ b/boost/thread/v2/thread.hpp @@ -91,7 +91,19 @@ namespace boost cv.wait_until(lk, t); } -#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY +#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC && defined BOOST_CHRONO_HAS_CLOCK_STEADY + template <class Rep, class Period> + void sleep_for(const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + if (d > duration<Rep, Period>::zero()) + { + steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d); + sleep_until(c_timeout); + } + } + +#elif defined BOOST_THREAD_SLEEP_FOR_IS_STEADY template <class Rep, class Period> void sleep_for(const chrono::duration<Rep, Period>& d) @@ -127,7 +139,8 @@ namespace boost using namespace chrono; if (d > duration<Rep, Period>::zero()) { - steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d); + //system_clock::time_point c_timeout = time_point_cast<system_clock::duration>(system_clock::now() + ceil<nanoseconds>(d)); + system_clock::time_point c_timeout = system_clock::now() + ceil<system_clock::duration>(d); sleep_until(c_timeout); } } diff --git a/boost/thread/win32/condition_variable.hpp b/boost/thread/win32/condition_variable.hpp index 14c23ce0e2..23e9e44484 100644 --- a/boost/thread/win32/condition_variable.hpp +++ b/boost/thread/win32/condition_variable.hpp @@ -339,8 +339,8 @@ namespace boost { if (wait_duration.is_pos_infinity()) { - wait(m); // or do_wait(m,detail::timeout::sentinel()); - return true; + wait(m); // or do_wait(m,detail::timeout::sentinel()); + return true; } if (wait_duration.is_special()) { @@ -362,6 +362,18 @@ namespace boost template<typename duration_type,typename predicate_type> bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred) { + if (wait_duration.is_pos_infinity()) + { + while (!pred()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + } + return true; + } + if (wait_duration.is_special()) + { + return pred(); + } return do_wait(m,wait_duration.total_milliseconds(),pred); } #endif diff --git a/boost/thread/win32/shared_mutex.hpp b/boost/thread/win32/shared_mutex.hpp index fff97b7355..b7822d1142 100644 --- a/boost/thread/win32/shared_mutex.hpp +++ b/boost/thread/win32/shared_mutex.hpp @@ -139,6 +139,7 @@ namespace boost void lock_shared() { + #if defined BOOST_THREAD_USES_DATETIME BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel())); #else @@ -389,6 +390,7 @@ namespace boost void lock() { + #if defined BOOST_THREAD_USES_DATETIME BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel())); #else @@ -739,6 +741,7 @@ namespace boost new_state.upgrade=false; bool const last_reader=!--new_state.shared_count; + new_state.shared_waiting=0; if(last_reader) { if(new_state.exclusive_waiting) @@ -746,7 +749,6 @@ namespace boost --new_state.exclusive_waiting; new_state.exclusive_waiting_blocked=false; } - new_state.shared_waiting=0; } state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); diff --git a/boost/thread/win32/thread_data.hpp b/boost/thread/win32/thread_data.hpp index 51f6273f43..005f3ba503 100644 --- a/boost/thread/win32/thread_data.hpp +++ b/boost/thread/win32/thread_data.hpp @@ -280,12 +280,13 @@ namespace boost { interruptible_wait(abs_time); } -#ifdef BOOST_THREAD_USES_CHRONO - inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) - { - interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count()); - } -#endif +// #11322 sleep_for() nanoseconds overload will always return too early on windows +//#ifdef BOOST_THREAD_USES_CHRONO +// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) +// { +// interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count()); +// } +//#endif namespace no_interruption_point { bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); @@ -306,12 +307,13 @@ namespace boost { non_interruptible_wait(abs_time); } -#ifdef BOOST_THREAD_USES_CHRONO - inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) - { - non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count()); - } -#endif +// #11322 sleep_for() nanoseconds overload will always return too early on windows +//#ifdef BOOST_THREAD_USES_CHRONO +// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) +// { +// non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count()); +// } +//#endif } } diff --git a/boost/thread/win32/thread_primitives.hpp b/boost/thread/win32/thread_primitives.hpp index d0d4f0aec3..b63503ad52 100644 --- a/boost/thread/win32/thread_primitives.hpp +++ b/boost/thread/win32/thread_primitives.hpp @@ -46,7 +46,7 @@ namespace boost unsigned const create_event_manual_reset = 0x00000001; unsigned const event_all_access = EVENT_ALL_ACCESS; unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS; - + # ifdef BOOST_NO_ANSI_APIS # if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA @@ -59,7 +59,7 @@ namespace boost using ::CreateSemaphoreExW; # endif using ::OpenEventW; - using ::GetModuleGandleW; + using ::GetModuleHandleW; # else using ::CreateMutexA; using ::CreateEventA; @@ -79,8 +79,8 @@ namespace boost using ::ReleaseSemaphore; using ::SetEvent; using ::ResetEvent; - using ::WaitForMultipleObjectsEx; - using ::WaitForSingleObjectEx; + using ::WaitForMultipleObjectsEx; + using ::WaitForSingleObjectEx; using ::GetCurrentProcessId; using ::GetCurrentThreadId; using ::GetCurrentThread; @@ -91,7 +91,7 @@ namespace boost using ::Sleep; using ::QueueUserAPC; using ::GetProcAddress; -#endif +#endif } } } @@ -286,7 +286,7 @@ namespace boost } // Oops, we weren't called often enough, we're stuck - return 0xFFFFFFFF; + return 0xFFFFFFFF; } #else #endif @@ -295,12 +295,12 @@ namespace boost static detail::gettickcount64_t gettickcount64impl; if(gettickcount64impl) return gettickcount64impl; - + // GetTickCount and GetModuleHandle are not allowed in the Windows Runtime, // and kernel32 isn't used in Windows Phone. #if BOOST_PLAT_WINDOWS_RUNTIME gettickcount64impl = &GetTickCount64; -#else +#else farproc_t addr=GetProcAddress( #if !defined(BOOST_NO_ANSI_APIS) GetModuleHandleA("KERNEL32.DLL"), @@ -312,7 +312,7 @@ namespace boost gettickcount64impl=(detail::gettickcount64_t) addr; else gettickcount64impl=&GetTickCount64emulation; -#endif +#endif return gettickcount64impl; } @@ -343,14 +343,14 @@ namespace boost handle const res = win32::CreateEventW(0, type, state, mutex_name); #else handle const res = win32::CreateEventExW( - 0, - mutex_name, + 0, + mutex_name, type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0, event_all_access); #endif return res; } - + inline handle create_anonymous_event(event_type type,initial_event_state state) { handle const res = create_event(0, type, state); @@ -374,7 +374,7 @@ namespace boost #endif return res; } - + inline handle create_anonymous_semaphore(long initial_count,long max_count) { handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count); @@ -402,20 +402,20 @@ namespace boost { BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0); } - + inline void get_system_info(system_info *info) { #if BOOST_PLAT_WINDOWS_RUNTIME - win32::GetNativeSystemInfo(info); + win32::GetNativeSystemInfo(info); #else win32::GetSystemInfo(info); #endif } - + inline void sleep(unsigned long milliseconds) { if(milliseconds == 0) - { + { #if BOOST_PLAT_WINDOWS_RUNTIME std::this_thread::yield(); #else @@ -425,13 +425,13 @@ namespace boost else { #if BOOST_PLAT_WINDOWS_RUNTIME - ::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0); + ::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0); #else ::boost::detail::win32::Sleep(milliseconds); #endif } } - + #if BOOST_PLAT_WINDOWS_RUNTIME class BOOST_THREAD_DECL scoped_winrt_thread { @@ -639,7 +639,7 @@ namespace boost } old=current; } - while(true); + while(true) ; return (old&value)!=0; } @@ -656,7 +656,7 @@ namespace boost } old=current; } - while(true); + while(true) ; return (old&value)!=0; } } |