Chris@16: // (C) Copyright 2008-10 Anthony Williams Chris@101: // (C) Copyright 2011-2015 Vicente J. Botet Escriba Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_THREAD_FUTURE_HPP Chris@16: #define BOOST_THREAD_FUTURE_HPP Chris@16: Chris@16: #include Chris@16: Chris@16: // boost::thread::future requires exception handling Chris@16: // due to boost::exception::exception_ptr dependency Chris@16: Chris@16: #ifndef BOOST_NO_EXCEPTIONS Chris@16: Chris@101: #include Chris@16: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: Chris@101: #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL Chris@101: #include Chris@101: #else Chris@101: #include Chris@101: #endif Chris@101: Chris@101: #include Chris@16: #include Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: #include Chris@16: #endif Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS Chris@16: #include Chris@101: #include Chris@101: #if ! defined BOOST_NO_CXX11_ALLOCATOR Chris@101: #include Chris@16: #endif Chris@101: #endif Chris@101: Chris@101: #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY Chris@101: #include Chris@101: #include Chris@101: #endif Chris@101: Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE Chris@16: #define BOOST_THREAD_FUTURE future Chris@16: #else Chris@16: #define BOOST_THREAD_FUTURE unique_future Chris@16: #endif Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: namespace detail Chris@16: { Chris@16: struct relocker Chris@16: { Chris@16: boost::unique_lock& lock_; Chris@16: Chris@16: relocker(boost::unique_lock& lk): Chris@16: lock_(lk) Chris@16: { Chris@16: lock_.unlock(); Chris@16: } Chris@16: ~relocker() Chris@16: { Chris@101: if (! lock_.owns_lock()) { Chris@16: lock_.lock(); Chris@16: } Chris@16: } Chris@16: void lock() { Chris@101: if (! lock_.owns_lock()) { Chris@16: lock_.lock(); Chris@16: } Chris@16: } Chris@16: private: Chris@16: relocker& operator=(relocker const&); Chris@16: }; Chris@16: Chris@16: struct shared_state_base : enable_shared_from_this Chris@16: { Chris@16: typedef std::list waiter_list; Chris@101: typedef waiter_list::iterator notify_when_ready_handle; Chris@16: // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout. Chris@16: typedef shared_ptr continuation_ptr_type; Chris@101: typedef std::vector continuations_type; Chris@16: Chris@16: boost::exception_ptr exception; Chris@16: bool done; Chris@101: bool is_valid_; Chris@16: bool is_deferred_; Chris@101: bool is_constructed; Chris@101: std::size_t cnt_; Chris@16: launch policy_; Chris@16: mutable boost::mutex mutex; Chris@16: boost::condition_variable waiters; Chris@16: waiter_list external_waiters; Chris@16: boost::function callback; Chris@16: // This declaration should be only included conditionally, but is included to maintain the same layout. Chris@101: continuations_type continuations; Chris@16: Chris@16: // This declaration should be only included conditionally, but is included to maintain the same layout. Chris@101: virtual void launch_continuation(boost::unique_lock&, shared_ptr) Chris@16: { Chris@16: } Chris@16: Chris@16: shared_state_base(): Chris@16: done(false), Chris@101: is_valid_(true), Chris@16: is_deferred_(false), Chris@101: is_constructed(false), Chris@101: cnt_(0), Chris@16: policy_(launch::none), Chris@101: continuations() Chris@16: {} Chris@16: virtual ~shared_state_base() Chris@101: { Chris@101: BOOST_ASSERT(cnt_==0); Chris@101: } Chris@101: virtual void block_if_needed(boost::unique_lock&) Chris@16: {} Chris@16: Chris@101: bool valid(boost::unique_lock&) { return is_valid_; } Chris@101: bool valid() { Chris@101: boost::unique_lock lk(this->mutex); Chris@101: return valid(lk); Chris@101: } Chris@101: void invalidate(boost::unique_lock&) { is_valid_ = false; } Chris@101: void invalidate() { Chris@101: boost::unique_lock lk(this->mutex); Chris@101: invalidate(lk); Chris@101: } Chris@101: void validate(boost::unique_lock&) { is_valid_ = true; } Chris@101: void validate() { Chris@101: boost::unique_lock lk(this->mutex); Chris@101: validate(lk); Chris@101: } Chris@101: Chris@101: void inc(boost::unique_lock&) { ++cnt_; } Chris@101: void inc() { boost::unique_lock lk(this->mutex); inc(lk); } Chris@101: Chris@101: void dec(boost::unique_lock& lk) { Chris@101: if (--cnt_ == 0) { Chris@101: block_if_needed(lk); Chris@101: } Chris@101: } Chris@101: void dec() { boost::unique_lock lk(this->mutex); dec(lk); } Chris@101: Chris@16: void set_deferred() Chris@16: { Chris@16: is_deferred_ = true; Chris@16: policy_ = launch::deferred; Chris@16: } Chris@16: void set_async() Chris@16: { Chris@16: is_deferred_ = false; Chris@16: policy_ = launch::async; Chris@16: } Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: void set_executor() Chris@16: { Chris@101: is_deferred_ = false; Chris@101: policy_ = launch::executor; Chris@101: } Chris@101: #endif Chris@101: notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv) Chris@101: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: do_callback(lock); Chris@16: return external_waiters.insert(external_waiters.end(),&cv); Chris@16: } Chris@16: Chris@101: void unnotify_when_ready(notify_when_ready_handle it) Chris@16: { Chris@101: boost::lock_guard lock(this->mutex); Chris@16: external_waiters.erase(it); Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@16: void do_continuation(boost::unique_lock& lock) Chris@16: { Chris@101: if (! continuations.empty()) { Chris@101: continuations_type the_continuations = continuations; Chris@101: continuations.clear(); Chris@101: relocker rlk(lock); Chris@101: for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { Chris@101: boost::unique_lock cont_lock((*it)->mutex); Chris@101: (*it)->launch_continuation(cont_lock, *it); Chris@101: } Chris@16: } Chris@16: } Chris@16: #else Chris@16: void do_continuation(boost::unique_lock&) Chris@16: { Chris@16: } Chris@16: #endif Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@101: virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock& lock) Chris@16: { Chris@101: continuations.push_back(continuation); Chris@16: if (done) { Chris@16: do_continuation(lock); Chris@16: } Chris@16: } Chris@16: #endif Chris@16: void mark_finished_internal(boost::unique_lock& lock) Chris@16: { Chris@16: done=true; Chris@16: waiters.notify_all(); Chris@16: for(waiter_list::const_iterator it=external_waiters.begin(), Chris@16: end=external_waiters.end();it!=end;++it) Chris@16: { Chris@16: (*it)->notify_all(); Chris@16: } Chris@16: do_continuation(lock); Chris@16: } Chris@16: void make_ready() Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: mark_finished_internal(lock); Chris@16: } Chris@16: Chris@16: void do_callback(boost::unique_lock& lock) Chris@16: { Chris@16: if(callback && !done) Chris@16: { Chris@16: boost::function local_callback=callback; Chris@16: relocker relock(lock); Chris@16: local_callback(); Chris@16: } Chris@16: } Chris@16: Chris@101: virtual bool run_if_is_deferred() Chris@101: { Chris@101: boost::unique_lock lk(this->mutex); Chris@101: if (is_deferred_) Chris@101: { Chris@101: is_deferred_=false; Chris@101: execute(lk); Chris@101: return true; Chris@101: } Chris@101: else Chris@101: return false; Chris@101: } Chris@101: virtual bool run_if_is_deferred_or_ready() Chris@101: { Chris@101: boost::unique_lock lk(this->mutex); Chris@101: if (is_deferred_) Chris@101: { Chris@101: is_deferred_=false; Chris@101: execute(lk); Chris@101: Chris@101: return true; Chris@101: } Chris@101: else Chris@101: return done; Chris@101: } Chris@16: void wait_internal(boost::unique_lock &lk, bool rethrow=true) Chris@16: { Chris@16: do_callback(lk); Chris@101: if (is_deferred_) Chris@16: { Chris@101: is_deferred_=false; Chris@101: execute(lk); Chris@101: } Chris@101: while(!done) Chris@101: { Chris@101: waiters.wait(lk); Chris@101: } Chris@101: if(rethrow && exception) Chris@101: { Chris@101: boost::rethrow_exception(exception); Chris@16: } Chris@16: } Chris@16: Chris@101: virtual void wait(boost::unique_lock& lock, bool rethrow=true) Chris@16: { Chris@16: wait_internal(lock, rethrow); Chris@16: } Chris@16: Chris@101: void wait(bool rethrow=true) Chris@101: { Chris@101: boost::unique_lock lock(this->mutex); Chris@101: wait(lock, rethrow); Chris@101: } Chris@101: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: bool timed_wait_until(boost::system_time const& target_time) Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: if (is_deferred_) Chris@16: return false; Chris@16: Chris@16: do_callback(lock); Chris@16: while(!done) Chris@16: { Chris@16: bool const success=waiters.timed_wait(lock,target_time); Chris@16: if(!success && !done) Chris@16: { Chris@16: return false; Chris@16: } Chris@16: } Chris@16: return true; Chris@16: } Chris@16: #endif Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: Chris@16: template Chris@16: future_status Chris@16: wait_until(const chrono::time_point& abs_time) Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: if (is_deferred_) Chris@16: return future_status::deferred; Chris@16: do_callback(lock); Chris@16: while(!done) Chris@16: { Chris@16: cv_status const st=waiters.wait_until(lock,abs_time); Chris@16: if(st==cv_status::timeout && !done) Chris@16: { Chris@16: return future_status::timeout; Chris@16: } Chris@16: } Chris@16: return future_status::ready; Chris@16: } Chris@16: #endif Chris@16: void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock& lock) Chris@16: { Chris@16: exception=e; Chris@16: mark_finished_internal(lock); Chris@16: } Chris@16: Chris@16: void mark_exceptional_finish() Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: mark_exceptional_finish_internal(boost::current_exception(), lock); Chris@16: } Chris@16: Chris@16: void set_exception_at_thread_exit(exception_ptr e) Chris@16: { Chris@101: unique_lock lk(this->mutex); Chris@16: if (has_value(lk)) Chris@16: { Chris@16: throw_exception(promise_already_satisfied()); Chris@16: } Chris@16: exception=e; Chris@16: this->is_constructed = true; Chris@16: detail::make_ready_at_thread_exit(shared_from_this()); Chris@16: } Chris@16: Chris@16: bool has_value() const Chris@16: { Chris@101: boost::lock_guard lock(this->mutex); Chris@101: return done && ! exception; Chris@16: } Chris@16: Chris@16: bool has_value(unique_lock& ) const Chris@16: { Chris@101: return done && ! exception; Chris@16: } Chris@16: Chris@16: bool has_exception() const Chris@16: { Chris@101: boost::lock_guard lock(this->mutex); Chris@101: return done && exception; Chris@16: } Chris@16: Chris@16: launch launch_policy(boost::unique_lock&) const Chris@16: { Chris@16: return policy_; Chris@16: } Chris@16: Chris@101: future_state::state get_state(boost::unique_lock& lk) const Chris@16: { Chris@16: if(!done) Chris@16: { Chris@16: return future_state::waiting; Chris@16: } Chris@16: else Chris@16: { Chris@16: return future_state::ready; Chris@16: } Chris@16: } Chris@101: future_state::state get_state() const Chris@101: { Chris@101: boost::lock_guard guard(this->mutex); Chris@101: if(!done) Chris@101: { Chris@101: return future_state::waiting; Chris@101: } Chris@101: else Chris@101: { Chris@101: return future_state::ready; Chris@101: } Chris@101: } Chris@16: Chris@16: exception_ptr get_exception_ptr() Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: wait_internal(lock, false); Chris@16: return exception; Chris@16: } Chris@16: Chris@16: template Chris@16: void set_wait_callback(F f,U* u) Chris@16: { Chris@101: boost::lock_guard lock(this->mutex); Chris@16: callback=boost::bind(f,boost::ref(*u)); Chris@16: } Chris@16: Chris@16: virtual void execute(boost::unique_lock&) {} Chris@16: Chris@16: private: Chris@16: shared_state_base(shared_state_base const&); Chris@16: shared_state_base& operator=(shared_state_base const&); Chris@16: }; Chris@16: Chris@16: // Used to create stand-alone futures Chris@16: template Chris@16: struct shared_state: Chris@16: detail::shared_state_base Chris@16: { Chris@101: #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL Chris@101: typedef boost::optional storage_type; Chris@101: #else Chris@101: typedef boost::csbl::unique_ptr storage_type; Chris@101: #endif Chris@101: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: typedef T const& source_reference_type; Chris@101: typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; Chris@101: typedef T move_dest_type; Chris@101: #elif defined BOOST_THREAD_USES_MOVE Chris@101: typedef typename conditional::value,T,T const&>::type source_reference_type; Chris@101: typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; Chris@101: typedef T move_dest_type; Chris@101: #else Chris@101: typedef T& source_reference_type; Chris@101: typedef typename conditional::value, BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; Chris@101: typedef typename conditional::value, BOOST_THREAD_RV_REF(T),T>::type move_dest_type; Chris@101: #endif Chris@101: Chris@101: typedef const T& shared_future_get_result_type; Chris@16: Chris@16: storage_type result; Chris@16: Chris@16: shared_state(): Chris@101: result() Chris@16: {} Chris@16: Chris@16: ~shared_state() Chris@16: {} Chris@16: Chris@16: void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock& lock) Chris@16: { Chris@101: #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL Chris@101: result = result_; Chris@16: #else Chris@101: result.reset(new T(result_)); Chris@16: #endif Chris@16: this->mark_finished_internal(lock); Chris@16: } Chris@16: Chris@101: void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock& lock) Chris@101: { Chris@101: #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL Chris@101: result = boost::move(result_); Chris@101: #elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: result.reset(new T(boost::move(result_))); Chris@101: #else Chris@101: result.reset(new T(static_cast(result_))); Chris@101: #endif Chris@101: this->mark_finished_internal(lock); Chris@101: } Chris@101: Chris@101: Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template Chris@101: void mark_finished_with_result_internal(boost::unique_lock& lock, BOOST_THREAD_FWD_REF(Args)... args) Chris@101: { Chris@101: #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL Chris@101: result.emplace(boost::forward(args)...); Chris@101: #else Chris@101: result.reset(new T(boost::forward(args)...)); Chris@101: #endif Chris@101: this->mark_finished_internal(lock); Chris@101: } Chris@101: #endif Chris@101: Chris@16: void mark_finished_with_result(source_reference_type result_) Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: this->mark_finished_with_result_internal(result_, lock); Chris@16: } Chris@16: Chris@16: void mark_finished_with_result(rvalue_source_type result_) Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: Chris@16: #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: mark_finished_with_result_internal(boost::move(result_), lock); Chris@16: #else Chris@16: mark_finished_with_result_internal(static_cast(result_), lock); Chris@16: #endif Chris@16: } Chris@16: Chris@101: storage_type& get_storage(boost::unique_lock& lk) Chris@16: { Chris@101: wait_internal(lk); Chris@101: return result; Chris@16: } Chris@101: virtual move_dest_type get(boost::unique_lock& lk) Chris@16: { Chris@101: return boost::move(*get_storage(lk)); Chris@16: } Chris@101: move_dest_type get() Chris@101: { Chris@101: boost::unique_lock lk(this->mutex); Chris@101: return this->get(lk); Chris@101: } Chris@101: Chris@101: virtual shared_future_get_result_type get_sh(boost::unique_lock& lk) Chris@101: { Chris@101: return *get_storage(lk); Chris@101: } Chris@101: shared_future_get_result_type get_sh() Chris@101: { Chris@101: boost::unique_lock lk(this->mutex); Chris@101: return this->get_sh(lk); Chris@101: } Chris@101: Chris@16: void set_value_at_thread_exit(source_reference_type result_) Chris@16: { Chris@16: unique_lock lk(this->mutex); Chris@16: if (this->has_value(lk)) Chris@16: { Chris@16: throw_exception(promise_already_satisfied()); Chris@16: } Chris@101: #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL Chris@101: result = result_; Chris@101: #else Chris@16: result.reset(new T(result_)); Chris@101: #endif Chris@16: Chris@16: this->is_constructed = true; Chris@16: detail::make_ready_at_thread_exit(shared_from_this()); Chris@16: } Chris@16: void set_value_at_thread_exit(rvalue_source_type result_) Chris@16: { Chris@16: unique_lock lk(this->mutex); Chris@16: if (this->has_value(lk)) Chris@16: throw_exception(promise_already_satisfied()); Chris@101: Chris@101: #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL Chris@101: result = boost::move(result_); Chris@101: #else Chris@101: result.reset(new T(boost::move(result_))); Chris@101: #endif Chris@101: #else Chris@101: #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL Chris@101: result = boost::move(result_); Chris@101: #else Chris@101: result.reset(new T(static_cast(result_))); Chris@101: #endif Chris@101: #endif Chris@16: this->is_constructed = true; Chris@16: detail::make_ready_at_thread_exit(shared_from_this()); Chris@16: } Chris@16: Chris@16: private: Chris@16: shared_state(shared_state const&); Chris@16: shared_state& operator=(shared_state const&); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct shared_state: Chris@16: detail::shared_state_base Chris@16: { Chris@101: typedef T* storage_type; Chris@101: typedef T& source_reference_type; Chris@101: typedef T& move_dest_type; Chris@101: typedef T& shared_future_get_result_type; Chris@16: Chris@16: T* result; Chris@16: Chris@16: shared_state(): Chris@16: result(0) Chris@16: {} Chris@16: Chris@16: ~shared_state() Chris@16: { Chris@16: } Chris@16: Chris@16: void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock& lock) Chris@16: { Chris@16: result= &result_; Chris@16: mark_finished_internal(lock); Chris@16: } Chris@16: Chris@16: void mark_finished_with_result(source_reference_type result_) Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: mark_finished_with_result_internal(result_, lock); Chris@16: } Chris@16: Chris@101: virtual T& get(boost::unique_lock& lock) Chris@16: { Chris@101: wait_internal(lock); Chris@16: return *result; Chris@16: } Chris@101: T& get() Chris@16: { Chris@101: boost::unique_lock lk(this->mutex); Chris@101: return get(lk); Chris@101: } Chris@101: Chris@101: virtual T& get_sh(boost::unique_lock& lock) Chris@101: { Chris@101: wait_internal(lock); Chris@16: return *result; Chris@16: } Chris@101: T& get_sh() Chris@101: { Chris@101: boost::unique_lock lock(this->mutex); Chris@101: return get_sh(lock); Chris@101: } Chris@16: Chris@16: void set_value_at_thread_exit(T& result_) Chris@16: { Chris@16: unique_lock lk(this->mutex); Chris@16: if (this->has_value(lk)) Chris@16: throw_exception(promise_already_satisfied()); Chris@16: result= &result_; Chris@16: this->is_constructed = true; Chris@16: detail::make_ready_at_thread_exit(shared_from_this()); Chris@16: } Chris@16: Chris@16: private: Chris@16: shared_state(shared_state const&); Chris@16: shared_state& operator=(shared_state const&); Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct shared_state: Chris@16: detail::shared_state_base Chris@16: { Chris@101: typedef void shared_future_get_result_type; Chris@101: typedef void move_dest_type; Chris@16: Chris@16: shared_state() Chris@16: {} Chris@16: Chris@16: void mark_finished_with_result_internal(boost::unique_lock& lock) Chris@16: { Chris@16: mark_finished_internal(lock); Chris@16: } Chris@16: Chris@16: void mark_finished_with_result() Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@16: mark_finished_with_result_internal(lock); Chris@16: } Chris@16: Chris@101: virtual void get(boost::unique_lock& lock) Chris@16: { Chris@101: this->wait_internal(lock); Chris@16: } Chris@101: void get() Chris@16: { Chris@101: boost::unique_lock lock(this->mutex); Chris@101: this->get(lock); Chris@101: } Chris@101: Chris@101: virtual void get_sh(boost::unique_lock& lock) Chris@101: { Chris@101: this->wait_internal(lock); Chris@101: } Chris@101: void get_sh() Chris@101: { Chris@101: boost::unique_lock lock(this->mutex); Chris@101: this->get_sh(lock); Chris@16: } Chris@16: Chris@16: void set_value_at_thread_exit() Chris@16: { Chris@16: unique_lock lk(this->mutex); Chris@16: if (this->has_value(lk)) Chris@16: { Chris@16: throw_exception(promise_already_satisfied()); Chris@16: } Chris@16: this->is_constructed = true; Chris@16: detail::make_ready_at_thread_exit(shared_from_this()); Chris@16: } Chris@16: private: Chris@16: shared_state(shared_state const&); Chris@16: shared_state& operator=(shared_state const&); Chris@16: }; Chris@16: Chris@16: ///////////////////////// Chris@16: /// future_async_shared_state_base Chris@16: ///////////////////////// Chris@16: template Chris@16: struct future_async_shared_state_base: shared_state Chris@16: { Chris@16: typedef shared_state base_type; Chris@16: protected: Chris@16: boost::thread thr_; Chris@16: void join() Chris@16: { Chris@16: if (thr_.joinable()) thr_.join(); Chris@16: } Chris@16: public: Chris@16: future_async_shared_state_base() Chris@16: { Chris@16: this->set_async(); Chris@16: } Chris@101: Chris@101: virtual void block_if_needed(boost::unique_lock& lk) Chris@16: { Chris@101: this->wait(lk, false); Chris@16: } Chris@16: Chris@16: ~future_async_shared_state_base() Chris@16: { Chris@16: join(); Chris@16: } Chris@16: Chris@101: virtual void wait(boost::unique_lock& lk, bool rethrow) Chris@16: { Chris@101: { Chris@101: relocker rlk(lk); Chris@101: join(); Chris@101: } Chris@101: this->base_type::wait(lk, rethrow); Chris@16: } Chris@16: }; Chris@16: Chris@16: ///////////////////////// Chris@16: /// future_async_shared_state Chris@16: ///////////////////////// Chris@16: template Chris@16: struct future_async_shared_state: future_async_shared_state_base Chris@16: { Chris@101: future_async_shared_state() Chris@16: { Chris@16: } Chris@16: Chris@101: void init(BOOST_THREAD_FWD_REF(Fp) f) Chris@16: { Chris@101: shared_ptr that = this->shared_from_this(); Chris@101: this->thr_ = thread(&future_async_shared_state::run, that, boost::forward(f)); Chris@101: } Chris@101: Chris@101: static void run(shared_ptr that_, BOOST_THREAD_FWD_REF(Fp) f) Chris@101: { Chris@101: future_async_shared_state* that = dynamic_cast(that_.get()); Chris@16: try Chris@16: { Chris@16: that->mark_finished_with_result(f()); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: that->mark_exceptional_finish(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct future_async_shared_state: public future_async_shared_state_base Chris@16: { Chris@101: void init(BOOST_THREAD_FWD_REF(Fp) f) Chris@16: { Chris@101: this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f)); Chris@16: } Chris@16: Chris@101: static void run(shared_ptr that_, BOOST_THREAD_FWD_REF(Fp) f) Chris@16: { Chris@101: future_async_shared_state* that = dynamic_cast(that_.get()); Chris@16: try Chris@16: { Chris@16: f(); Chris@16: that->mark_finished_with_result(); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: that->mark_exceptional_finish(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct future_async_shared_state: future_async_shared_state_base Chris@16: { Chris@101: void init(BOOST_THREAD_FWD_REF(Fp) f) Chris@16: { Chris@101: this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f)); Chris@16: } Chris@16: Chris@101: static void run(shared_ptr that_, BOOST_THREAD_FWD_REF(Fp) f) Chris@16: { Chris@101: future_async_shared_state* that = dynamic_cast(that_.get()); Chris@16: try Chris@16: { Chris@16: that->mark_finished_with_result(f()); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: that->mark_exceptional_finish(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: ////////////////////////// Chris@16: /// future_deferred_shared_state Chris@16: ////////////////////////// Chris@16: template Chris@16: struct future_deferred_shared_state: shared_state Chris@16: { Chris@16: typedef shared_state base_type; Chris@16: Fp func_; Chris@16: Chris@16: public: Chris@16: explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) Chris@101: : func_(boost::move(f)) Chris@16: { Chris@16: this->set_deferred(); Chris@16: } Chris@16: Chris@16: virtual void execute(boost::unique_lock& lck) { Chris@16: try Chris@16: { Chris@16: Fp local_fuct=boost::move(func_); Chris@16: relocker relock(lck); Chris@16: Rp res = local_fuct(); Chris@16: relock.lock(); Chris@16: this->mark_finished_with_result_internal(boost::move(res), lck); Chris@16: } Chris@16: catch (...) Chris@16: { Chris@16: this->mark_exceptional_finish_internal(current_exception(), lck); Chris@16: } Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct future_deferred_shared_state: shared_state Chris@16: { Chris@16: typedef shared_state base_type; Chris@16: Fp func_; Chris@16: Chris@16: public: Chris@16: explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) Chris@101: : func_(boost::move(f)) Chris@16: { Chris@16: this->set_deferred(); Chris@16: } Chris@16: Chris@16: virtual void execute(boost::unique_lock& lck) { Chris@16: try Chris@16: { Chris@16: this->mark_finished_with_result_internal(func_(), lck); Chris@16: } Chris@16: catch (...) Chris@16: { Chris@16: this->mark_exceptional_finish_internal(current_exception(), lck); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct future_deferred_shared_state: shared_state Chris@16: { Chris@16: typedef shared_state base_type; Chris@16: Fp func_; Chris@16: Chris@16: public: Chris@16: explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) Chris@101: : func_(boost::move(f)) Chris@16: { Chris@16: this->set_deferred(); Chris@16: } Chris@16: Chris@16: virtual void execute(boost::unique_lock& lck) { Chris@16: try Chris@16: { Chris@16: Fp local_fuct=boost::move(func_); Chris@16: relocker relock(lck); Chris@16: local_fuct(); Chris@16: relock.lock(); Chris@16: this->mark_finished_with_result_internal(lck); Chris@16: } Chris@16: catch (...) Chris@16: { Chris@16: this->mark_exceptional_finish_internal(current_exception(), lck); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: class future_waiter Chris@16: { Chris@16: struct registered_waiter; Chris@16: typedef std::vector::size_type count_type; Chris@16: Chris@16: struct registered_waiter Chris@16: { Chris@16: boost::shared_ptr future_; Chris@101: detail::shared_state_base::notify_when_ready_handle handle; Chris@16: count_type index; Chris@16: Chris@16: registered_waiter(boost::shared_ptr const& a_future, Chris@101: detail::shared_state_base::notify_when_ready_handle handle_, Chris@16: count_type index_): Chris@101: future_(a_future),handle(handle_),index(index_) Chris@16: {} Chris@16: }; Chris@16: Chris@16: struct all_futures_lock Chris@16: { Chris@16: #ifdef _MANAGED Chris@16: typedef std::ptrdiff_t count_type_portable; Chris@16: #else Chris@16: typedef count_type count_type_portable; Chris@16: #endif Chris@16: count_type_portable count; Chris@16: boost::scoped_array > locks; Chris@16: Chris@16: all_futures_lock(std::vector& futures): Chris@16: count(futures.size()),locks(new boost::unique_lock[count]) Chris@16: { Chris@16: for(count_type_portable i=0;i(futures[i].future_->mutex)); Chris@16: } Chris@16: } Chris@16: Chris@16: void lock() Chris@16: { Chris@16: boost::lock(locks.get(),locks.get()+count); Chris@16: } Chris@16: Chris@16: void unlock() Chris@16: { Chris@16: for(count_type_portable i=0;i futures_; Chris@16: count_type future_count; Chris@16: Chris@16: public: Chris@16: future_waiter(): Chris@16: future_count(0) Chris@16: {} Chris@16: Chris@16: template Chris@16: void add(F& f) Chris@16: { Chris@16: if(f.future_) Chris@16: { Chris@101: registered_waiter waiter(f.future_,f.future_->notify_when_ready(cv),future_count); Chris@101: try { Chris@101: futures_.push_back(waiter); Chris@101: } catch(...) { Chris@101: f.future_->unnotify_when_ready(waiter.handle); Chris@101: throw; Chris@101: } Chris@16: } Chris@16: ++future_count; Chris@16: } Chris@16: Chris@101: #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES Chris@101: template Chris@101: void add(F1& f1, Fs&... fs) Chris@101: { Chris@101: add(f1); add(fs...); Chris@101: } Chris@101: #endif Chris@101: Chris@16: count_type wait() Chris@16: { Chris@101: all_futures_lock lk(futures_); Chris@16: for(;;) Chris@16: { Chris@101: for(count_type i=0;idone) Chris@16: { Chris@101: return futures_[i].index; Chris@16: } Chris@16: } Chris@16: cv.wait(lk); Chris@16: } Chris@16: } Chris@16: Chris@16: ~future_waiter() Chris@16: { Chris@101: for(count_type i=0;iunnotify_when_ready(futures_[i].handle); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: } Chris@16: Chris@16: template Chris@16: class BOOST_THREAD_FUTURE; Chris@16: Chris@16: template Chris@16: class shared_future; Chris@16: Chris@16: template Chris@101: struct is_future_type > : true_type Chris@16: { Chris@16: }; Chris@16: Chris@16: template Chris@101: struct is_future_type > : true_type Chris@16: { Chris@16: }; Chris@16: Chris@101: // template Chris@101: // typename boost::disable_if,Iterator>::type wait_for_any(Iterator begin,Iterator end) Chris@101: // { Chris@101: // if(begin==end) Chris@101: // return end; Chris@101: // Chris@101: // detail::future_waiter waiter; Chris@101: // for(Iterator current=begin;current!=end;++current) Chris@101: // { Chris@101: // waiter.add(*current); Chris@101: // } Chris@101: // return boost::next(begin,waiter.wait()); Chris@101: // } Chris@101: Chris@101: #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES Chris@16: template Chris@16: typename boost::enable_if,unsigned>::type wait_for_any(F1& f1,F2& f2) Chris@16: { Chris@16: detail::future_waiter waiter; Chris@16: waiter.add(f1); Chris@16: waiter.add(f2); Chris@16: return waiter.wait(); Chris@16: } Chris@16: Chris@16: template Chris@16: unsigned wait_for_any(F1& f1,F2& f2,F3& f3) Chris@16: { Chris@16: detail::future_waiter waiter; Chris@16: waiter.add(f1); Chris@16: waiter.add(f2); Chris@16: waiter.add(f3); Chris@16: return waiter.wait(); Chris@16: } Chris@16: Chris@16: template Chris@16: unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4) Chris@16: { Chris@16: detail::future_waiter waiter; Chris@16: waiter.add(f1); Chris@16: waiter.add(f2); Chris@16: waiter.add(f3); Chris@16: waiter.add(f4); Chris@16: return waiter.wait(); Chris@16: } Chris@16: Chris@16: template Chris@16: unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) Chris@16: { Chris@16: detail::future_waiter waiter; Chris@16: waiter.add(f1); Chris@16: waiter.add(f2); Chris@16: waiter.add(f3); Chris@16: waiter.add(f4); Chris@16: waiter.add(f5); Chris@16: return waiter.wait(); Chris@16: } Chris@101: #else Chris@101: template Chris@101: typename boost::enable_if, unsigned>::type wait_for_any(F1& f1, Fs&... fs) Chris@101: { Chris@101: detail::future_waiter waiter; Chris@101: waiter.add(f1, fs...); Chris@101: return waiter.wait(); Chris@101: } Chris@101: #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: template Chris@16: class promise; Chris@16: Chris@16: template Chris@16: class packaged_task; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: /// Common implementation for all the futures independently of the return type Chris@16: class base_future Chris@16: { Chris@101: public: Chris@16: }; Chris@16: /// Common implementation for future and shared_future. Chris@16: template Chris@16: class basic_future : public base_future Chris@16: { Chris@16: protected: Chris@16: public: Chris@16: Chris@16: typedef boost::shared_ptr > future_ptr; Chris@101: typedef typename detail::shared_state::move_dest_type move_dest_type; Chris@101: Chris@101: static //BOOST_CONSTEXPR Chris@101: future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) { Chris@101: promise p; Chris@101: p.set_exception(ex.ptr_); Chris@101: return p.get_future().future_; Chris@101: } Chris@101: Chris@101: void set_exceptional_if_invalid() { Chris@101: if (valid()) return; Chris@101: promise p; Chris@101: p.set_exception(future_uninitialized()); Chris@101: future_ = p.get_future().future_; Chris@101: } Chris@16: Chris@16: future_ptr future_; Chris@16: Chris@16: basic_future(future_ptr a_future): Chris@16: future_(a_future) Chris@16: { Chris@101: if (a_future) a_future->inc(); Chris@16: } Chris@16: Chris@16: public: Chris@16: typedef future_state::state state; Chris@16: Chris@101: BOOST_THREAD_MOVABLE_ONLY(basic_future) Chris@16: basic_future(): future_() {} Chris@101: Chris@101: Chris@101: //BOOST_CONSTEXPR Chris@101: basic_future(exceptional_ptr const& ex) Chris@101: : future_(make_exceptional_future_ptr(ex)) Chris@101: { Chris@101: future_->inc(); Chris@101: } Chris@101: Chris@101: ~basic_future() { Chris@101: if (future_) future_->dec(); Chris@101: } Chris@16: Chris@16: basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT: Chris@16: future_(BOOST_THREAD_RV(other).future_) Chris@16: { Chris@16: BOOST_THREAD_RV(other).future_.reset(); Chris@16: } Chris@16: basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT Chris@16: { Chris@101: if (this->future_) { Chris@101: this->future_->dec(); Chris@101: } Chris@16: future_=BOOST_THREAD_RV(other).future_; Chris@16: BOOST_THREAD_RV(other).future_.reset(); Chris@16: return *this; Chris@16: } Chris@16: void swap(basic_future& that) BOOST_NOEXCEPT Chris@16: { Chris@16: future_.swap(that.future_); Chris@16: } Chris@16: // functions to check state, and wait for ready Chris@101: state get_state(boost::unique_lock& lk) const Chris@101: { Chris@101: if(!future_) Chris@101: { Chris@101: return future_state::uninitialized; Chris@101: } Chris@101: return future_->get_state(lk); Chris@101: } Chris@16: state get_state() const Chris@16: { Chris@16: if(!future_) Chris@16: { Chris@16: return future_state::uninitialized; Chris@16: } Chris@16: return future_->get_state(); Chris@16: } Chris@16: Chris@16: bool is_ready() const Chris@16: { Chris@16: return get_state()==future_state::ready; Chris@16: } Chris@16: Chris@101: bool is_ready(boost::unique_lock& lk) const Chris@101: { Chris@101: return get_state(lk)==future_state::ready; Chris@101: } Chris@16: bool has_exception() const Chris@16: { Chris@16: return future_ && future_->has_exception(); Chris@16: } Chris@16: Chris@16: bool has_value() const Chris@16: { Chris@16: return future_ && future_->has_value(); Chris@16: } Chris@16: Chris@16: launch launch_policy(boost::unique_lock& lk) const Chris@16: { Chris@16: if ( future_ ) return future_->launch_policy(lk); Chris@16: else return launch(launch::none); Chris@16: } Chris@16: Chris@16: exception_ptr get_exception_ptr() Chris@16: { Chris@16: return future_ Chris@16: ? future_->get_exception_ptr() Chris@16: : exception_ptr(); Chris@16: } Chris@16: Chris@16: bool valid() const BOOST_NOEXCEPT Chris@16: { Chris@101: return future_ != 0 && future_->valid(); Chris@16: } Chris@16: Chris@16: void wait() const Chris@16: { Chris@16: if(!future_) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@16: future_->wait(false); Chris@16: } Chris@16: Chris@101: typedef detail::shared_state_base::notify_when_ready_handle notify_when_ready_handle; Chris@101: Chris@101: boost::mutex& mutex() { Chris@101: if(!future_) Chris@101: { Chris@101: boost::throw_exception(future_uninitialized()); Chris@101: } Chris@101: return future_->mutex; Chris@101: }; Chris@101: Chris@101: notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv) Chris@101: { Chris@101: if(!future_) Chris@101: { Chris@101: boost::throw_exception(future_uninitialized()); Chris@101: } Chris@101: return future_->notify_when_ready(cv); Chris@101: } Chris@101: Chris@101: void unnotify_when_ready(notify_when_ready_handle h) Chris@101: { Chris@101: if(!future_) Chris@101: { Chris@101: boost::throw_exception(future_uninitialized()); Chris@101: } Chris@101: return future_->unnotify_when_ready(h); Chris@101: } Chris@101: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: template Chris@16: bool timed_wait(Duration const& rel_time) const Chris@16: { Chris@16: return timed_wait_until(boost::get_system_time()+rel_time); Chris@16: } Chris@16: Chris@16: bool timed_wait_until(boost::system_time const& abs_time) const Chris@16: { Chris@16: if(!future_) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@16: return future_->timed_wait_until(abs_time); Chris@16: } Chris@16: #endif Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: template Chris@16: future_status Chris@16: wait_for(const chrono::duration& rel_time) const Chris@16: { Chris@16: return wait_until(chrono::steady_clock::now() + rel_time); Chris@16: Chris@16: } Chris@16: template Chris@16: future_status Chris@16: wait_until(const chrono::time_point& abs_time) const Chris@16: { Chris@16: if(!future_) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@16: return future_->wait_until(abs_time); Chris@16: } Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: } // detail Chris@16: BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future BOOST_THREAD_DCL_MOVABLE_END Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: #if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005 Chris@16: template Chris@16: BOOST_THREAD_FUTURE Chris@16: make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); Chris@16: Chris@16: template Chris@16: BOOST_THREAD_FUTURE Chris@16: make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); Chris@16: #endif // #if (!defined _MSC_VER || _MSC_VER >= 1400) Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@16: template Chris@16: struct future_deferred_continuation_shared_state; Chris@16: template Chris@16: struct future_async_continuation_shared_state; Chris@16: Chris@16: template Chris@16: BOOST_THREAD_FUTURE Chris@16: make_future_async_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); Chris@16: Chris@16: template Chris@16: BOOST_THREAD_FUTURE Chris@16: make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); Chris@16: #endif Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP Chris@16: template Chris@16: struct future_unwrap_shared_state; Chris@16: template Chris@16: inline BOOST_THREAD_FUTURE Chris@16: make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f); Chris@16: #endif Chris@16: } Chris@16: Chris@16: template Chris@16: class BOOST_THREAD_FUTURE : public detail::basic_future Chris@16: { Chris@16: private: Chris@16: typedef detail::basic_future base_type; Chris@16: typedef typename base_type::future_ptr future_ptr; Chris@16: Chris@16: friend class shared_future; Chris@16: friend class promise; Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@16: template Chris@16: friend struct detail::future_async_continuation_shared_state; Chris@16: template Chris@16: friend struct detail::future_deferred_continuation_shared_state; Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_async_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); Chris@16: #endif Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP Chris@16: template Chris@16: friend struct detail::future_unwrap_shared_state; Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f); Chris@16: #endif Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: template friend class packaged_task; // todo check if this works in windows Chris@16: #else Chris@16: friend class packaged_task; Chris@16: #endif Chris@16: friend class detail::future_waiter; Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); Chris@16: Chris@16: Chris@101: typedef typename base_type::move_dest_type move_dest_type; Chris@101: public: // when_all Chris@16: Chris@16: BOOST_THREAD_FUTURE(future_ptr a_future): Chris@16: base_type(a_future) Chris@16: { Chris@16: } Chris@16: Chris@16: public: Chris@16: BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) Chris@16: typedef future_state::state state; Chris@16: typedef R value_type; // EXTENSION Chris@16: Chris@16: BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} Chris@101: //BOOST_CONSTEXPR Chris@101: BOOST_THREAD_FUTURE(exceptional_ptr const& ex): Chris@101: base_type(ex) {} Chris@16: Chris@16: ~BOOST_THREAD_FUTURE() {} Chris@16: Chris@16: BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: Chris@16: base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) Chris@16: { Chris@16: } Chris@16: inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE >) other); // EXTENSION Chris@16: Chris@101: explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future) other) : Chris@101: base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) Chris@101: {} Chris@101: Chris@16: BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT Chris@16: { Chris@16: this->base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: shared_future share() Chris@16: { Chris@16: return shared_future(::boost::move(*this)); Chris@16: } Chris@16: Chris@16: void swap(BOOST_THREAD_FUTURE& other) Chris@16: { Chris@16: static_cast(this)->swap(other); Chris@16: } Chris@16: Chris@16: // todo this function must be private and friendship provided to the internal users. Chris@16: void set_async() Chris@16: { Chris@16: this->future_->set_async(); Chris@16: } Chris@16: // todo this function must be private and friendship provided to the internal users. Chris@16: void set_deferred() Chris@16: { Chris@16: this->future_->set_deferred(); Chris@16: } Chris@101: bool run_if_is_deferred() { Chris@101: return this->future_->run_if_is_deferred(); Chris@101: } Chris@101: bool run_if_is_deferred_or_ready() { Chris@101: return this->future_->run_if_is_deferred_or_ready(); Chris@101: } Chris@16: // retrieving the value Chris@16: move_dest_type get() Chris@16: { Chris@101: if (this->future_ == 0) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@101: unique_lock lk(this->future_->mutex); Chris@101: if (! this->future_->valid(lk)) Chris@101: { Chris@101: boost::throw_exception(future_uninitialized()); Chris@101: } Chris@16: #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET Chris@101: this->future_->invalidate(lk); Chris@16: #endif Chris@101: return this->future_->get(lk); Chris@16: } Chris@16: Chris@16: template Chris@16: typename boost::disable_if< is_void, move_dest_type>::type Chris@16: get_or(BOOST_THREAD_RV_REF(R2) v) Chris@16: { Chris@101: Chris@101: if (this->future_ == 0) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@101: unique_lock lk(this->future_->mutex); Chris@101: if (! this->future_->valid(lk)) Chris@101: { Chris@101: boost::throw_exception(future_uninitialized()); Chris@101: } Chris@101: this->future_->wait(lk, false); Chris@16: #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET Chris@101: this->future_->invalidate(lk); Chris@16: #endif Chris@101: Chris@101: if (this->future_->has_value(lk)) { Chris@101: return this->future_->get(lk); Chris@16: } Chris@16: else { Chris@16: return boost::move(v); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: typename boost::disable_if< is_void, move_dest_type>::type Chris@16: get_or(R2 const& v) // EXTENSION Chris@16: { Chris@101: if (this->future_ == 0) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@101: unique_lock lk(this->future_->mutex); Chris@101: if (! this->future_->valid(lk)) Chris@101: { Chris@101: boost::throw_exception(future_uninitialized()); Chris@101: } Chris@101: this->future_->wait(lk, false); Chris@16: #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET Chris@101: this->future_->invalidate(lk); Chris@16: #endif Chris@101: if (this->future_->has_value(lk)) { Chris@101: return this->future_->get(lk); Chris@16: } Chris@16: else { Chris@16: return v; Chris@16: } Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@16: template Chris@16: inline BOOST_THREAD_FUTURE::type> Chris@16: then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION Chris@16: template Chris@16: inline BOOST_THREAD_FUTURE::type> Chris@16: then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: template Chris@101: inline BOOST_THREAD_FUTURE::type> Chris@101: then(Ex& ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION Chris@101: #endif Chris@16: Chris@16: template Chris@16: inline typename boost::disable_if< is_void, BOOST_THREAD_FUTURE >::type Chris@16: fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION Chris@16: template Chris@16: inline typename boost::disable_if< is_void, BOOST_THREAD_FUTURE >::type Chris@16: fallback_to(R2 const& v); // EXTENSION Chris@16: Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE BOOST_THREAD_DCL_MOVABLE_END Chris@16: Chris@16: template Chris@16: class BOOST_THREAD_FUTURE > : public detail::basic_future > Chris@16: { Chris@16: typedef BOOST_THREAD_FUTURE R; Chris@16: Chris@16: private: Chris@16: typedef detail::basic_future base_type; Chris@16: typedef typename base_type::future_ptr future_ptr; Chris@16: Chris@16: friend class shared_future; Chris@16: friend class promise; Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@16: template Chris@16: friend struct detail::future_async_continuation_shared_state; Chris@16: template Chris@16: friend struct detail::future_deferred_continuation_shared_state; Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_async_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); Chris@16: #endif Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP Chris@16: template Chris@16: friend struct detail::future_unwrap_shared_state; Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f); Chris@16: #endif Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: template friend class packaged_task; // todo check if this works in windows Chris@16: #else Chris@16: friend class packaged_task; Chris@16: #endif Chris@16: friend class detail::future_waiter; Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); Chris@16: Chris@101: typedef typename base_type::move_dest_type move_dest_type; Chris@16: Chris@16: BOOST_THREAD_FUTURE(future_ptr a_future): Chris@16: base_type(a_future) Chris@16: { Chris@16: } Chris@16: Chris@16: public: Chris@16: BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) Chris@16: typedef future_state::state state; Chris@16: typedef R value_type; // EXTENSION Chris@16: Chris@16: BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} Chris@101: //BOOST_CONSTEXPR Chris@101: BOOST_THREAD_FUTURE(exceptional_ptr const& ex): Chris@101: base_type(ex) {} Chris@16: Chris@16: ~BOOST_THREAD_FUTURE() {} Chris@16: Chris@16: BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: Chris@16: base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) Chris@16: { Chris@16: } Chris@16: Chris@16: BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT Chris@16: { Chris@16: this->base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: shared_future share() Chris@16: { Chris@16: return shared_future(::boost::move(*this)); Chris@16: } Chris@16: Chris@16: void swap(BOOST_THREAD_FUTURE& other) Chris@16: { Chris@16: static_cast(this)->swap(other); Chris@16: } Chris@16: Chris@16: // todo this function must be private and friendship provided to the internal users. Chris@16: void set_async() Chris@16: { Chris@16: this->future_->set_async(); Chris@16: } Chris@16: // todo this function must be private and friendship provided to the internal users. Chris@16: void set_deferred() Chris@16: { Chris@16: this->future_->set_deferred(); Chris@16: } Chris@101: bool run_if_is_deferred() { Chris@101: return this->future_->run_if_is_deferred(); Chris@101: } Chris@101: bool run_if_is_deferred_or_ready() { Chris@101: return this->future_->run_if_is_deferred_or_ready(); Chris@101: } Chris@16: // retrieving the value Chris@16: move_dest_type get() Chris@16: { Chris@101: if (this->future_ == 0) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@101: unique_lock lk(this->future_->mutex); Chris@101: if (! this->future_->valid(lk)) Chris@101: { Chris@101: boost::throw_exception(future_uninitialized()); Chris@101: } Chris@16: #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET Chris@101: this->future_->invalidate(lk); Chris@16: #endif Chris@101: return this->future_->get(lk); Chris@16: } Chris@16: move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION Chris@16: { Chris@101: if (this->future_ == 0) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@101: unique_lock lk(this->future_->mutex); Chris@101: if (! this->future_->valid(lk)) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@101: this->future_->wait(lk, false); Chris@16: #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET Chris@101: this->future_->invalidate(lk); Chris@16: #endif Chris@101: if (this->future_->has_value(lk)) return this->future_->get(lk); Chris@101: else return boost::move(v); Chris@101: } Chris@101: Chris@101: move_dest_type get_or(R const& v) // EXTENSION Chris@101: { Chris@101: if (this->future_ == 0) Chris@101: { Chris@101: boost::throw_exception(future_uninitialized()); Chris@101: } Chris@101: unique_lock lk(this->future_->mutex); Chris@101: if (! this->future_->valid(lk)) Chris@101: { Chris@101: boost::throw_exception(future_uninitialized()); Chris@101: } Chris@101: this->future_->wait(lk, false); Chris@101: #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET Chris@101: this->future_->invalidate(lk); Chris@101: #endif Chris@101: if (this->future_->has_value(lk)) return this->future_->get(lk); Chris@16: else return v; Chris@16: } Chris@16: Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@16: template Chris@16: inline BOOST_THREAD_FUTURE::type> Chris@16: then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION Chris@16: template Chris@16: inline BOOST_THREAD_FUTURE::type> Chris@16: then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: template Chris@101: inline BOOST_THREAD_FUTURE::type> Chris@101: then(Ex &ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION Chris@101: #endif Chris@16: #endif Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP Chris@16: inline Chris@16: BOOST_THREAD_FUTURE Chris@16: unwrap(); // EXTENSION Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: template Chris@16: class shared_future : public detail::basic_future Chris@16: { Chris@16: typedef detail::basic_future base_type; Chris@16: typedef typename base_type::future_ptr future_ptr; Chris@16: Chris@16: friend class detail::future_waiter; Chris@16: friend class promise; Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@16: template Chris@16: friend struct detail::future_async_continuation_shared_state; Chris@16: template Chris@16: friend struct detail::future_deferred_continuation_shared_state; Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_async_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); Chris@16: Chris@16: template Chris@16: friend BOOST_THREAD_FUTURE Chris@16: detail::make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); Chris@16: #endif Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: template friend class packaged_task;// todo check if this works in windows Chris@16: #else Chris@16: friend class packaged_task; Chris@16: #endif Chris@16: shared_future(future_ptr a_future): Chris@16: base_type(a_future) Chris@16: {} Chris@16: Chris@16: public: Chris@101: BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future) Chris@16: typedef R value_type; // EXTENSION Chris@16: Chris@16: shared_future(shared_future const& other): Chris@101: base_type(other.future_) Chris@16: {} Chris@16: Chris@16: typedef future_state::state state; Chris@16: Chris@16: BOOST_CONSTEXPR shared_future() Chris@16: {} Chris@101: //BOOST_CONSTEXPR Chris@101: shared_future(exceptional_ptr const& ex): Chris@101: base_type(ex) {} Chris@16: ~shared_future() Chris@16: {} Chris@16: Chris@101: shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other) Chris@16: { Chris@101: if (other.future_) { Chris@101: other.future_->inc(); Chris@101: } Chris@101: if (this->future_) { Chris@101: this->future_->dec(); Chris@101: } Chris@101: this->future_ = other.future_; Chris@16: return *this; Chris@16: } Chris@101: Chris@16: shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT : Chris@16: base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) Chris@16: { Chris@16: } Chris@16: shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE ) other) BOOST_NOEXCEPT : Chris@16: base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) Chris@16: { Chris@16: } Chris@16: Chris@16: shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT Chris@16: { Chris@16: base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); Chris@16: return *this; Chris@16: } Chris@16: shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE ) other) BOOST_NOEXCEPT Chris@16: { Chris@16: base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(shared_future& other) BOOST_NOEXCEPT Chris@16: { Chris@16: static_cast(this)->swap(other); Chris@16: } Chris@101: bool run_if_is_deferred() { Chris@101: return this->future_->run_if_is_deferred(); Chris@101: } Chris@101: bool run_if_is_deferred_or_ready() { Chris@101: return this->future_->run_if_is_deferred_or_ready(); Chris@101: } Chris@16: // retrieving the value Chris@101: typename detail::shared_state::shared_future_get_result_type get() const Chris@16: { Chris@16: if(!this->future_) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@16: return this->future_->get_sh(); Chris@16: } Chris@16: Chris@16: template Chris@16: typename boost::disable_if< is_void, typename detail::shared_state::shared_future_get_result_type>::type Chris@101: get_or(BOOST_THREAD_RV_REF(R2) v) const // EXTENSION Chris@16: { Chris@16: if(!this->future_) Chris@16: { Chris@16: boost::throw_exception(future_uninitialized()); Chris@16: } Chris@101: this->future_->wait(); Chris@101: if (this->future_->has_value()) return this->future_->get_sh(); Chris@16: else return boost::move(v); Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@16: template Chris@16: inline BOOST_THREAD_FUTURE::type> Chris@101: then(BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION Chris@16: template Chris@16: inline BOOST_THREAD_FUTURE::type> Chris@101: then(launch policy, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: template Chris@101: inline BOOST_THREAD_FUTURE::type> Chris@101: then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION Chris@101: #endif Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future BOOST_THREAD_DCL_MOVABLE_END Chris@16: Chris@16: template Chris@16: class promise Chris@16: { Chris@16: typedef boost::shared_ptr > future_ptr; Chris@16: Chris@101: typedef typename detail::shared_state::source_reference_type source_reference_type; Chris@101: typedef typename detail::shared_state::rvalue_source_type rvalue_source_type; Chris@101: typedef typename detail::shared_state::move_dest_type move_dest_type; Chris@101: typedef typename detail::shared_state::shared_future_get_result_type shared_future_get_result_type; Chris@101: Chris@16: future_ptr future_; Chris@16: bool future_obtained; Chris@16: Chris@16: void lazy_init() Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY Chris@16: #include Chris@16: if(!atomic_load(&future_)) Chris@16: { Chris@16: future_ptr blank; Chris@16: atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state)); Chris@16: } Chris@16: #include Chris@16: #endif Chris@16: } Chris@16: Chris@16: public: Chris@16: BOOST_THREAD_MOVABLE_ONLY(promise) Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS Chris@16: template Chris@16: promise(boost::allocator_arg_t, Allocator a) Chris@16: { Chris@16: typedef typename Allocator::template rebind >::other A2; Chris@16: A2 a2(a); Chris@16: typedef thread_detail::allocator_destructor D; Chris@16: Chris@16: future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state(), D(a2, 1) ); Chris@16: future_obtained = false; Chris@16: } Chris@16: #endif Chris@16: promise(): Chris@16: #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY Chris@16: future_(), Chris@16: #else Chris@16: future_(new detail::shared_state()), Chris@16: #endif Chris@16: future_obtained(false) Chris@16: {} Chris@16: Chris@16: ~promise() Chris@16: { Chris@16: if(future_) Chris@16: { Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: Chris@16: if(!future_->done && !future_->is_constructed) Chris@16: { Chris@16: future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : Chris@16: future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) Chris@16: { Chris@16: BOOST_THREAD_RV(rhs).future_.reset(); Chris@16: BOOST_THREAD_RV(rhs).future_obtained=false; Chris@16: } Chris@16: promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT Chris@16: { Chris@16: future_=BOOST_THREAD_RV(rhs).future_; Chris@16: future_obtained=BOOST_THREAD_RV(rhs).future_obtained; Chris@16: BOOST_THREAD_RV(rhs).future_.reset(); Chris@16: BOOST_THREAD_RV(rhs).future_obtained=false; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(promise& other) Chris@16: { Chris@16: future_.swap(other.future_); Chris@16: std::swap(future_obtained,other.future_obtained); Chris@16: } Chris@16: Chris@16: // Result retrieval Chris@16: BOOST_THREAD_FUTURE get_future() Chris@16: { Chris@16: lazy_init(); Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: if (future_obtained) Chris@16: { Chris@16: boost::throw_exception(future_already_retrieved()); Chris@16: } Chris@16: future_obtained=true; Chris@16: return BOOST_THREAD_FUTURE(future_); Chris@16: } Chris@16: Chris@101: #if defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: template Chris@101: typename boost::enable_if_c::value && is_same::value, void>::type set_value(TR const & r) Chris@16: { Chris@16: lazy_init(); Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: if(future_->done) Chris@16: { Chris@16: boost::throw_exception(promise_already_satisfied()); Chris@16: } Chris@16: future_->mark_finished_with_result_internal(r, lock); Chris@16: } Chris@101: #else Chris@101: void set_value(source_reference_type r) Chris@101: { Chris@101: lazy_init(); Chris@101: boost::unique_lock lock(future_->mutex); Chris@101: if(future_->done) Chris@101: { Chris@101: boost::throw_exception(promise_already_satisfied()); Chris@101: } Chris@101: future_->mark_finished_with_result_internal(r, lock); Chris@101: } Chris@101: #endif Chris@101: Chris@101: void set_value(rvalue_source_type r) Chris@16: { Chris@16: lazy_init(); Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: if(future_->done) Chris@16: { Chris@16: boost::throw_exception(promise_already_satisfied()); Chris@16: } Chris@16: #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: future_->mark_finished_with_result_internal(boost::move(r), lock); Chris@16: #else Chris@101: future_->mark_finished_with_result_internal(static_cast(r), lock); Chris@16: #endif Chris@16: } Chris@16: Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template Chris@101: void emplace(BOOST_THREAD_FWD_REF(Args) ...args) Chris@101: { Chris@101: lazy_init(); Chris@101: boost::unique_lock lock(future_->mutex); Chris@101: if(future_->done) Chris@101: { Chris@101: boost::throw_exception(promise_already_satisfied()); Chris@101: } Chris@101: future_->mark_finished_with_result_internal(lock, boost::forward(args)...); Chris@101: } Chris@101: Chris@101: #endif Chris@101: Chris@16: void set_exception(boost::exception_ptr p) Chris@16: { Chris@16: lazy_init(); Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: if(future_->done) Chris@16: { Chris@16: boost::throw_exception(promise_already_satisfied()); Chris@16: } Chris@16: future_->mark_exceptional_finish_internal(p, lock); Chris@16: } Chris@16: template Chris@16: void set_exception(E ex) Chris@16: { Chris@101: set_exception(boost::copy_exception(ex)); Chris@16: } Chris@16: // setting the result with deferred notification Chris@101: #if defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: template Chris@101: typename boost::enable_if_c::value && is_same::value, void>::type set_value_at_thread_exit(TR const& r) Chris@16: { Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: future_->set_value_at_thread_exit(r); Chris@16: } Chris@101: #else Chris@101: void set_value_at_thread_exit(source_reference_type r) Chris@101: { Chris@101: if (future_.get()==0) Chris@101: { Chris@101: boost::throw_exception(promise_moved()); Chris@101: } Chris@101: future_->set_value_at_thread_exit(r); Chris@101: } Chris@101: #endif Chris@16: void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r) Chris@16: { Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: future_->set_value_at_thread_exit(boost::move(r)); Chris@16: } Chris@16: void set_exception_at_thread_exit(exception_ptr e) Chris@16: { Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: future_->set_exception_at_thread_exit(e); Chris@16: } Chris@16: template Chris@16: void set_exception_at_thread_exit(E ex) Chris@16: { Chris@101: set_exception_at_thread_exit(boost::copy_exception(ex)); Chris@16: } Chris@16: Chris@16: template Chris@16: void set_wait_callback(F f) Chris@16: { Chris@16: lazy_init(); Chris@16: future_->set_wait_callback(f,this); Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: template Chris@16: class promise Chris@16: { Chris@16: typedef boost::shared_ptr > future_ptr; Chris@16: Chris@16: future_ptr future_; Chris@16: bool future_obtained; Chris@16: Chris@16: void lazy_init() Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY Chris@16: #include Chris@16: if(!atomic_load(&future_)) Chris@16: { Chris@16: future_ptr blank; Chris@16: atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state)); Chris@16: } Chris@16: #include Chris@16: #endif Chris@16: } Chris@16: Chris@16: public: Chris@16: BOOST_THREAD_MOVABLE_ONLY(promise) Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS Chris@16: template Chris@16: promise(boost::allocator_arg_t, Allocator a) Chris@16: { Chris@16: typedef typename Allocator::template rebind >::other A2; Chris@16: A2 a2(a); Chris@16: typedef thread_detail::allocator_destructor D; Chris@16: Chris@16: future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state(), D(a2, 1) ); Chris@16: future_obtained = false; Chris@16: } Chris@16: #endif Chris@16: promise(): Chris@16: #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY Chris@16: future_(), Chris@16: #else Chris@16: future_(new detail::shared_state()), Chris@16: #endif Chris@16: future_obtained(false) Chris@16: {} Chris@16: Chris@16: ~promise() Chris@16: { Chris@16: if(future_) Chris@16: { Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: Chris@16: if(!future_->done && !future_->is_constructed) Chris@16: { Chris@16: future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : Chris@16: future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) Chris@16: { Chris@16: BOOST_THREAD_RV(rhs).future_.reset(); Chris@16: BOOST_THREAD_RV(rhs).future_obtained=false; Chris@16: } Chris@16: promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT Chris@16: { Chris@16: future_=BOOST_THREAD_RV(rhs).future_; Chris@16: future_obtained=BOOST_THREAD_RV(rhs).future_obtained; Chris@16: BOOST_THREAD_RV(rhs).future_.reset(); Chris@16: BOOST_THREAD_RV(rhs).future_obtained=false; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(promise& other) Chris@16: { Chris@16: future_.swap(other.future_); Chris@16: std::swap(future_obtained,other.future_obtained); Chris@16: } Chris@16: Chris@16: // Result retrieval Chris@16: BOOST_THREAD_FUTURE get_future() Chris@16: { Chris@16: lazy_init(); Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: if (future_obtained) Chris@16: { Chris@16: boost::throw_exception(future_already_retrieved()); Chris@16: } Chris@16: future_obtained=true; Chris@16: return BOOST_THREAD_FUTURE(future_); Chris@16: } Chris@16: Chris@16: void set_value(R& r) Chris@16: { Chris@16: lazy_init(); Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: if(future_->done) Chris@16: { Chris@16: boost::throw_exception(promise_already_satisfied()); Chris@16: } Chris@16: future_->mark_finished_with_result_internal(r, lock); Chris@16: } Chris@16: Chris@16: void set_exception(boost::exception_ptr p) Chris@16: { Chris@16: lazy_init(); Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: if(future_->done) Chris@16: { Chris@16: boost::throw_exception(promise_already_satisfied()); Chris@16: } Chris@16: future_->mark_exceptional_finish_internal(p, lock); Chris@16: } Chris@16: template Chris@16: void set_exception(E ex) Chris@16: { Chris@101: set_exception(boost::copy_exception(ex)); Chris@16: } Chris@16: Chris@16: // setting the result with deferred notification Chris@16: void set_value_at_thread_exit(R& r) Chris@16: { Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: future_->set_value_at_thread_exit(r); Chris@16: } Chris@16: Chris@16: void set_exception_at_thread_exit(exception_ptr e) Chris@16: { Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: future_->set_exception_at_thread_exit(e); Chris@16: } Chris@16: template Chris@16: void set_exception_at_thread_exit(E ex) Chris@16: { Chris@101: set_exception_at_thread_exit(boost::copy_exception(ex)); Chris@16: } Chris@16: Chris@16: template Chris@16: void set_wait_callback(F f) Chris@16: { Chris@16: lazy_init(); Chris@16: future_->set_wait_callback(f,this); Chris@16: } Chris@16: }; Chris@101: Chris@16: template <> Chris@16: class promise Chris@16: { Chris@16: typedef boost::shared_ptr > future_ptr; Chris@16: Chris@16: future_ptr future_; Chris@16: bool future_obtained; Chris@16: Chris@16: void lazy_init() Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY Chris@16: if(!atomic_load(&future_)) Chris@16: { Chris@16: future_ptr blank; Chris@16: atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state)); Chris@16: } Chris@16: #endif Chris@16: } Chris@16: public: Chris@16: BOOST_THREAD_MOVABLE_ONLY(promise) Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS Chris@16: template Chris@16: promise(boost::allocator_arg_t, Allocator a) Chris@16: { Chris@16: typedef typename Allocator::template rebind >::other A2; Chris@16: A2 a2(a); Chris@16: typedef thread_detail::allocator_destructor D; Chris@16: Chris@16: future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state(), D(a2, 1) ); Chris@16: future_obtained = false; Chris@16: } Chris@16: #endif Chris@16: promise(): Chris@16: #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY Chris@16: future_(), Chris@16: #else Chris@16: future_(new detail::shared_state), Chris@16: #endif Chris@16: future_obtained(false) Chris@16: {} Chris@16: Chris@16: ~promise() Chris@16: { Chris@16: if(future_) Chris@16: { Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: Chris@16: if(!future_->done && !future_->is_constructed) Chris@16: { Chris@16: future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : Chris@16: future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) Chris@16: { Chris@16: // we need to release the future as shared_ptr doesn't implements move semantics Chris@16: BOOST_THREAD_RV(rhs).future_.reset(); Chris@16: BOOST_THREAD_RV(rhs).future_obtained=false; Chris@16: } Chris@16: Chris@16: promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT Chris@16: { Chris@16: future_=BOOST_THREAD_RV(rhs).future_; Chris@16: future_obtained=BOOST_THREAD_RV(rhs).future_obtained; Chris@16: BOOST_THREAD_RV(rhs).future_.reset(); Chris@16: BOOST_THREAD_RV(rhs).future_obtained=false; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(promise& other) Chris@16: { Chris@16: future_.swap(other.future_); Chris@16: std::swap(future_obtained,other.future_obtained); Chris@16: } Chris@16: Chris@16: // Result retrieval Chris@16: BOOST_THREAD_FUTURE get_future() Chris@16: { Chris@16: lazy_init(); Chris@16: Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: if(future_obtained) Chris@16: { Chris@16: boost::throw_exception(future_already_retrieved()); Chris@16: } Chris@16: future_obtained=true; Chris@101: //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE(future_)); Chris@16: return BOOST_THREAD_FUTURE(future_); Chris@16: } Chris@16: Chris@16: void set_value() Chris@16: { Chris@16: lazy_init(); Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: if(future_->done) Chris@16: { Chris@16: boost::throw_exception(promise_already_satisfied()); Chris@16: } Chris@16: future_->mark_finished_with_result_internal(lock); Chris@16: } Chris@16: Chris@16: void set_exception(boost::exception_ptr p) Chris@16: { Chris@16: lazy_init(); Chris@16: boost::unique_lock lock(future_->mutex); Chris@16: if(future_->done) Chris@16: { Chris@16: boost::throw_exception(promise_already_satisfied()); Chris@16: } Chris@16: future_->mark_exceptional_finish_internal(p,lock); Chris@16: } Chris@16: template Chris@16: void set_exception(E ex) Chris@16: { Chris@101: set_exception(boost::copy_exception(ex)); Chris@16: } Chris@16: Chris@16: // setting the result with deferred notification Chris@16: void set_value_at_thread_exit() Chris@16: { Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: future_->set_value_at_thread_exit(); Chris@16: } Chris@16: Chris@16: void set_exception_at_thread_exit(exception_ptr e) Chris@16: { Chris@16: if (future_.get()==0) Chris@16: { Chris@16: boost::throw_exception(promise_moved()); Chris@16: } Chris@16: future_->set_exception_at_thread_exit(e); Chris@16: } Chris@16: template Chris@16: void set_exception_at_thread_exit(E ex) Chris@16: { Chris@101: set_exception_at_thread_exit(boost::copy_exception(ex)); Chris@16: } Chris@16: Chris@16: template Chris@16: void set_wait_callback(F f) Chris@16: { Chris@16: lazy_init(); Chris@16: future_->set_wait_callback(f,this); Chris@16: } Chris@16: Chris@16: }; Chris@101: } Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS Chris@101: namespace boost { namespace container { Chris@101: template Chris@101: struct uses_allocator< ::boost::promise , Alloc> : true_type Chris@16: { Chris@101: }; Chris@101: }} Chris@101: #if ! defined BOOST_NO_CXX11_ALLOCATOR Chris@101: namespace std { Chris@101: template Chris@101: struct uses_allocator< ::boost::promise , Alloc> : true_type Chris@101: { Chris@101: }; Chris@101: } Chris@16: #endif Chris@101: #endif Chris@101: Chris@101: namespace boost Chris@101: { Chris@16: Chris@16: BOOST_THREAD_DCL_MOVABLE_BEG(T) promise BOOST_THREAD_DCL_MOVABLE_END Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: template Chris@16: struct task_base_shared_state; Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: struct task_base_shared_state: Chris@16: #else Chris@16: template Chris@16: struct task_base_shared_state: Chris@16: #endif Chris@16: #else Chris@16: template Chris@16: struct task_base_shared_state: Chris@16: #endif Chris@16: detail::shared_state Chris@16: { Chris@16: bool started; Chris@16: Chris@16: task_base_shared_state(): Chris@16: started(false) Chris@16: {} Chris@16: Chris@16: void reset() Chris@16: { Chris@101: // todo The packaged_task::reset must be as if an assignemnt froma new packaged_task with the same function Chris@101: // the reset function is an optimization that avoids reallocating a new task. Chris@16: started=false; Chris@101: this->validate(); Chris@16: } Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; Chris@16: void run(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: #else Chris@16: virtual void do_run()=0; Chris@16: void run() Chris@16: #endif Chris@16: { Chris@16: { Chris@16: boost::lock_guard lk(this->mutex); Chris@16: if(started) Chris@16: { Chris@16: boost::throw_exception(task_already_started()); Chris@16: } Chris@16: started=true; Chris@16: } Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: do_run(boost::move(args)...); Chris@16: #else Chris@16: do_run(); Chris@16: #endif Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; Chris@16: void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: #else Chris@16: virtual void do_apply()=0; Chris@16: void apply() Chris@16: #endif Chris@16: { Chris@16: { Chris@16: boost::lock_guard lk(this->mutex); Chris@16: if(started) Chris@16: { Chris@16: boost::throw_exception(task_already_started()); Chris@16: } Chris@16: started=true; Chris@16: } Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: do_apply(boost::move(args)...); Chris@16: #else Chris@16: do_apply(); Chris@16: #endif Chris@16: } Chris@16: Chris@16: void owner_destroyed() Chris@16: { Chris@16: boost::unique_lock lk(this->mutex); Chris@16: if(!started) Chris@16: { Chris@16: started=true; Chris@16: this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: template Chris@16: struct task_shared_state; Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #else Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: #else Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: { Chris@16: private: Chris@16: task_shared_state(task_shared_state&); Chris@16: public: Chris@16: F f; Chris@16: task_shared_state(F const& f_): Chris@16: f(f_) Chris@16: {} Chris@16: task_shared_state(BOOST_THREAD_RV_REF(F) f_): Chris@16: f(boost::move(f_)) Chris@16: {} Chris@16: Chris@101: F callable() Chris@101: { Chris@101: return boost::move(f); Chris@101: } Chris@101: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: this->set_value_at_thread_exit(f(boost::move(args)...)); Chris@16: } Chris@16: #else Chris@16: void do_apply() Chris@16: { Chris@16: try Chris@16: { Chris@16: this->set_value_at_thread_exit(f()); Chris@16: } Chris@16: #endif Chris@16: catch(...) Chris@16: { Chris@16: this->set_exception_at_thread_exit(current_exception()); Chris@16: } Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: this->mark_finished_with_result(f(boost::move(args)...)); Chris@16: } Chris@16: #else Chris@16: void do_run() Chris@16: { Chris@16: try Chris@16: { Chris@16: #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: R res((f())); Chris@16: this->mark_finished_with_result(boost::move(res)); Chris@16: #else Chris@16: this->mark_finished_with_result(f()); Chris@16: #endif Chris@16: } Chris@16: #endif Chris@16: catch(...) Chris@16: { Chris@16: this->mark_exceptional_finish(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #else Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: #else Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: { Chris@16: private: Chris@16: task_shared_state(task_shared_state&); Chris@16: public: Chris@16: F f; Chris@16: task_shared_state(F const& f_): Chris@16: f(f_) Chris@16: {} Chris@16: task_shared_state(BOOST_THREAD_RV_REF(F) f_): Chris@16: f(boost::move(f_)) Chris@16: {} Chris@16: Chris@101: F callable() Chris@101: { Chris@101: return f; Chris@101: } Chris@101: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: this->set_value_at_thread_exit(f(boost::move(args)...)); Chris@16: } Chris@16: #else Chris@16: void do_apply() Chris@16: { Chris@16: try Chris@16: { Chris@16: this->set_value_at_thread_exit(f()); Chris@16: } Chris@16: #endif Chris@16: catch(...) Chris@16: { Chris@16: this->set_exception_at_thread_exit(current_exception()); Chris@16: } Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: this->mark_finished_with_result(f(boost::move(args)...)); Chris@16: } Chris@16: #else Chris@16: void do_run() Chris@16: { Chris@16: try Chris@16: { Chris@16: R& res((f())); Chris@16: this->mark_finished_with_result(res); Chris@16: } Chris@16: #endif Chris@16: catch(...) Chris@16: { Chris@16: this->mark_exceptional_finish(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #else Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: #else Chris@16: template Chris@16: struct task_shared_state : Chris@16: task_base_shared_state Chris@16: #endif Chris@16: { Chris@16: private: Chris@16: task_shared_state(task_shared_state&); Chris@101: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: typedef R (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... ); Chris@101: #else Chris@101: typedef R (*CallableType)(); Chris@101: #endif Chris@16: public: Chris@101: CallableType f; Chris@101: task_shared_state(CallableType f_): Chris@16: f(f_) Chris@16: {} Chris@16: Chris@101: CallableType callable() Chris@101: { Chris@101: return f; Chris@101: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: this->set_value_at_thread_exit(f(boost::move(args)...)); Chris@16: } Chris@16: #else Chris@16: void do_apply() Chris@16: { Chris@16: try Chris@16: { Chris@16: R r((f())); Chris@16: this->set_value_at_thread_exit(boost::move(r)); Chris@16: } Chris@16: #endif Chris@16: catch(...) Chris@16: { Chris@16: this->set_exception_at_thread_exit(current_exception()); Chris@16: } Chris@16: } Chris@16: Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: this->mark_finished_with_result(f(boost::move(args)...)); Chris@16: } Chris@16: #else Chris@16: void do_run() Chris@16: { Chris@16: try Chris@16: { Chris@16: R res((f())); Chris@16: this->mark_finished_with_result(boost::move(res)); Chris@16: } Chris@16: #endif Chris@16: catch(...) Chris@16: { Chris@16: this->mark_exceptional_finish(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #else Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: #else Chris@16: template Chris@16: struct task_shared_state : Chris@16: task_base_shared_state Chris@16: #endif Chris@16: { Chris@16: private: Chris@16: task_shared_state(task_shared_state&); Chris@16: public: Chris@101: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... ); Chris@101: #else Chris@101: typedef R& (*CallableType)(); Chris@101: #endif Chris@101: CallableType f; Chris@101: task_shared_state(CallableType f_): Chris@16: f(f_) Chris@16: {} Chris@16: Chris@101: CallableType callable() Chris@101: { Chris@101: return boost::move(f); Chris@101: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: this->set_value_at_thread_exit(f(boost::move(args)...)); Chris@16: } Chris@16: #else Chris@16: void do_apply() Chris@16: { Chris@16: try Chris@16: { Chris@16: this->set_value_at_thread_exit(f()); Chris@16: } Chris@16: #endif Chris@16: catch(...) Chris@16: { Chris@16: this->set_exception_at_thread_exit(current_exception()); Chris@16: } Chris@16: } Chris@16: Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: this->mark_finished_with_result(f(boost::move(args)...)); Chris@16: } Chris@16: #else Chris@16: void do_run() Chris@16: { Chris@16: try Chris@16: { Chris@16: this->mark_finished_with_result(f()); Chris@16: } Chris@16: #endif Chris@16: catch(...) Chris@16: { Chris@16: this->mark_exceptional_finish(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: #endif Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #else Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: #else Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: { Chris@16: private: Chris@16: task_shared_state(task_shared_state&); Chris@16: public: Chris@101: typedef F CallableType; Chris@16: F f; Chris@16: task_shared_state(F const& f_): Chris@16: f(f_) Chris@16: {} Chris@16: task_shared_state(BOOST_THREAD_RV_REF(F) f_): Chris@16: f(boost::move(f_)) Chris@16: {} Chris@101: F callable() Chris@101: { Chris@101: return boost::move(f); Chris@101: } Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: f(boost::move(args)...); Chris@16: #else Chris@16: void do_apply() Chris@16: { Chris@16: try Chris@16: { Chris@16: f(); Chris@16: #endif Chris@16: this->set_value_at_thread_exit(); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: this->set_exception_at_thread_exit(current_exception()); Chris@16: } Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: f(boost::move(args)...); Chris@16: #else Chris@16: void do_run() Chris@16: { Chris@16: try Chris@16: { Chris@16: f(); Chris@16: #endif Chris@16: this->mark_finished_with_result(); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: this->mark_exceptional_finish(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #else Chris@16: template<> Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: #else Chris@16: template<> Chris@16: struct task_shared_state: Chris@16: task_base_shared_state Chris@16: #endif Chris@16: { Chris@16: private: Chris@16: task_shared_state(task_shared_state&); Chris@101: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: typedef void (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes)...); Chris@101: #else Chris@101: typedef void (*CallableType)(); Chris@101: #endif Chris@16: public: Chris@101: CallableType f; Chris@101: task_shared_state(CallableType f_): Chris@16: f(f_) Chris@16: {} Chris@101: CallableType callable() Chris@101: { Chris@101: return f; Chris@101: } Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: f(boost::move(args)...); Chris@16: #else Chris@16: void do_apply() Chris@16: { Chris@16: try Chris@16: { Chris@16: f(); Chris@16: #endif Chris@16: this->set_value_at_thread_exit(); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: this->set_exception_at_thread_exit(current_exception()); Chris@16: } Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) Chris@16: { Chris@16: try Chris@16: { Chris@101: f(boost::move(args)...); Chris@16: #else Chris@16: void do_run() Chris@16: { Chris@16: try Chris@16: { Chris@16: f(); Chris@16: #endif Chris@16: this->mark_finished_with_result(); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: this->mark_exceptional_finish(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: class packaged_task Chris@16: { Chris@16: typedef boost::shared_ptr > task_ptr; Chris@16: boost::shared_ptr > task; Chris@16: #else Chris@16: template Chris@16: class packaged_task Chris@16: { Chris@16: typedef boost::shared_ptr > task_ptr; Chris@16: boost::shared_ptr > task; Chris@16: #endif Chris@16: #else Chris@16: template Chris@16: class packaged_task Chris@16: { Chris@16: typedef boost::shared_ptr > task_ptr; Chris@16: boost::shared_ptr > task; Chris@16: #endif Chris@16: bool future_obtained; Chris@16: struct dummy; Chris@16: Chris@16: public: Chris@16: typedef R result_type; Chris@16: BOOST_THREAD_MOVABLE_ONLY(packaged_task) Chris@16: Chris@16: packaged_task(): Chris@16: future_obtained(false) Chris@16: {} Chris@16: Chris@16: // construction and destruction Chris@16: #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args) Chris@16: { Chris@16: typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...); Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@101: task= task_ptr(new task_shared_state_type(f, boost::move(args)...)); Chris@16: future_obtained=false; Chris@16: } Chris@16: #else Chris@16: explicit packaged_task(R(*f)()) Chris@16: { Chris@16: typedef R(*FR)(); Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: task= task_ptr(new task_shared_state_type(f)); Chris@16: future_obtained=false; Chris@16: } Chris@16: #endif Chris@16: #else Chris@16: explicit packaged_task(R(*f)()) Chris@16: { Chris@16: typedef R(*FR)(); Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: task= task_ptr(new task_shared_state_type(f)); Chris@16: future_obtained=false; Chris@16: } Chris@16: #endif Chris@16: #endif Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: explicit packaged_task(BOOST_THREAD_FWD_REF(F) f Chris@16: , typename boost::disable_if::type, packaged_task>, dummy* >::type=0 Chris@16: ) Chris@16: { Chris@101: typedef typename decay::type FR; Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: task = task_ptr(new task_shared_state_type(boost::forward(f))); Chris@16: future_obtained = false; Chris@16: Chris@16: } Chris@16: Chris@16: #else Chris@16: template Chris@16: explicit packaged_task(F const& f Chris@16: , typename boost::disable_if::type, packaged_task>, dummy* >::type=0 Chris@16: ) Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: task = task_ptr(new task_shared_state_type(f)); Chris@16: future_obtained=false; Chris@16: } Chris@16: template Chris@16: explicit packaged_task(BOOST_THREAD_RV_REF(F) f) Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@101: task = task_ptr(new task_shared_state_type(boost::move(f))); Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@101: task = task_ptr(new task_shared_state_type(boost::move(f))); Chris@16: #endif Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@101: task = task_ptr(new task_shared_state_type(boost::move(f))); Chris@16: #endif Chris@16: future_obtained=false; Chris@16: Chris@16: } Chris@16: #endif Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS Chris@16: #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) Chris@16: template Chris@16: packaged_task(boost::allocator_arg_t, Allocator a, R(*f)()) Chris@16: { Chris@16: typedef R(*FR)(); Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: typedef typename Allocator::template rebind::other A2; Chris@16: A2 a2(a); Chris@16: typedef thread_detail::allocator_destructor D; Chris@16: Chris@16: task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) ); Chris@16: future_obtained = false; Chris@16: } Chris@16: #endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR Chris@16: Chris@16: #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f) Chris@16: { Chris@101: typedef typename decay::type FR; Chris@101: Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: typedef typename Allocator::template rebind::other A2; Chris@16: A2 a2(a); Chris@16: typedef thread_detail::allocator_destructor D; Chris@16: Chris@16: task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward(f)), D(a2, 1) ); Chris@16: future_obtained = false; Chris@16: } Chris@16: #else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: packaged_task(boost::allocator_arg_t, Allocator a, const F& f) Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: typedef typename Allocator::template rebind::other A2; Chris@16: A2 a2(a); Chris@16: typedef thread_detail::allocator_destructor D; Chris@16: Chris@16: task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) ); Chris@16: future_obtained = false; Chris@16: } Chris@16: template Chris@16: packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f) Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: #else Chris@16: typedef detail::task_shared_state task_shared_state_type; Chris@16: #endif Chris@16: typedef typename Allocator::template rebind::other A2; Chris@16: A2 a2(a); Chris@16: typedef thread_detail::allocator_destructor D; Chris@16: Chris@101: task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) ); Chris@16: future_obtained = false; Chris@16: } Chris@16: Chris@16: #endif //BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS Chris@16: Chris@101: ~packaged_task() { Chris@101: if(task) { Chris@16: task->owner_destroyed(); Chris@16: } Chris@16: } Chris@16: Chris@16: // assignment Chris@101: packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT Chris@101: : future_obtained(BOOST_THREAD_RV(other).future_obtained) { Chris@16: task.swap(BOOST_THREAD_RV(other).task); Chris@16: BOOST_THREAD_RV(other).future_obtained=false; Chris@16: } Chris@101: packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT { Chris@101: Chris@16: #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: packaged_task temp(boost::move(other)); Chris@16: #else Chris@16: packaged_task temp(static_cast(other)); Chris@16: #endif Chris@16: swap(temp); Chris@16: return *this; Chris@16: } Chris@16: Chris@101: void reset() { Chris@16: if (!valid()) Chris@16: throw future_error(system::make_error_code(future_errc::no_state)); Chris@101: Chris@101: // As if *this = packaged_task(task->callable()); Chris@101: Chris@16: task->reset(); Chris@16: future_obtained=false; Chris@16: } Chris@16: Chris@101: void swap(packaged_task& other) BOOST_NOEXCEPT { Chris@16: task.swap(other.task); Chris@16: std::swap(future_obtained,other.future_obtained); Chris@16: } Chris@101: bool valid() const BOOST_NOEXCEPT { Chris@16: return task.get()!=0; Chris@16: } Chris@16: Chris@16: // result retrieval Chris@101: BOOST_THREAD_FUTURE get_future() { Chris@101: if(!task) { Chris@101: boost::throw_exception(task_moved()); Chris@101: } else if(!future_obtained) { Chris@101: future_obtained=true; Chris@101: return BOOST_THREAD_FUTURE(task); Chris@101: } else { Chris@101: boost::throw_exception(future_already_retrieved()); Chris@101: } Chris@101: } Chris@101: Chris@101: // execution Chris@101: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args) { Chris@101: if(!task) { Chris@16: boost::throw_exception(task_moved()); Chris@16: } Chris@101: task->run(boost::move(args)...); Chris@16: } Chris@101: void make_ready_at_thread_exit(ArgTypes... args) { Chris@101: if(!task) { Chris@16: boost::throw_exception(task_moved()); Chris@16: } Chris@101: if (task->has_value()) { Chris@16: boost::throw_exception(promise_already_satisfied()); Chris@16: } Chris@101: task->apply(boost::move(args)...); Chris@16: } Chris@16: #else Chris@101: void operator()() { Chris@101: if(!task) { Chris@16: boost::throw_exception(task_moved()); Chris@16: } Chris@16: task->run(); Chris@16: } Chris@101: void make_ready_at_thread_exit() { Chris@101: if(!task) { Chris@16: boost::throw_exception(task_moved()); Chris@16: } Chris@101: if (task->has_value()) boost::throw_exception(promise_already_satisfied()); Chris@16: task->apply(); Chris@16: } Chris@16: #endif Chris@16: template Chris@101: void set_wait_callback(F f) { Chris@16: task->set_wait_callback(f,this); Chris@16: } Chris@16: }; Chris@101: } Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS Chris@101: namespace boost { namespace container { Chris@101: template Chris@101: struct uses_allocator< ::boost::packaged_task , Alloc> : true_type Chris@101: {}; Chris@101: }} Chris@101: #if ! defined BOOST_NO_CXX11_ALLOCATOR Chris@101: namespace std { Chris@101: template Chris@101: struct uses_allocator< ::boost::packaged_task , Alloc> : true_type Chris@101: {}; Chris@101: } Chris@16: #endif Chris@101: #endif Chris@101: Chris@101: namespace boost Chris@101: { Chris@101: BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task BOOST_THREAD_DCL_MOVABLE_END Chris@101: Chris@101: namespace detail Chris@101: { Chris@101: //////////////////////////////// Chris@101: // make_future_deferred_shared_state Chris@101: //////////////////////////////// Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) { Chris@101: shared_ptr > Chris@101: h(new future_deferred_shared_state(boost::forward(f))); Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: Chris@101: //////////////////////////////// Chris@101: // make_future_async_shared_state Chris@101: //////////////////////////////// Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) { Chris@101: shared_ptr > Chris@101: h(new future_async_shared_state()); Chris@101: h->init(boost::forward(f)); Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: } Chris@16: Chris@16: //////////////////////////////// Chris@16: // template Chris@16: // future async(launch policy, F&&, ArgTypes&&...); Chris@16: //////////////////////////////// Chris@16: Chris@16: #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR Chris@16: Chris@101: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { Chris@101: typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); Chris@101: typedef detail::invoker::type, typename decay::type...> BF; Chris@101: typedef typename BF::result_type Rp; Chris@101: Chris@101: if (underlying_cast(policy) & int(launch::async)) { Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state( Chris@16: BF( Chris@101: f Chris@16: , thread_detail::decay_copy(boost::forward(args))... Chris@16: ) Chris@16: )); Chris@101: } else if (underlying_cast(policy) & int(launch::deferred)) { Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state( Chris@16: BF( Chris@101: f Chris@16: , thread_detail::decay_copy(boost::forward(args))... Chris@16: ) Chris@16: )); Chris@101: } else { Chris@101: std::terminate(); Chris@101: BOOST_THREAD_FUTURE ret; Chris@101: return ::boost::move(ret); Chris@101: } Chris@101: } Chris@101: Chris@101: #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: async(launch policy, R(*f)()) { Chris@101: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@101: typedef packaged_task packaged_task_type; Chris@101: #else Chris@101: typedef packaged_task packaged_task_type; Chris@101: #endif Chris@101: Chris@101: if (underlying_cast(policy) & int(launch::async)) { Chris@101: packaged_task_type pt( f ); Chris@101: BOOST_THREAD_FUTURE ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future()); Chris@101: ret.set_async(); Chris@101: boost::thread( boost::move(pt) ).detach(); Chris@101: return ::boost::move(ret); Chris@101: } else if (underlying_cast(policy) & int(launch::deferred)) { Chris@101: std::terminate(); Chris@101: BOOST_THREAD_FUTURE ret; Chris@101: return ::boost::move(ret); Chris@101: } else { Chris@101: std::terminate(); Chris@101: BOOST_THREAD_FUTURE ret; Chris@101: return ::boost::move(ret); Chris@101: } Chris@101: } Chris@16: #endif Chris@101: #endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) Chris@101: Chris@101: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE::type( Chris@101: typename decay::type... Chris@101: )>::type> Chris@101: async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { Chris@101: typedef typename boost::result_of::type( Chris@101: typename decay::type... Chris@101: )>::type R; Chris@101: typedef detail::invoker::type, typename decay::type...> BF; Chris@101: typedef typename BF::result_type Rp; Chris@101: Chris@101: if (underlying_cast(policy) & int(launch::async)) { Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state( Chris@16: BF( Chris@16: thread_detail::decay_copy(boost::forward(f)) Chris@101: , thread_detail::decay_copy(boost::forward(args))... Chris@16: ) Chris@16: )); Chris@101: } else if (underlying_cast(policy) & int(launch::deferred)) { Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state( Chris@16: BF( Chris@16: thread_detail::decay_copy(boost::forward(f)) Chris@101: , thread_detail::decay_copy(boost::forward(args))... Chris@16: ) Chris@16: )); Chris@101: } else { Chris@101: std::terminate(); Chris@101: BOOST_THREAD_FUTURE ret; Chris@101: return ::boost::move(ret); Chris@101: } Chris@101: } Chris@101: Chris@101: #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE::type()>::type> Chris@101: async(launch policy, BOOST_THREAD_FWD_REF(F) f) { Chris@101: typedef typename boost::result_of::type()>::type R; Chris@101: #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@101: typedef packaged_task packaged_task_type; Chris@101: #else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@101: typedef packaged_task packaged_task_type; Chris@101: #endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK Chris@101: Chris@101: if (underlying_cast(policy) & int(launch::async)) { Chris@101: packaged_task_type pt( boost::forward(f) ); Chris@101: BOOST_THREAD_FUTURE ret = pt.get_future(); Chris@101: ret.set_async(); Chris@101: boost::thread( boost::move(pt) ).detach(); Chris@101: return ::boost::move(ret); Chris@101: } else if (underlying_cast(policy) & int(launch::deferred)) { Chris@101: std::terminate(); Chris@101: BOOST_THREAD_FUTURE ret; Chris@101: return ::boost::move(ret); Chris@101: // return boost::detail::make_future_deferred_shared_state( Chris@101: // BF( Chris@101: // thread_detail::decay_copy(boost::forward(f)) Chris@101: // ) Chris@101: // ); Chris@101: } else { Chris@101: std::terminate(); Chris@101: BOOST_THREAD_FUTURE ret; Chris@101: return ::boost::move(ret); Chris@101: } Chris@101: } Chris@101: #endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: namespace detail { Chris@101: ///////////////////////// Chris@101: /// shared_state_nullary_task Chris@101: ///////////////////////// Chris@101: template Chris@101: struct shared_state_nullary_task Chris@101: { Chris@101: shared_state* that; Chris@101: Fp f_; Chris@101: public: Chris@101: Chris@101: shared_state_nullary_task(shared_state* st, BOOST_THREAD_FWD_REF(Fp) f) Chris@101: : that(st), f_(boost::move(f)) Chris@101: {}; Chris@101: #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@101: BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) Chris@101: shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT Chris@101: : that(x.that), f_(x.f_) Chris@101: {} Chris@101: shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT Chris@101: { Chris@101: if (this != &x) { Chris@101: that=x.that; Chris@101: f_=x.f_; Chris@101: } Chris@101: return *this; Chris@101: } Chris@101: // move Chris@101: shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT Chris@101: : that(x.that), f_(boost::move(x.f_)) Chris@101: { Chris@101: x.that=0; Chris@101: } Chris@101: shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT Chris@101: { Chris@101: if (this != &x) { Chris@101: that=x.that; Chris@101: f_=boost::move(x.f_); Chris@101: x.that=0; Chris@101: } Chris@101: return *this; Chris@101: } Chris@101: #endif Chris@101: void operator()() { Chris@101: try { Chris@101: that->mark_finished_with_result(f_()); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: }; Chris@101: Chris@101: template Chris@101: struct shared_state_nullary_task Chris@101: { Chris@101: shared_state* that; Chris@101: Fp f_; Chris@101: public: Chris@101: shared_state_nullary_task(shared_state* st, BOOST_THREAD_FWD_REF(Fp) f) Chris@101: : that(st), f_(boost::move(f)) Chris@101: {}; Chris@101: #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@101: BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) Chris@101: shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT Chris@101: : that(x.that), f_(x.f_) Chris@101: {} Chris@101: shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT Chris@101: { Chris@101: if (this != &x) { Chris@101: that=x.that; Chris@101: f_=x.f_; Chris@101: } Chris@101: return *this; Chris@101: } Chris@101: // move Chris@101: shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT Chris@101: : that(x.that), f_(boost::move(x.f_)) Chris@101: { Chris@101: x.that=0; Chris@101: } Chris@101: shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { Chris@101: if (this != &x) { Chris@101: that=x.that; Chris@101: f_=boost::move(x.f_); Chris@101: x.that=0; Chris@101: } Chris@101: return *this; Chris@101: } Chris@101: #endif Chris@101: void operator()() { Chris@101: try { Chris@101: f_(); Chris@101: that->mark_finished_with_result(); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: }; Chris@101: Chris@101: template Chris@101: struct shared_state_nullary_task Chris@101: { Chris@101: shared_state* that; Chris@101: Fp f_; Chris@101: public: Chris@101: shared_state_nullary_task(shared_state* st, BOOST_THREAD_FWD_REF(Fp) f) Chris@101: : that(st), f_(boost::move(f)) Chris@101: {} Chris@101: #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@101: BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) Chris@101: shared_state_nullary_task(shared_state_nullary_task const& x) BOOST_NOEXCEPT Chris@101: : that(x.that), f_(x.f_) {} Chris@101: Chris@101: shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { Chris@101: if (this != &x){ Chris@101: that=x.that; Chris@101: f_=x.f_; Chris@101: } Chris@101: return *this; Chris@101: } Chris@101: // move Chris@101: shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT Chris@101: : that(x.that), f_(boost::move(x.f_)) Chris@101: { Chris@101: x.that=0; Chris@101: } Chris@101: shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { Chris@101: if (this != &x) { Chris@101: that=x.that; Chris@101: f_=boost::move(x.f_); Chris@101: x.that=0; Chris@101: } Chris@101: return *this; Chris@101: } Chris@101: #endif Chris@101: void operator()() { Chris@101: try { Chris@101: that->mark_finished_with_result(f_()); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: }; Chris@101: Chris@101: ///////////////////////// Chris@101: /// future_executor_shared_state_base Chris@101: ///////////////////////// Chris@101: template Chris@101: struct future_executor_shared_state: shared_state Chris@101: { Chris@101: typedef shared_state base_type; Chris@101: protected: Chris@101: public: Chris@101: template Chris@101: future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { Chris@101: this->set_executor(); Chris@101: shared_state_nullary_task t(this, boost::forward(f)); Chris@101: ex.submit(boost::move(t)); Chris@101: } Chris@101: Chris@101: virtual void block_if_needed(boost::unique_lock&lk) Chris@101: { Chris@101: this->wait(lk, false); Chris@101: } Chris@101: Chris@101: ~future_executor_shared_state() {} Chris@101: }; Chris@101: Chris@101: //////////////////////////////// Chris@101: // make_future_executor_shared_state Chris@101: //////////////////////////////// Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { Chris@101: shared_ptr > Chris@101: h(new future_executor_shared_state(ex, boost::forward(f))); Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: Chris@101: } // detail Chris@101: Chris@101: //////////////////////////////// Chris@101: // template Chris@101: // future async(Executor& ex, F&&, ArgTypes&&...); Chris@101: //////////////////////////////// Chris@101: Chris@101: //#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: #if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE) Chris@101: Chris@101: #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { Chris@101: typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); Chris@101: typedef detail::invoker::type, typename decay::type...> BF; Chris@101: typedef typename BF::result_type Rp; Chris@101: Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, Chris@101: BF( Chris@101: f Chris@101: , thread_detail::decay_copy(boost::forward(args))... Chris@101: ) Chris@101: )); Chris@101: } Chris@101: #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE::type( Chris@101: typename decay::type... Chris@101: )>::type> Chris@101: async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { Chris@101: typedef detail::invoker::type, typename decay::type...> BF; Chris@101: typedef typename BF::result_type Rp; Chris@101: Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, Chris@101: BF( Chris@101: thread_detail::decay_copy(boost::forward(f)) Chris@101: , thread_detail::decay_copy(boost::forward(args))... Chris@101: ) Chris@101: )); Chris@101: } Chris@101: Chris@101: #else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: async(Executor& ex, R(*f)()) { Chris@101: typedef R(*F)(); Chris@101: typedef detail::invoker BF; Chris@101: typedef typename BF::result_type Rp; Chris@101: Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, Chris@101: BF( Chris@101: f Chris@101: ) Chris@101: )); Chris@101: } Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) { Chris@101: typedef R(*F)(BOOST_THREAD_FWD_REF(A1)); Chris@101: typedef detail::invoker::type> BF; Chris@101: typedef typename BF::result_type Rp; Chris@101: Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, Chris@101: BF( Chris@101: f Chris@101: , thread_detail::decay_copy(boost::forward(a1)) Chris@101: ) Chris@101: )); Chris@101: } Chris@101: #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE::type()>::type> Chris@101: async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) { Chris@101: typedef detail::invoker::type> BF; Chris@101: typedef typename BF::result_type Rp; Chris@101: Chris@101: return boost::detail::make_future_executor_shared_state(ex, Chris@101: BF( Chris@101: thread_detail::decay_copy(boost::forward(f)) Chris@101: ) Chris@101: ); Chris@101: } Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE::type( Chris@101: typename decay::type Chris@101: )>::type> Chris@101: async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) { Chris@101: typedef detail::invoker::type, typename decay::type> BF; Chris@101: typedef typename BF::result_type Rp; Chris@101: Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, Chris@101: BF( Chris@101: thread_detail::decay_copy(boost::forward(f)) Chris@101: , thread_detail::decay_copy(boost::forward(a1)) Chris@101: ) Chris@101: )); Chris@101: } Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE::type( Chris@101: typename decay::type, typename decay::type Chris@101: )>::type> Chris@101: async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) { Chris@101: typedef detail::invoker::type, typename decay::type, typename decay::type> BF; Chris@101: typedef typename BF::result_type Rp; Chris@101: Chris@101: return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, Chris@101: BF( Chris@101: thread_detail::decay_copy(boost::forward(f)) Chris@101: , thread_detail::decay_copy(boost::forward(a1)) Chris@101: , thread_detail::decay_copy(boost::forward(a2)) Chris@101: ) Chris@101: )); Chris@101: } Chris@101: Chris@101: #endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: #endif Chris@101: Chris@101: //////////////////////////////// Chris@101: // template Chris@101: // future async(F&&, ArgTypes&&...); Chris@101: //////////////////////////////// Chris@101: Chris@101: #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR Chris@101: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { Chris@101: return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward(args)...)); Chris@101: } Chris@101: #else Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: async(R(*f)()) { Chris@101: return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f)); Chris@101: } Chris@101: #endif Chris@101: #endif Chris@101: Chris@101: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@101: template Chris@101: BOOST_THREAD_FUTURE::type( Chris@101: typename decay::type... Chris@101: )>::type> Chris@101: async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { Chris@101: return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward(f), boost::forward(args)...)); Chris@101: } Chris@16: #else Chris@101: template Chris@101: BOOST_THREAD_FUTURE::type> Chris@101: async(BOOST_THREAD_FWD_REF(F) f) { Chris@101: return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward(f))); Chris@101: } Chris@16: #endif Chris@16: Chris@16: //////////////////////////////// Chris@16: // make_future deprecated Chris@16: //////////////////////////////// Chris@16: template Chris@101: BOOST_THREAD_FUTURE::type> make_future(BOOST_THREAD_FWD_REF(T) value) { Chris@16: typedef typename decay::type future_value_type; Chris@16: promise p; Chris@16: p.set_value(boost::forward(value)); Chris@16: return BOOST_THREAD_MAKE_RV_REF(p.get_future()); Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_USES_MOVE Chris@101: inline BOOST_THREAD_FUTURE make_future() { Chris@16: promise p; Chris@16: p.set_value(); Chris@16: return BOOST_THREAD_MAKE_RV_REF(p.get_future()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: //////////////////////////////// Chris@16: // make_ready_future Chris@16: //////////////////////////////// Chris@101: namespace detail { Chris@101: template Chris@101: struct deduced_type_impl Chris@101: { Chris@101: typedef T type; Chris@101: }; Chris@101: Chris@101: template Chris@101: struct deduced_type_impl const> Chris@101: { Chris@101: typedef T& type; Chris@101: }; Chris@101: template Chris@101: struct deduced_type_impl > Chris@101: { Chris@101: typedef T& type; Chris@101: }; Chris@101: #if __cplusplus > 201103L Chris@101: template Chris@101: struct deduced_type_impl > Chris@101: { Chris@101: typedef T& type; Chris@101: }; Chris@101: #endif Chris@101: template Chris@101: struct deduced_type Chris@101: { Chris@101: typedef typename detail::deduced_type_impl::type>::type type; Chris@101: }; Chris@101: Chris@101: } Chris@101: Chris@101: Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template Chris@101: #else Chris@101: template Chris@101: #endif Chris@101: BOOST_THREAD_FUTURE::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) { Chris@101: typedef typename detail::deduced_type::type future_value_type; Chris@16: promise p; Chris@101: p.set_value(boost::forward(value)); Chris@16: return BOOST_THREAD_MAKE_RV_REF(p.get_future()); Chris@16: } Chris@16: Chris@101: // explicit overloads Chris@101: template Chris@101: BOOST_THREAD_FUTURE make_ready_future(typename remove_reference::type & x) Chris@16: { Chris@101: promise p; Chris@101: p.set_value(x); Chris@101: return p.get_future(); Chris@101: } Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference::type) x) Chris@101: { Chris@101: promise p; Chris@101: p.set_value(forward::type>(x)); Chris@101: return p.get_future(); Chris@101: } Chris@101: Chris@101: // variadic overload Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template Chris@101: BOOST_THREAD_FUTURE make_ready_future(Args&&... args) Chris@101: { Chris@101: promise p; Chris@101: p.emplace(forward(args)...); Chris@101: return p.get_future(); Chris@101: Chris@101: } Chris@101: #endif Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE make_ready_no_decay_future(T1 value) { Chris@101: typedef T future_value_type; Chris@101: promise p; Chris@101: p.set_value(value); Chris@101: return BOOST_THREAD_MAKE_RV_REF(p.get_future()); Chris@101: } Chris@101: Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined BOOST_THREAD_USES_MOVE Chris@101: inline BOOST_THREAD_FUTURE make_ready_future() { Chris@16: promise p; Chris@16: p.set_value(); Chris@101: return p.get_future(); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@101: BOOST_THREAD_FUTURE make_ready_future(exception_ptr ex) { Chris@16: promise p; Chris@16: p.set_exception(ex); Chris@16: return BOOST_THREAD_MAKE_RV_REF(p.get_future()); Chris@16: } Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE make_exceptional_future(exception_ptr ex) { Chris@101: promise p; Chris@101: p.set_exception(ex); Chris@101: return BOOST_THREAD_MAKE_RV_REF(p.get_future()); Chris@101: } Chris@101: Chris@16: template Chris@101: BOOST_THREAD_FUTURE make_exceptional_future(E ex) { Chris@16: promise p; Chris@16: p.set_exception(boost::copy_exception(ex)); Chris@16: return BOOST_THREAD_MAKE_RV_REF(p.get_future()); Chris@16: } Chris@16: Chris@101: template Chris@101: BOOST_THREAD_FUTURE make_exceptional_future() { Chris@101: promise p; Chris@101: p.set_exception(boost::current_exception()); Chris@101: return BOOST_THREAD_MAKE_RV_REF(p.get_future()); Chris@101: } Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE make_exceptional_future_if_invalid(BOOST_THREAD_FWD_REF(BOOST_THREAD_FUTURE) fut) { Chris@101: fut.set_exceptional_if_invalid(); Chris@101: return boost::move(fut); Chris@101: } Chris@101: template Chris@101: shared_future make_exceptional_future_if_invalid(shared_future fut) { Chris@101: fut.set_exceptional_if_invalid(); Chris@101: return fut; Chris@101: } Chris@101: Chris@16: #if 0 Chris@16: template Chris@16: make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE { Chris@16: typedef decltype(closure()) T; Chris@16: promise p; Chris@101: try { Chris@16: p.set_value(closure()); Chris@101: } catch(...) { Chris@16: p.set_exception(std::current_exception()); Chris@16: } Chris@16: return BOOST_THREAD_MAKE_RV_REF(p.get_future()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: //////////////////////////////// Chris@16: // make_shared_future deprecated Chris@16: //////////////////////////////// Chris@16: template Chris@101: shared_future::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) { Chris@16: typedef typename decay::type future_type; Chris@16: promise p; Chris@16: p.set_value(boost::forward(value)); Chris@16: return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); Chris@16: } Chris@16: Chris@101: inline shared_future make_shared_future() { Chris@16: promise p; Chris@16: return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); Chris@16: } Chris@16: Chris@16: //////////////////////////////// Chris@16: // detail::future_async_continuation_shared_state Chris@16: //////////////////////////////// Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@101: namespace detail Chris@101: { Chris@101: Chris@101: ///////////////////////// Chris@101: /// future_async_continuation_shared_state Chris@101: ///////////////////////// Chris@101: Chris@101: template Chris@101: struct future_async_continuation_shared_state: future_async_shared_state_base Chris@16: { Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : parent(boost::move(f)), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: } Chris@101: Chris@101: Chris@101: void launch_continuation(boost::unique_lock&, shared_ptr that) { Chris@101: this->thr_ = thread(&future_async_continuation_shared_state::run, that); Chris@101: } Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: future_async_continuation_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: that->mark_finished_with_result(that->continuation(boost::move(that->parent))); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: Chris@101: ~future_async_continuation_shared_state() { Chris@101: } Chris@101: }; Chris@101: Chris@101: template Chris@101: struct future_async_continuation_shared_state: public future_async_shared_state_base Chris@101: { Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : parent(boost::move(f)), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: } Chris@101: Chris@101: void launch_continuation(boost::unique_lock&, shared_ptr that) { Chris@101: this->thr_ = thread(&future_async_continuation_shared_state::run, that); Chris@101: } Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: future_async_continuation_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: that->continuation(boost::move(that->parent)); Chris@101: that->mark_finished_with_result(); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: Chris@101: ~future_async_continuation_shared_state() {} Chris@101: Chris@101: }; Chris@101: Chris@101: ///////////////////////// Chris@101: /// future_executor_continuation_shared_state Chris@101: ///////////////////////// Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: Chris@101: template Chris@101: struct run_it { Chris@101: shared_ptr that_; Chris@101: Chris@101: run_it(shared_ptr that) : that_ (that) {} Chris@101: void operator()() Chris@16: { Chris@101: FutureExecutorContinuationSharedState* that = dynamic_cast(that_.get()); Chris@101: that->run(that_); Chris@101: } Chris@101: }; Chris@101: Chris@101: template Chris@101: struct future_executor_continuation_shared_state: shared_state Chris@101: { Chris@101: Ex* ex; Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : ex(&ex), parent(boost::move(f)), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: this->set_executor(); Chris@101: } Chris@101: Chris@101: void launch_continuation(boost::unique_lock& lck, shared_ptr that ) { Chris@101: relocker relock(lck); Chris@101: run_it fct(that); Chris@101: ex->submit(fct); Chris@101: } Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: future_executor_continuation_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: that->mark_finished_with_result(that->continuation(boost::move(that->parent))); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@16: } Chris@101: } Chris@101: Chris@101: virtual void block_if_needed(boost::unique_lock&lk) Chris@101: { Chris@101: this->wait(lk, false); Chris@101: } Chris@101: Chris@101: ~future_executor_continuation_shared_state() {} Chris@101: }; Chris@101: Chris@101: template Chris@101: struct future_executor_continuation_shared_state: public shared_state Chris@101: { Chris@101: Ex* ex; Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : ex(&ex), parent(boost::move(f)), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: this->set_executor(); Chris@101: } Chris@101: Chris@101: void launch_continuation(boost::unique_lock& lck, shared_ptr that ) { Chris@101: relocker relock(lck); Chris@101: run_it fct(that); Chris@101: ex->submit(fct); Chris@101: } Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: future_executor_continuation_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: that->continuation(boost::move(that->parent)); Chris@101: that->mark_finished_with_result(); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@16: } Chris@101: } Chris@101: Chris@101: virtual void block_if_needed(boost::unique_lock&lk) Chris@101: { Chris@101: this->wait(lk, false); Chris@101: } Chris@101: Chris@101: ~future_executor_continuation_shared_state() {} Chris@101: }; Chris@16: #endif Chris@101: Chris@101: ///////////////////////// Chris@101: /// shared_future_async_continuation_shared_state Chris@101: ///////////////////////// Chris@101: Chris@101: template Chris@101: struct shared_future_async_continuation_shared_state: future_async_shared_state_base Chris@101: { Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : parent(f), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: } Chris@101: Chris@101: void launch_continuation(boost::unique_lock&, shared_ptr that) { Chris@101: this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that); Chris@101: } Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: shared_future_async_continuation_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: that->mark_finished_with_result(that->continuation(that->parent)); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@16: } Chris@101: } Chris@101: Chris@101: ~shared_future_async_continuation_shared_state() {} Chris@101: }; Chris@101: Chris@101: template Chris@101: struct shared_future_async_continuation_shared_state: public future_async_shared_state_base Chris@101: { Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : parent(f), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: } Chris@101: Chris@101: void launch_continuation(boost::unique_lock&, shared_ptr that) { Chris@101: this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that); Chris@101: } Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: shared_future_async_continuation_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: that->continuation(that->parent); Chris@101: that->mark_finished_with_result(); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@16: } Chris@101: } Chris@101: Chris@101: ~shared_future_async_continuation_shared_state() {} Chris@101: }; Chris@101: Chris@101: ///////////////////////// Chris@101: /// shared_future_executor_continuation_shared_state Chris@101: ///////////////////////// Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: Chris@101: template Chris@101: struct shared_future_executor_continuation_shared_state: shared_state Chris@101: { Chris@101: Ex* ex; Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : ex(&ex), parent(f), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: this->set_executor(); Chris@101: } Chris@101: Chris@101: void launch_continuation(boost::unique_lock& lck, shared_ptr that) { Chris@101: relocker relock(lck); Chris@101: run_it fct(that); Chris@101: ex->submit(fct); Chris@101: } Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: shared_future_executor_continuation_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: that->mark_finished_with_result(that->continuation(that->parent)); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: Chris@101: virtual void block_if_needed(boost::unique_lock&lk) Chris@16: { Chris@101: this->wait(lk, false); Chris@101: } Chris@101: Chris@101: ~shared_future_executor_continuation_shared_state() {} Chris@101: }; Chris@101: Chris@101: template Chris@101: struct shared_future_executor_continuation_shared_state: public shared_state Chris@101: { Chris@101: Ex* ex; Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : ex(&ex), parent(f), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: } Chris@101: Chris@101: void launch_continuation(boost::unique_lock& lck, shared_ptr that) { Chris@101: relocker relock(lck); Chris@101: run_it fct(that); Chris@101: ex->submit(fct); Chris@101: } Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: shared_future_executor_continuation_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: that->continuation(that->parent); Chris@101: that->mark_finished_with_result(); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@16: } Chris@101: } Chris@101: Chris@101: virtual void block_if_needed(boost::unique_lock&lk) Chris@101: { Chris@101: this->wait(lk, false); Chris@101: } Chris@101: Chris@101: ~shared_future_executor_continuation_shared_state() {} Chris@101: }; Chris@101: #endif Chris@101: ////////////////////////// Chris@101: /// future_deferred_continuation_shared_state Chris@101: ////////////////////////// Chris@101: template Chris@101: struct future_deferred_continuation_shared_state: shared_state Chris@101: { Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : parent(boost::move(f)), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: this->set_deferred(); Chris@101: } Chris@101: Chris@101: virtual void launch_continuation(boost::unique_lock&lk, shared_ptr ) { Chris@101: if (this->is_deferred_) { Chris@101: this->is_deferred_=false; Chris@101: this->execute(lk); Chris@16: } Chris@101: } Chris@101: Chris@101: virtual void execute(boost::unique_lock& lck) { Chris@101: try { Chris@101: Fp local_fuct=boost::move(continuation); Chris@101: F ftmp = boost::move(parent); Chris@101: relocker relock(lck); Chris@101: Rp res = local_fuct(boost::move(ftmp)); Chris@101: relock.lock(); Chris@101: this->mark_finished_with_result_internal(boost::move(res), lck); Chris@101: } catch (...) { Chris@101: this->mark_exceptional_finish_internal(current_exception(), lck); Chris@101: } Chris@101: } Chris@101: }; Chris@101: Chris@101: template Chris@101: struct future_deferred_continuation_shared_state: shared_state Chris@101: { Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : parent(boost::move(f)), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: this->set_deferred(); Chris@101: } Chris@101: Chris@101: ~future_deferred_continuation_shared_state() { Chris@101: } Chris@101: virtual void launch_continuation(boost::unique_lock& lk, shared_ptr ) { Chris@101: if (this->is_deferred_) { Chris@101: this->is_deferred_=false; Chris@101: this->execute(lk); Chris@101: } Chris@101: } Chris@101: Chris@101: virtual void execute(boost::unique_lock& lck) { Chris@101: try { Chris@101: Fp local_fuct=boost::move(continuation); Chris@101: F ftmp = boost::move(parent); Chris@101: relocker relock(lck); Chris@101: local_fuct(boost::move(ftmp)); Chris@101: relock.lock(); Chris@101: this->mark_finished_with_result_internal(lck); Chris@101: } catch (...) { Chris@101: this->mark_exceptional_finish_internal(current_exception(), lck); Chris@101: } Chris@101: } Chris@101: }; Chris@101: Chris@101: ////////////////////////// Chris@101: /// shared_future_deferred_continuation_shared_state Chris@101: ////////////////////////// Chris@101: template Chris@101: struct shared_future_deferred_continuation_shared_state: shared_state Chris@101: { Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : parent(f), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: this->set_deferred(); Chris@101: } Chris@101: Chris@101: virtual void launch_continuation(boost::unique_lock& lk, shared_ptr ) { Chris@101: if (this->is_deferred_) { Chris@101: this->is_deferred_=false; Chris@101: this->execute(lk); Chris@101: } Chris@101: } Chris@101: Chris@101: virtual void execute(boost::unique_lock& lck) { Chris@101: try { Chris@101: Fp local_fuct=boost::move(continuation); Chris@101: F ftmp = parent; Chris@101: relocker relock(lck); Chris@101: Rp res = local_fuct(ftmp); Chris@101: relock.lock(); Chris@101: this->mark_finished_with_result_internal(boost::move(res), lck); Chris@101: } catch (...) { Chris@101: this->mark_exceptional_finish_internal(current_exception(), lck); Chris@101: } Chris@101: } Chris@101: }; Chris@101: Chris@101: template Chris@101: struct shared_future_deferred_continuation_shared_state: shared_state Chris@101: { Chris@101: F parent; Chris@101: Fp continuation; Chris@101: shared_ptr centinel; Chris@101: Chris@101: public: Chris@101: shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) Chris@101: : parent(f), Chris@101: continuation(boost::move(c)), Chris@101: centinel(parent.future_) { Chris@101: this->set_deferred(); Chris@101: } Chris@101: Chris@101: virtual void launch_continuation(boost::unique_lock& lk, shared_ptr ) { Chris@101: if (this->is_deferred_) { Chris@101: this->is_deferred_=false; Chris@101: this->execute(lk); Chris@101: } Chris@101: } Chris@101: Chris@101: virtual void execute(boost::unique_lock& lck) { Chris@101: try { Chris@101: Fp local_fuct=boost::move(continuation); Chris@101: F ftmp = parent; Chris@101: relocker relock(lck); Chris@101: local_fuct(ftmp); Chris@101: relock.lock(); Chris@101: this->mark_finished_with_result_internal(lck); Chris@101: } catch (...) { Chris@101: this->mark_exceptional_finish_internal(current_exception(), lck); Chris@101: } Chris@101: } Chris@101: }; Chris@101: Chris@101: //////////////////////////////// Chris@101: // make_future_deferred_continuation_shared_state Chris@101: //////////////////////////////// Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_future_deferred_continuation_shared_state( Chris@101: boost::unique_lock &lock, Chris@101: BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) { Chris@101: shared_ptr > Chris@101: h(new future_deferred_continuation_shared_state(boost::move(f), boost::forward(c))); Chris@101: lock.lock(); Chris@101: h->parent.future_->set_continuation_ptr(h, lock); Chris@101: lock.unlock(); Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: Chris@101: //////////////////////////////// Chris@101: // make_future_async_continuation_shared_state Chris@101: //////////////////////////////// Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_future_async_continuation_shared_state( Chris@101: boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, Chris@101: BOOST_THREAD_FWD_REF(Fp) c) { Chris@101: shared_ptr > Chris@101: h(new future_async_continuation_shared_state(boost::move(f), boost::forward(c))); Chris@101: lock.lock(); Chris@101: h->parent.future_->set_continuation_ptr(h, lock); Chris@101: lock.unlock(); Chris@101: Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: Chris@101: //////////////////////////////// Chris@101: // make_future_executor_continuation_shared_state Chris@101: //////////////////////////////// Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_future_executor_continuation_shared_state(Ex& ex, Chris@101: boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, Chris@101: BOOST_THREAD_FWD_REF(Fp) c) { Chris@101: shared_ptr > Chris@101: h(new future_executor_continuation_shared_state(ex, boost::move(f), boost::forward(c))); Chris@101: lock.lock(); Chris@101: h->parent.future_->set_continuation_ptr(h, lock); Chris@101: lock.unlock(); Chris@101: Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@16: #endif Chris@101: Chris@101: //////////////////////////////// Chris@101: // make_shared_future_deferred_continuation_shared_state Chris@101: //////////////////////////////// Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_shared_future_deferred_continuation_shared_state( Chris@101: boost::unique_lock &lock, Chris@101: F f, BOOST_THREAD_FWD_REF(Fp) c) { Chris@101: shared_ptr > Chris@101: h(new shared_future_deferred_continuation_shared_state(f, boost::forward(c))); Chris@101: lock.lock(); Chris@101: h->parent.future_->set_continuation_ptr(h, lock); Chris@101: lock.unlock(); Chris@101: Chris@101: return BOOST_THREAD_FUTURE(h); Chris@16: } Chris@101: //////////////////////////////// Chris@101: // make_shared_future_async_continuation_shared_state Chris@101: //////////////////////////////// Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_shared_future_async_continuation_shared_state( Chris@101: boost::unique_lock &lock, F f, Chris@101: BOOST_THREAD_FWD_REF(Fp) c) { Chris@101: shared_ptr > Chris@101: h(new shared_future_async_continuation_shared_state(f, boost::forward(c))); Chris@101: lock.lock(); Chris@101: h->parent.future_->set_continuation_ptr(h, lock); Chris@101: lock.unlock(); Chris@101: Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: //////////////////////////////// Chris@101: // make_shared_future_executor_continuation_shared_state Chris@101: //////////////////////////////// Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_shared_future_executor_continuation_shared_state(Ex& ex, Chris@101: boost::unique_lock &lock, F f, Chris@101: BOOST_THREAD_FWD_REF(Fp) c) { Chris@101: shared_ptr > Chris@101: h(new shared_future_executor_continuation_shared_state(ex, f, boost::forward(c))); Chris@101: lock.lock(); Chris@101: h->parent.future_->set_continuation_ptr(h, lock); Chris@101: lock.unlock(); Chris@101: Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: #endif Chris@101: } Chris@16: Chris@16: //////////////////////////////// Chris@16: // template Chris@16: // auto future::then(F&& func) -> BOOST_THREAD_FUTURE; Chris@16: //////////////////////////////// Chris@16: Chris@16: template Chris@16: template Chris@16: inline BOOST_THREAD_FUTURE)>::type> Chris@101: BOOST_THREAD_FUTURE::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { Chris@16: typedef typename boost::result_of)>::type future_type; Chris@16: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@16: Chris@16: boost::unique_lock lock(this->future_->mutex); Chris@101: if (underlying_cast(policy) & int(launch::async)) { Chris@101: lock.unlock(); Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type, F>( Chris@101: lock, boost::move(*this), boost::forward(func) Chris@101: ))); Chris@101: } else if (underlying_cast(policy) & int(launch::deferred)) { Chris@101: this->future_->wait_internal(lock); Chris@101: lock.unlock(); Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state, future_type, F>( Chris@101: lock, boost::move(*this), boost::forward(func) Chris@101: ))); Chris@101: } else { Chris@101: lock.unlock(); Chris@16: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type, F>( Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ))); Chris@16: } Chris@101: } Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: template Chris@101: template Chris@101: inline BOOST_THREAD_FUTURE)>::type> Chris@101: BOOST_THREAD_FUTURE::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) { Chris@101: typedef typename boost::result_of)>::type future_type; Chris@101: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@101: Chris@101: boost::unique_lock lock(this->future_->mutex); Chris@101: lock.unlock(); Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state, future_type, F>(ex, Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ))); Chris@16: } Chris@101: #endif Chris@16: template Chris@16: template Chris@16: inline BOOST_THREAD_FUTURE)>::type> Chris@101: BOOST_THREAD_FUTURE::then(BOOST_THREAD_FWD_REF(F) func) { Chris@16: typedef typename boost::result_of)>::type future_type; Chris@16: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@16: Chris@16: boost::unique_lock lock(this->future_->mutex); Chris@101: if (underlying_cast(this->launch_policy(lock)) & int(launch::async)) { Chris@101: lock.unlock(); Chris@16: return boost::detail::make_future_async_continuation_shared_state, future_type, F>( Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ); Chris@101: } else if (underlying_cast(this->launch_policy(lock)) & int(launch::deferred)) { Chris@16: this->future_->wait_internal(lock); Chris@101: lock.unlock(); Chris@16: return boost::detail::make_future_deferred_continuation_shared_state, future_type, F>( Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ); Chris@101: } else { Chris@101: lock.unlock(); Chris@16: return boost::detail::make_future_async_continuation_shared_state, future_type, F>( Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ); Chris@16: } Chris@16: } Chris@16: Chris@101: //////////////////////////////// Chris@101: // template Chris@101: // auto future>::then(F&& func) -> BOOST_THREAD_FUTURE; Chris@101: //////////////////////////////// Chris@101: Chris@101: template Chris@16: template Chris@101: inline BOOST_THREAD_FUTURE >)>::type> Chris@101: BOOST_THREAD_FUTURE >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { Chris@101: typedef BOOST_THREAD_FUTURE R; Chris@101: typedef typename boost::result_of)>::type future_type; Chris@16: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@16: Chris@16: boost::unique_lock lock(this->future_->mutex); Chris@101: if (underlying_cast(policy) & int(launch::async)) { Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type, F>( Chris@101: lock, boost::move(*this), boost::forward(func) Chris@101: ))); Chris@101: } else if (underlying_cast(policy) & int(launch::deferred)) { Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state, future_type, F>( Chris@101: lock, boost::move(*this), boost::forward(func) Chris@101: ))); Chris@101: } else { Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type, F>( Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ))); Chris@16: } Chris@101: } Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: template Chris@101: template Chris@101: inline BOOST_THREAD_FUTURE >)>::type> Chris@101: BOOST_THREAD_FUTURE >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) { Chris@101: typedef BOOST_THREAD_FUTURE R; Chris@101: typedef typename boost::result_of)>::type future_type; Chris@101: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@101: Chris@101: boost::unique_lock lock(this->future_->mutex); Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state, future_type, F>(ex, Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ))); Chris@16: } Chris@101: #endif Chris@101: template Chris@16: template Chris@101: inline BOOST_THREAD_FUTURE >)>::type> Chris@101: BOOST_THREAD_FUTURE >::then(BOOST_THREAD_FWD_REF(F) func) { Chris@101: typedef BOOST_THREAD_FUTURE R; Chris@101: typedef typename boost::result_of)>::type future_type; Chris@16: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@16: Chris@16: boost::unique_lock lock(this->future_->mutex); Chris@101: if (underlying_cast(this->launch_policy(lock)) & int(launch::async)) { Chris@101: return boost::detail::make_future_async_continuation_shared_state, future_type, F>( Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ); Chris@101: } else if (underlying_cast(this->launch_policy(lock)) & int(launch::deferred)) { Chris@16: this->future_->wait_internal(lock); Chris@101: return boost::detail::make_future_deferred_continuation_shared_state, future_type, F>( Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ); Chris@101: } else { Chris@101: return boost::detail::make_future_async_continuation_shared_state, future_type, F>( Chris@16: lock, boost::move(*this), boost::forward(func) Chris@16: ); Chris@16: } Chris@16: } Chris@101: Chris@101: //////////////////////////////// Chris@101: // template Chris@101: // auto shared_future::then(F&& func) -> BOOST_THREAD_FUTURE; Chris@101: //////////////////////////////// Chris@101: Chris@101: template Chris@101: template Chris@101: inline BOOST_THREAD_FUTURE)>::type> Chris@101: shared_future::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const Chris@16: { Chris@101: typedef typename boost::result_of)>::type future_type; Chris@101: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@101: Chris@101: boost::unique_lock lock(this->future_->mutex); Chris@101: if (underlying_cast(policy) & int(launch::async)) { Chris@101: lock.unlock(); Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state, future_type, F>( Chris@101: lock, *this, boost::forward(func) Chris@101: ))); Chris@101: } else if (underlying_cast(policy) & int(launch::deferred)) { Chris@101: this->future_->wait_internal(lock); Chris@101: lock.unlock(); Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state, future_type, F>( Chris@101: lock, *this, boost::forward(func) Chris@101: ))); Chris@101: } else { Chris@101: lock.unlock(); Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state, future_type, F>( Chris@101: lock, *this, boost::forward(func) Chris@101: ))); Chris@101: } Chris@16: } Chris@101: #ifdef BOOST_THREAD_PROVIDES_EXECUTORS Chris@101: template Chris@101: template Chris@101: inline BOOST_THREAD_FUTURE)>::type> Chris@101: shared_future::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const Chris@101: { Chris@101: typedef typename boost::result_of)>::type future_type; Chris@101: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@101: Chris@101: boost::unique_lock lock(this->future_->mutex); Chris@101: lock.unlock(); Chris@101: return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state, future_type, F>(ex, Chris@101: lock, *this, boost::forward(func) Chris@101: ))); Chris@101: } Chris@101: #endif Chris@101: Chris@101: template Chris@101: template Chris@101: inline BOOST_THREAD_FUTURE)>::type> Chris@101: shared_future::then(BOOST_THREAD_FWD_REF(F) func) const { Chris@101: typedef typename boost::result_of)>::type future_type; Chris@101: Chris@101: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@101: Chris@101: boost::unique_lock lock(this->future_->mutex); Chris@101: if (underlying_cast(this->launch_policy(lock)) & int(launch::async)) { Chris@101: lock.unlock(); Chris@101: return boost::detail::make_shared_future_async_continuation_shared_state, future_type, F>( Chris@101: lock, *this, boost::forward(func)); Chris@101: } else if (underlying_cast(this->launch_policy(lock)) & int(launch::deferred)) { Chris@101: this->future_->wait_internal(lock); Chris@101: lock.unlock(); Chris@101: return boost::detail::make_shared_future_deferred_continuation_shared_state, future_type, F>( Chris@101: lock, *this, boost::forward(func)); Chris@101: } else { Chris@101: lock.unlock(); Chris@101: return boost::detail::make_shared_future_async_continuation_shared_state, future_type, F>( Chris@101: lock, *this, boost::forward(func)); Chris@101: } Chris@101: } Chris@101: Chris@101: namespace detail Chris@101: { Chris@101: template Chris@101: struct mfallbacker_to Chris@101: { Chris@101: T value_; Chris@101: typedef T result_type; Chris@101: mfallbacker_to(BOOST_THREAD_RV_REF(T) v) Chris@101: : value_(boost::move(v)) Chris@101: {} Chris@101: Chris@101: T operator()(BOOST_THREAD_FUTURE fut) { Chris@101: return fut.get_or(boost::move(value_)); Chris@101: } Chris@101: }; Chris@101: template Chris@101: struct cfallbacker_to Chris@101: { Chris@101: T value_; Chris@101: typedef T result_type; Chris@101: cfallbacker_to(T const& v) Chris@101: : value_(v) Chris@101: {} Chris@101: Chris@101: T operator()(BOOST_THREAD_FUTURE fut) const { Chris@101: return fut.get_or(value_); Chris@101: Chris@101: } Chris@101: }; Chris@101: } Chris@16: //////////////////////////////// Chris@16: // future future::fallback_to(R&& v); Chris@16: //////////////////////////////// Chris@16: Chris@16: template Chris@16: template Chris@16: inline typename boost::disable_if< is_void, BOOST_THREAD_FUTURE >::type Chris@101: BOOST_THREAD_FUTURE::fallback_to(BOOST_THREAD_RV_REF(R2) v) { Chris@16: return then(detail::mfallbacker_to(boost::move(v))); Chris@16: } Chris@16: Chris@16: template Chris@16: template Chris@16: inline typename boost::disable_if< is_void, BOOST_THREAD_FUTURE >::type Chris@101: BOOST_THREAD_FUTURE::fallback_to(R2 const& v) { Chris@16: return then(detail::cfallbacker_to(v)); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP Chris@101: namespace detail Chris@101: { Chris@101: ///////////////////////// Chris@101: /// future_unwrap_shared_state Chris@101: ///////////////////////// Chris@101: Chris@101: template Chris@101: struct future_unwrap_shared_state: shared_state Chris@16: { Chris@101: F parent; Chris@101: public: Chris@101: explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f) Chris@101: : parent(boost::move(f)) {} Chris@101: Chris@101: typename F::value_type parent_value(boost::unique_lock& ) { Chris@101: typename F::value_type r = parent.get(); Chris@101: r.set_exceptional_if_invalid(); Chris@101: return boost::move(r); Chris@101: } Chris@101: Chris@101: virtual void wait(boost::unique_lock& lk, bool ) { // todo see if rethrow must be used Chris@101: parent_value(lk).wait(); Chris@101: } Chris@101: virtual Rp get(boost::unique_lock& lk) { Chris@101: return parent_value(lk).get(); Chris@101: } Chris@101: #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION Chris@101: typedef shared_ptr continuation_ptr_type; Chris@101: Chris@101: virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock& lock) Chris@16: { Chris@101: boost::unique_lock lk(parent.future_->mutex); Chris@101: parent.future_->set_continuation_ptr(continuation, lk); Chris@16: } Chris@101: #endif Chris@101: }; Chris@101: Chris@101: template Chris@101: BOOST_THREAD_FUTURE Chris@101: make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f) { Chris@101: shared_ptr > Chris@101: h(new future_unwrap_shared_state(boost::move(f))); Chris@101: lock.lock(); Chris@101: h->parent.future_->set_continuation_ptr(h, lock); Chris@101: lock.unlock(); Chris@101: return BOOST_THREAD_FUTURE(h); Chris@16: } Chris@101: } Chris@16: Chris@16: template Chris@101: inline BOOST_THREAD_FUTURE::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE >) other) Chris@101: : base_type(other.unwrap()) {} Chris@16: Chris@16: template Chris@16: BOOST_THREAD_FUTURE Chris@16: BOOST_THREAD_FUTURE >::unwrap() Chris@16: { Chris@16: BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); Chris@16: boost::unique_lock lock(this->future_->mutex); Chris@101: lock.unlock(); Chris@16: return boost::detail::make_future_unwrap_shared_state >, R2>(lock, boost::move(*this)); Chris@16: } Chris@16: #endif Chris@101: Chris@101: #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY Chris@101: namespace detail Chris@101: { Chris@101: struct input_iterator_tag {}; Chris@101: struct vector_tag {}; Chris@101: struct values_tag {}; Chris@101: template Chris@101: struct alias_t { typedef T type; }; Chris@101: Chris@101: BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {}; Chris@101: BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {}; Chris@101: BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {}; Chris@101: //////////////////////////////// Chris@101: // detail::future_async_when_all_shared_state Chris@101: //////////////////////////////// Chris@101: template Chris@101: struct future_when_all_vector_shared_state: future_async_shared_state_base > Chris@101: { Chris@101: typedef csbl::vector vector_type; Chris@101: typedef typename F::value_type value_type; Chris@101: vector_type vec_; Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: future_when_all_vector_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: boost::wait_for_all(that->vec_.begin(), that->vec_.end()); Chris@101: that->mark_finished_with_result(boost::move(that->vec_)); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: bool run_deferred() { Chris@101: Chris@101: bool res = false; Chris@101: for (typename csbl::vector::iterator it = vec_.begin(); it != vec_.end(); ++it) { Chris@101: if (! it->run_if_is_deferred()) Chris@101: { Chris@101: res = true; Chris@101: } Chris@101: } Chris@101: return res; Chris@101: } Chris@101: void init() { Chris@101: if (! run_deferred()) Chris@101: { Chris@101: future_when_all_vector_shared_state::run(this->shared_from_this()); Chris@101: return; Chris@101: } Chris@101: this->thr_ = thread(&future_when_all_vector_shared_state::run, this->shared_from_this()); Chris@101: } Chris@101: Chris@101: public: Chris@101: template< typename InputIterator> Chris@101: future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last) Chris@101: : vec_(std::make_move_iterator(first), std::make_move_iterator(last)) Chris@101: { Chris@101: } Chris@101: Chris@101: future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector) v) Chris@101: : vec_(boost::move(v)) Chris@101: { Chris@101: } Chris@101: Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template< typename T0, typename ...T> Chris@101: future_when_all_vector_shared_state(values_tag, BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) { Chris@101: vec_.push_back(boost::forward(f)); Chris@101: typename alias_t::type{ Chris@101: ( //first part of magic unpacker Chris@101: vec_.push_back(boost::forward(futures)),'0' Chris@101: )..., '0' Chris@101: }; //second part of magic unpacker Chris@101: } Chris@101: #endif Chris@101: Chris@101: ~future_when_all_vector_shared_state() {} Chris@101: }; Chris@101: Chris@101: //////////////////////////////// Chris@101: // detail::future_async_when_any_shared_state Chris@101: //////////////////////////////// Chris@101: template Chris@101: struct future_when_any_vector_shared_state: future_async_shared_state_base > Chris@101: { Chris@101: typedef csbl::vector vector_type; Chris@101: typedef typename F::value_type value_type; Chris@101: vector_type vec_; Chris@101: Chris@101: static void run(shared_ptr that_) Chris@101: { Chris@101: future_when_any_vector_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: boost::wait_for_any(that->vec_.begin(), that->vec_.end()); Chris@101: that->mark_finished_with_result(boost::move(that->vec_)); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: bool run_deferred() { Chris@101: Chris@101: for (typename csbl::vector::iterator it = vec_.begin(); it != vec_.end(); ++it) { Chris@101: if (it->run_if_is_deferred_or_ready()) Chris@101: { Chris@101: return true; Chris@101: } Chris@101: } Chris@101: return false; Chris@101: } Chris@101: void init() { Chris@101: if (run_deferred()) Chris@101: { Chris@101: future_when_any_vector_shared_state::run(this->shared_from_this()); Chris@101: return; Chris@101: } Chris@101: Chris@101: this->thr_ = thread(&future_when_any_vector_shared_state::run, this->shared_from_this()); Chris@101: } Chris@101: Chris@101: public: Chris@101: template< typename InputIterator> Chris@101: future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last) Chris@101: : vec_(std::make_move_iterator(first), std::make_move_iterator(last)) Chris@101: { Chris@101: } Chris@101: Chris@101: future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector) v) Chris@101: : vec_(boost::move(v)) Chris@101: { Chris@101: } Chris@101: Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template< typename T0, typename ...T> Chris@101: future_when_any_vector_shared_state(values_tag, Chris@101: BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures Chris@101: ) { Chris@101: vec_.push_back(boost::forward(f)); Chris@101: typename alias_t::type{ Chris@101: ( //first part of magic unpacker Chris@101: vec_.push_back(boost::forward(futures)) Chris@101: ,'0' Chris@101: )..., Chris@101: '0' Chris@101: }; //second part of magic unpacker Chris@101: } Chris@101: #endif Chris@101: Chris@101: ~future_when_any_vector_shared_state() {} Chris@101: }; Chris@101: Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: struct wait_for_all_fctr { Chris@101: template Chris@101: void operator()(T&&... v) { Chris@101: boost::wait_for_all(boost::forward(v)...); Chris@101: } Chris@101: }; Chris@101: Chris@101: struct wait_for_any_fctr { Chris@101: template Chris@101: void operator()(T&&... v) { Chris@101: boost::wait_for_any(boost::forward(v)...); Chris@101: } Chris@101: }; Chris@101: Chris@101: Chris@101: template ::value> Chris@101: struct accumulate_run_if_is_deferred { Chris@101: bool operator ()(Tuple& t) Chris@101: { Chris@101: return (! csbl::get(t).run_if_is_deferred()) || accumulate_run_if_is_deferred()(t); Chris@101: } Chris@101: }; Chris@101: template Chris@101: struct accumulate_run_if_is_deferred { Chris@101: bool operator ()(Tuple& ) Chris@101: { Chris@101: return false; Chris@101: } Chris@101: }; Chris@101: Chris@101: Chris@101: template< typename Tuple, typename T0, typename ...T> Chris@101: struct future_when_all_tuple_shared_state: future_async_shared_state_base Chris@101: { Chris@101: Tuple tup_; Chris@101: typedef typename make_tuple_indices<1+sizeof...(T)>::type Index; Chris@101: Chris@101: static void run(shared_ptr that_) { Chris@101: future_when_all_tuple_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor()); Chris@101: that->wait_for_all(Index()); Chris@101: Chris@101: that->mark_finished_with_result(boost::move(that->tup_)); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: Chris@101: template Chris@101: void wait_for_all(tuple_indices) { Chris@101: #if defined BOOST_THREAD_PROVIDES_INVOKE Chris@101: return invoke(wait_for_all_fctr(), csbl::get(tup_)...); Chris@101: #else Chris@101: return wait_for_all_fctr()(csbl::get(tup_)...); Chris@101: #endif Chris@101: } Chris@101: Chris@101: bool run_deferred() { Chris@101: Chris@101: return accumulate_run_if_is_deferred()(tup_); Chris@101: } Chris@101: void init() { Chris@101: if (! run_deferred()) Chris@101: { Chris@101: future_when_all_tuple_shared_state::run(this->shared_from_this()); Chris@101: return; Chris@101: } Chris@101: Chris@101: this->thr_ = thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()); Chris@101: } Chris@101: public: Chris@101: template< typename F, typename ...Fs> Chris@101: future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) : Chris@101: tup_(boost::csbl::make_tuple(boost::forward(f), boost::forward(futures)...)) Chris@101: { Chris@101: } Chris@101: Chris@101: ~future_when_all_tuple_shared_state() {} Chris@101: Chris@101: }; Chris@101: Chris@101: Chris@101: template ::value> Chris@101: struct apply_any_run_if_is_deferred_or_ready { Chris@101: bool operator ()(Tuple& t) Chris@101: { Chris@101: if (csbl::get(t).run_if_is_deferred_or_ready()) return true; Chris@101: return apply_any_run_if_is_deferred_or_ready()(t); Chris@101: } Chris@101: }; Chris@101: template Chris@101: struct apply_any_run_if_is_deferred_or_ready { Chris@101: bool operator ()(Tuple& ) Chris@101: { Chris@101: return false; Chris@101: } Chris@101: }; Chris@101: Chris@101: template< typename Tuple, typename T0, typename ...T > Chris@101: struct future_when_any_tuple_shared_state: future_async_shared_state_base Chris@101: { Chris@101: Tuple tup_; Chris@101: typedef typename make_tuple_indices<1+sizeof...(T)>::type Index; Chris@101: Chris@101: static void run(shared_ptr that_) Chris@101: { Chris@101: future_when_any_tuple_shared_state* that = dynamic_cast(that_.get()); Chris@101: try { Chris@101: // TODO make use of apply(that->tup_, wait_for_any_fctr); Chris@101: that->wait_for_any(Index()); Chris@101: Chris@101: that->mark_finished_with_result(boost::move(that->tup_)); Chris@101: } catch(...) { Chris@101: that->mark_exceptional_finish(); Chris@101: } Chris@101: } Chris@101: template Chris@101: void wait_for_any(tuple_indices) { Chris@101: #if defined BOOST_THREAD_PROVIDES_INVOKE Chris@101: return invoke(wait_for_any_fctr(), csbl::get(tup_)...); Chris@101: #else Chris@101: return wait_for_any_fctr()(csbl::get(tup_)...); Chris@101: #endif Chris@101: } Chris@101: bool run_deferred() { Chris@101: return apply_any_run_if_is_deferred_or_ready()(tup_); Chris@101: } Chris@101: void init() { Chris@101: if (run_deferred()) Chris@101: { Chris@101: future_when_any_tuple_shared_state::run(this->shared_from_this()); Chris@101: return; Chris@101: } Chris@101: Chris@101: this->thr_ = thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()); Chris@101: } Chris@101: Chris@101: public: Chris@101: template< typename F, typename ...Fs> Chris@101: future_when_any_tuple_shared_state(values_tag, Chris@101: BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures Chris@101: ) : Chris@101: tup_(boost::csbl::make_tuple(boost::forward(f), boost::forward(futures)...)) Chris@101: { Chris@101: } Chris@101: Chris@101: ~future_when_any_tuple_shared_state() {} Chris@101: }; Chris@101: #endif Chris@101: Chris@101: } Chris@101: Chris@101: template< typename InputIterator> Chris@101: typename boost::disable_if, Chris@101: BOOST_THREAD_FUTURE > Chris@101: >::type Chris@101: when_all(InputIterator first, InputIterator last) { Chris@101: typedef typename InputIterator::value_type value_type; Chris@101: typedef csbl::vector container_type; Chris@101: typedef detail::future_when_all_vector_shared_state factory_type; Chris@101: Chris@101: if (first==last) return make_ready_future(container_type()); Chris@101: shared_ptr Chris@101: h(new factory_type(detail::input_iterator_tag_value, first,last)); Chris@101: h->init(); Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: Chris@101: inline BOOST_THREAD_FUTURE > when_all() { Chris@101: return make_ready_future(csbl::tuple<>()); Chris@101: } Chris@101: Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template< typename T0, typename ...T> Chris@101: BOOST_THREAD_FUTURE::type, typename decay::type...> > Chris@101: when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) { Chris@101: typedef csbl::tuple::type, typename decay::type...> container_type; Chris@101: typedef detail::future_when_all_tuple_shared_state::type, typename decay::type...> factory_type; Chris@101: Chris@101: shared_ptr Chris@101: h(new factory_type(detail::values_tag_value, boost::forward(f), boost::forward(futures)...)); Chris@101: h->init(); Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: #endif Chris@101: Chris@101: template< typename InputIterator> Chris@101: typename boost::disable_if, Chris@101: BOOST_THREAD_FUTURE > Chris@101: >::type Chris@101: when_any(InputIterator first, InputIterator last) { Chris@101: typedef typename InputIterator::value_type value_type; Chris@101: typedef csbl::vector container_type; Chris@101: typedef detail::future_when_any_vector_shared_state factory_type; Chris@101: Chris@101: if (first==last) return make_ready_future(container_type()); Chris@101: shared_ptr Chris@101: h(new factory_type(detail::input_iterator_tag_value, first,last)); Chris@101: h->init(); Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: Chris@101: inline BOOST_THREAD_FUTURE > when_any() { Chris@101: return make_ready_future(csbl::tuple<>()); Chris@101: } Chris@101: Chris@101: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template< typename T0, typename ...T> Chris@101: BOOST_THREAD_FUTURE::type, typename decay::type...> > Chris@101: when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) { Chris@101: typedef csbl::tuple::type, typename decay::type...> container_type; Chris@101: typedef detail::future_when_any_tuple_shared_state::type, typename decay::type...> factory_type; Chris@101: Chris@101: shared_ptr Chris@101: h(new factory_type(detail::values_tag_value, boost::forward(f), boost::forward(futures)...)); Chris@101: h->init(); Chris@101: return BOOST_THREAD_FUTURE(h); Chris@101: } Chris@101: #endif Chris@101: #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY Chris@16: } Chris@16: Chris@16: #endif // BOOST_NO_EXCEPTION Chris@16: #endif // header