diff options
Diffstat (limited to '3rdParty/Boost/src/boost/thread/future.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/thread/future.hpp | 1243 |
1 files changed, 864 insertions, 379 deletions
diff --git a/3rdParty/Boost/src/boost/thread/future.hpp b/3rdParty/Boost/src/boost/thread/future.hpp index a4b4343..6bf5cf6 100644 --- a/3rdParty/Boost/src/boost/thread/future.hpp +++ b/3rdParty/Boost/src/boost/thread/future.hpp @@ -1,4 +1,5 @@ -// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -6,6 +7,15 @@ #ifndef BOOST_THREAD_FUTURE_HPP #define BOOST_THREAD_FUTURE_HPP + +#include <boost/thread/detail/config.hpp> + +// boost::thread::future requires exception handling +// due to boost::exception::exception_ptr dependency + +#ifndef BOOST_NO_EXCEPTIONS + +#include <boost/detail/scoped_enum_emulation.hpp> #include <stdexcept> #include <boost/thread/detail/move.hpp> #include <boost/thread/thread_time.hpp> @@ -16,6 +26,8 @@ #include <boost/scoped_ptr.hpp> #include <boost/type_traits/is_fundamental.hpp> #include <boost/type_traits/is_convertible.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/type_traits/remove_cv.hpp> #include <boost/mpl/if.hpp> #include <boost/config.hpp> #include <boost/throw_exception.hpp> @@ -28,59 +40,168 @@ #include <list> #include <boost/next_prior.hpp> #include <vector> +#include <boost/system/error_code.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#endif + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include <boost/thread/detail/memory.hpp> +#endif + +#include <boost/utility/result_of.hpp> +#include <boost/thread/thread.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_FUTURE future +#else +#define BOOST_THREAD_FUTURE unique_future +#endif + namespace boost { - class future_uninitialized: - public std::logic_error + + //enum class future_errc + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc) + { + broken_promise, + future_already_retrieved, + promise_already_satisfied, + no_state + } + BOOST_SCOPED_ENUM_DECLARE_END(future_errc) + + namespace system + { + template <> + struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type {}; + + #ifdef BOOST_NO_CXX11_SCOPED_ENUMS + template <> + struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { }; + #endif + } + + //enum class launch + BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch) + { + async = 1, + deferred = 2, + any = async | deferred + } + BOOST_SCOPED_ENUM_DECLARE_END(launch) + + //enum class future_status + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status) + { + ready, + timeout, + deferred + } + BOOST_SCOPED_ENUM_DECLARE_END(future_status) + + BOOST_THREAD_DECL + const system::error_category& future_category() BOOST_NOEXCEPT; + + namespace system + { + inline + error_code + make_error_code(future_errc e) //BOOST_NOEXCEPT + { + return error_code(underlying_cast<int>(e), boost::future_category()); + } + + inline + error_condition + make_error_condition(future_errc e) //BOOST_NOEXCEPT + { + return error_condition(underlying_cast<int>(e), future_category()); + } + } + + class BOOST_SYMBOL_VISIBLE future_error + : public std::logic_error + { + system::error_code ec_; + public: + future_error(system::error_code ec) + : logic_error(ec.message()), + ec_(ec) + { + } + + const system::error_code& code() const BOOST_NOEXCEPT + { + return ec_; + } + const char* what() const BOOST_THREAD_NOEXCEPT_OR_THROW + { + return code().message().c_str(); + } + + }; + + class BOOST_SYMBOL_VISIBLE future_uninitialized: + public future_error { public: - future_uninitialized(): - std::logic_error("Future Uninitialized") + future_uninitialized() : + future_error(system::make_error_code(future_errc::no_state)) {} }; - class broken_promise: - public std::logic_error + class BOOST_SYMBOL_VISIBLE broken_promise: + public future_error { public: broken_promise(): - std::logic_error("Broken promise") + future_error(system::make_error_code(future_errc::broken_promise)) {} }; - class future_already_retrieved: - public std::logic_error + class BOOST_SYMBOL_VISIBLE future_already_retrieved: + public future_error { public: future_already_retrieved(): - std::logic_error("Future already retrieved") + future_error(system::make_error_code(future_errc::future_already_retrieved)) {} }; - class promise_already_satisfied: - public std::logic_error + class BOOST_SYMBOL_VISIBLE promise_already_satisfied: + public future_error { public: promise_already_satisfied(): - std::logic_error("Promise already satisfied") + future_error(system::make_error_code(future_errc::promise_already_satisfied)) {} }; - class task_already_started: - public std::logic_error + class BOOST_SYMBOL_VISIBLE task_already_started: + public future_error { public: task_already_started(): - std::logic_error("Task already started") + future_error(system::make_error_code(future_errc::promise_already_satisfied)) {} }; - class task_moved: - public std::logic_error - { - public: - task_moved(): - std::logic_error("Task moved") - {} - }; + class BOOST_SYMBOL_VISIBLE task_moved: + public future_error + { + public: + task_moved(): + future_error(system::make_error_code(future_errc::no_state)) + {} + }; + + class promise_moved: + public future_error + { + public: + promise_moved(): + future_error(system::make_error_code(future_errc::no_state)) + {} + }; namespace future_state { @@ -93,6 +214,7 @@ namespace boost { boost::exception_ptr exception; bool done; + bool thread_was_interrupted; boost::mutex mutex; boost::condition_variable waiters; typedef std::list<boost::condition_variable_any*> waiter_list; @@ -100,7 +222,8 @@ namespace boost boost::function<void()> callback; future_object_base(): - done(false) + done(false), + thread_was_interrupted(false) {} virtual ~future_object_base() {} @@ -111,7 +234,7 @@ namespace boost do_callback(lock); return external_waiters.insert(external_waiters.end(),&cv); } - + void remove_external_waiter(waiter_list::iterator it) { boost::lock_guard<boost::mutex> lock(mutex); @@ -132,7 +255,7 @@ namespace boost struct relocker { boost::unique_lock<boost::mutex>& lock; - + relocker(boost::unique_lock<boost::mutex>& lock_): lock(lock_) { @@ -155,7 +278,7 @@ namespace boost local_callback(); } } - + void wait(bool rethrow=true) { @@ -165,6 +288,10 @@ namespace boost { waiters.wait(lock); } + if(rethrow && thread_was_interrupted) + { + throw boost::thread_interrupted(); + } if(rethrow && exception) { boost::rethrow_exception(exception); @@ -185,7 +312,26 @@ namespace boost } return true; } - + +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) + { + boost::unique_lock<boost::mutex> lock(mutex); + do_callback(lock); + while(!done) + { + cv_status const st=waiters.wait_until(lock,abs_time); + if(st==cv_status::timeout && !done) + { + return future_status::timeout; + } + } + return future_status::ready; + } +#endif void mark_exceptional_finish_internal(boost::exception_ptr const& e) { exception=e; @@ -196,16 +342,21 @@ namespace boost boost::lock_guard<boost::mutex> lock(mutex); mark_exceptional_finish_internal(boost::current_exception()); } - + void mark_interrupted_finish() + { + boost::lock_guard<boost::mutex> lock(mutex); + thread_was_interrupted=true; + mark_finished_internal(); + } bool has_value() { boost::lock_guard<boost::mutex> lock(mutex); - return done && !exception; + return done && !(exception || thread_was_interrupted); } bool has_exception() { boost::lock_guard<boost::mutex> lock(mutex); - return done && exception; + return done && (exception || thread_was_interrupted); } template<typename F,typename U> @@ -213,7 +364,7 @@ namespace boost { callback=boost::bind(f,boost::ref(*u)); } - + private: future_object_base(future_object_base const&); future_object_base& operator=(future_object_base const&); @@ -223,25 +374,31 @@ namespace boost struct future_traits { typedef boost::scoped_ptr<T> storage_type; -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES typedef T const& source_reference_type; struct dummy; - typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type; - typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,T&&>::type move_dest_type; + typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; + typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type; +#elif defined BOOST_THREAD_USES_MOVE + typedef T& source_reference_type; + typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; + typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; #else typedef T& source_reference_type; - typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T const&>::type rvalue_source_type; - typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T>::type move_dest_type; + typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; + typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; #endif + typedef const T& shared_future_get_result_type; + static void init(storage_type& storage,source_reference_type t) { storage.reset(new T(t)); } - + static void init(storage_type& storage,rvalue_source_type t) { - storage.reset(new T(static_cast<rvalue_source_type>(t))); + storage.reset(new T(static_cast<rvalue_source_type>(t))); } static void cleanup(storage_type& storage) @@ -249,7 +406,7 @@ namespace boost storage.reset(); } }; - + template<typename T> struct future_traits<T&> { @@ -258,6 +415,7 @@ namespace boost struct rvalue_source_type {}; typedef T& move_dest_type; + typedef T& shared_future_get_result_type; static void init(storage_type& storage,T& t) { @@ -275,6 +433,7 @@ namespace boost { typedef bool storage_type; typedef void move_dest_type; + typedef void shared_future_get_result_type; static void init(storage_type& storage) { @@ -296,7 +455,8 @@ namespace boost typedef typename future_traits<T>::source_reference_type source_reference_type; typedef typename future_traits<T>::rvalue_source_type rvalue_source_type; typedef typename future_traits<T>::move_dest_type move_dest_type; - + typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type; + storage_type result; future_object(): @@ -308,6 +468,7 @@ namespace boost future_traits<T>::init(result,result_); mark_finished_internal(); } + void mark_finished_with_result_internal(rvalue_source_type result_) { future_traits<T>::init(result,static_cast<rvalue_source_type>(result_)); @@ -319,10 +480,11 @@ namespace boost boost::lock_guard<boost::mutex> lock(mutex); mark_finished_with_result_internal(result_); } + void mark_finished_with_result(rvalue_source_type result_) { boost::lock_guard<boost::mutex> lock(mutex); - mark_finished_with_result_internal(result_); + mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_)); } move_dest_type get() @@ -331,6 +493,12 @@ namespace boost return static_cast<move_dest_type>(*result); } + shared_future_get_result_type get_sh() + { + wait(); + return static_cast<shared_future_get_result_type>(*result); + } + future_state::state get_state() { boost::lock_guard<boost::mutex> guard(mutex); @@ -353,6 +521,8 @@ namespace boost struct future_object<void>: detail::future_object_base { + typedef void shared_future_get_result_type; + future_object() {} @@ -371,7 +541,10 @@ namespace boost { wait(); } - + void get_sh() + { + wait(); + } future_state::state get_state() { boost::lock_guard<boost::mutex> guard(mutex); @@ -384,74 +557,93 @@ namespace boost return future_state::ready; } } - private: future_object(future_object const&); future_object& operator=(future_object const&); }; +// template<typename T, typename Allocator> +// struct future_object_alloc: public future_object<T> +// { +// typedef future_object<T> base; +// Allocator alloc_; +// +// public: +// explicit future_object_alloc(const Allocator& a) +// : alloc_(a) {} +// +// }; class future_waiter { struct registered_waiter; - typedef std::vector<registered_waiter>::size_type count_type; - + typedef std::vector<int>::size_type count_type; + struct registered_waiter { - boost::shared_ptr<detail::future_object_base> future; + boost::shared_ptr<detail::future_object_base> future_; detail::future_object_base::waiter_list::iterator wait_iterator; count_type index; - registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_, + registered_waiter(boost::shared_ptr<detail::future_object_base> const& a_future, detail::future_object_base::waiter_list::iterator wait_iterator_, count_type index_): - future(future_),wait_iterator(wait_iterator_),index(index_) + future_(a_future),wait_iterator(wait_iterator_),index(index_) {} }; - + struct all_futures_lock { - count_type count; +#ifdef _MANAGED + typedef std::ptrdiff_t count_type_portable; +#else + typedef count_type count_type_portable; +#endif + count_type_portable count; boost::scoped_array<boost::unique_lock<boost::mutex> > locks; - + all_futures_lock(std::vector<registered_waiter>& futures): count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count]) { - for(count_type i=0;i<count;++i) + for(count_type_portable i=0;i<count;++i) { - locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex); +#if defined __DECCXX || defined __SUNPRO_CC || defined __hpux + locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move(); +#else + locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex); +#endif } } - + void lock() { boost::lock(locks.get(),locks.get()+count); } - + void unlock() { - for(count_type i=0;i<count;++i) + for(count_type_portable i=0;i<count;++i) { locks[i].unlock(); } } }; - + boost::condition_variable_any cv; std::vector<registered_waiter> futures; count_type future_count; - + public: future_waiter(): future_count(0) {} - + template<typename F> void add(F& f) { - if(f.future) + if(f.future_) { - futures.push_back(registered_waiter(f.future,f.future->register_external_waiter(cv),future_count)); + futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count)); } ++future_count; } @@ -463,7 +655,7 @@ namespace boost { for(count_type i=0;i<futures.size();++i) { - if(futures[i].future->done) + if(futures[i].future_->done) { return futures[i].index; } @@ -471,21 +663,21 @@ namespace boost cv.wait(lk); } } - + ~future_waiter() { for(count_type i=0;i<futures.size();++i) { - futures[i].future->remove_external_waiter(futures[i].wait_iterator); + futures[i].future_->remove_external_waiter(futures[i].wait_iterator); } } - + }; - + } template <typename R> - class unique_future; + class BOOST_THREAD_FUTURE; template <typename R> class shared_future; @@ -495,13 +687,13 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value=false); }; - + template<typename T> - struct is_future_type<unique_future<T> > + struct is_future_type<BOOST_THREAD_FUTURE<T> > { BOOST_STATIC_CONSTANT(bool, value=true); }; - + template<typename T> struct is_future_type<shared_future<T> > { @@ -531,7 +723,7 @@ namespace boost f2.wait(); f3.wait(); } - + template<typename F1,typename F2,typename F3,typename F4> void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4) { @@ -556,7 +748,7 @@ namespace boost { if(begin==end) return end; - + detail::future_waiter waiter; for(Iterator current=begin;current!=end;++current) { @@ -583,7 +775,7 @@ namespace boost waiter.add(f3); return waiter.wait(); } - + template<typename F1,typename F2,typename F3,typename F4> unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4) { @@ -606,7 +798,7 @@ namespace boost waiter.add(f5); return waiter.wait(); } - + template <typename R> class promise; @@ -614,14 +806,13 @@ namespace boost class packaged_task; template <typename R> - class unique_future + class BOOST_THREAD_FUTURE { - unique_future(unique_future & rhs);// = delete; - unique_future& operator=(unique_future& rhs);// = delete; + private: typedef boost::shared_ptr<detail::future_object<R> > future_ptr; - - future_ptr future; + + future_ptr future_; friend class shared_future<R>; friend class promise<R>; @@ -630,139 +821,151 @@ namespace boost typedef typename detail::future_traits<R>::move_dest_type move_dest_type; - unique_future(future_ptr future_): - future(future_) + BOOST_THREAD_FUTURE(future_ptr a_future): + future_(a_future) {} public: + BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) typedef future_state::state state; - unique_future() + BOOST_THREAD_FUTURE() {} - - ~unique_future() + + ~BOOST_THREAD_FUTURE() {} -#ifndef BOOST_NO_RVALUE_REFERENCES - unique_future(unique_future && other) - { - future.swap(other.future); - } - unique_future& operator=(unique_future && other) - { - future=other.future; - other.future.reset(); - return *this; - } -#else - unique_future(boost::detail::thread_move_t<unique_future> other): - future(other->future) + BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: + future_(BOOST_THREAD_RV(other).future_) { - other->future.reset(); + BOOST_THREAD_RV(other).future_.reset(); } - unique_future& operator=(boost::detail::thread_move_t<unique_future> other) + BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT { - future=other->future; - other->future.reset(); + future_=BOOST_THREAD_RV(other).future_; + BOOST_THREAD_RV(other).future_.reset(); return *this; } - operator boost::detail::thread_move_t<unique_future>() + shared_future<R> share() { - return boost::detail::thread_move_t<unique_future>(*this); + return shared_future<R>(::boost::move(*this)); } -#endif - void swap(unique_future& other) + void swap(BOOST_THREAD_FUTURE& other) { - future.swap(other.future); + future_.swap(other.future_); } // retrieving the value move_dest_type get() { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - return future->get(); + return future_->get(); } - + // functions to check state, and wait for ready - state get_state() const + state get_state() const BOOST_NOEXCEPT { - if(!future) + if(!future_) { return future_state::uninitialized; } - return future->get_state(); + return future_->get_state(); } - - bool is_ready() const + bool is_ready() const BOOST_NOEXCEPT { return get_state()==future_state::ready; } - - bool has_exception() const + + bool has_exception() const BOOST_NOEXCEPT { - return future && future->has_exception(); + return future_ && future_->has_exception(); } - - bool has_value() const + + bool has_value() const BOOST_NOEXCEPT { - return future && future->has_value(); + return future_ && future_->has_value(); } - + + bool valid() const BOOST_NOEXCEPT + { + return future_ != 0; + } + + void wait() const { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - future->wait(false); + future_->wait(false); } - + template<typename Duration> bool timed_wait(Duration const& rel_time) const { return timed_wait_until(boost::get_system_time()+rel_time); } - + bool timed_wait_until(boost::system_time const& abs_time) const { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - return future->timed_wait_until(abs_time); + return future_->timed_wait_until(abs_time); } - +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const + { + return wait_until(chrono::steady_clock::now() + rel_time); + + } + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->wait_until(abs_time); + } +#endif }; + BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END + template <typename R> class shared_future { typedef boost::shared_ptr<detail::future_object<R> > future_ptr; - - future_ptr future; -// shared_future(const unique_future<R>& other); -// shared_future& operator=(const unique_future<R>& other); + future_ptr future_; friend class detail::future_waiter; friend class promise<R>; friend class packaged_task<R>; - - shared_future(future_ptr future_): - future(future_) + + shared_future(future_ptr a_future): + future_(a_future) {} public: + BOOST_THREAD_MOVABLE(shared_future) + shared_future(shared_future const& other): - future(other.future) + future_(other.future_) {} typedef future_state::state state; @@ -775,396 +978,405 @@ namespace boost shared_future& operator=(shared_future const& other) { - future=other.future; + future_=other.future_; return *this; } -#ifndef BOOST_NO_RVALUE_REFERENCES - shared_future(shared_future && other) + shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(other).future_) { - future.swap(other.future); + BOOST_THREAD_RV(other).future_.reset(); } - shared_future(unique_future<R> && other) + shared_future(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(other).future_) { - future.swap(other.future); + BOOST_THREAD_RV(other).future_.reset(); } - shared_future& operator=(shared_future && other) + shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT { - future.swap(other.future); - other.future.reset(); + future_.swap(BOOST_THREAD_RV(other).future_); + BOOST_THREAD_RV(other).future_.reset(); return *this; } - shared_future& operator=(unique_future<R> && other) + shared_future& operator=(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT { - future.swap(other.future); - other.future.reset(); + future_.swap(BOOST_THREAD_RV(other).future_); + BOOST_THREAD_RV(other).future_.reset(); return *this; } -#else - shared_future(boost::detail::thread_move_t<shared_future> other): - future(other->future) - { - other->future.reset(); - } -// shared_future(const unique_future<R> &) = delete; - shared_future(boost::detail::thread_move_t<unique_future<R> > other): - future(other->future) - { - other->future.reset(); - } - shared_future& operator=(boost::detail::thread_move_t<shared_future> other) - { - future.swap(other->future); - other->future.reset(); - return *this; - } - shared_future& operator=(boost::detail::thread_move_t<unique_future<R> > other) - { - future.swap(other->future); - other->future.reset(); - return *this; - } - - operator boost::detail::thread_move_t<shared_future>() - { - return boost::detail::thread_move_t<shared_future>(*this); - } - -#endif - void swap(shared_future& other) + void swap(shared_future& other) BOOST_NOEXCEPT { - future.swap(other.future); + future_.swap(other.future_); } // retrieving the value - R get() + typename detail::future_object<R>::shared_future_get_result_type get() { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - return future->get(); + return future_->get_sh(); } - + // functions to check state, and wait for ready - state get_state() const + state get_state() const BOOST_NOEXCEPT { - if(!future) + if(!future_) { return future_state::uninitialized; } - return future->get_state(); + return future_->get_state(); } - - bool is_ready() const + bool valid() const BOOST_NOEXCEPT + { + return future_ != 0; + } + + bool is_ready() const BOOST_NOEXCEPT { return get_state()==future_state::ready; } - - bool has_exception() const + + bool has_exception() const BOOST_NOEXCEPT { - return future && future->has_exception(); + return future_ && future_->has_exception(); } - - bool has_value() const + + bool has_value() const BOOST_NOEXCEPT { - return future && future->has_value(); + return future_ && future_->has_value(); } void wait() const { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - future->wait(false); + future_->wait(false); } - + template<typename Duration> bool timed_wait(Duration const& rel_time) const { return timed_wait_until(boost::get_system_time()+rel_time); } - + bool timed_wait_until(boost::system_time const& abs_time) const { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - return future->timed_wait_until(abs_time); + return future_->timed_wait_until(abs_time); } - +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const + { + return wait_until(chrono::steady_clock::now() + rel_time); + + } + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->wait_until(abs_time); + } +#endif }; + BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END + template <typename R> class promise { typedef boost::shared_ptr<detail::future_object<R> > future_ptr; - - future_ptr future; + + future_ptr future_; bool future_obtained; - - promise(promise & rhs);// = delete; - promise & operator=(promise & rhs);// = delete; void lazy_init() { - if(!atomic_load(&future)) +#if defined BOOST_THREAD_PROMISE_LAZY + if(!atomic_load(&future_)) { future_ptr blank; - atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<R>)); + atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R>)); } +#endif } - + public: -// template <class Allocator> explicit promise(Allocator a); + BOOST_THREAD_MOVABLE_ONLY(promise) +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + promise(boost::allocator_arg_t, Allocator a) + { + typedef typename Allocator::template rebind<detail::future_object<R> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<R>(), D(a2, 1) ); + future_obtained = false; + } +#endif promise(): - future(),future_obtained(false) +#if defined BOOST_THREAD_PROMISE_LAZY + future_(), +#else + future_(new detail::future_object<R>()), +#endif + future_obtained(false) {} - + ~promise() { - if(future) + if(future_) { - boost::lock_guard<boost::mutex> lock(future->mutex); + boost::lock_guard<boost::mutex> lock(future_->mutex); - if(!future->done) + if(!future_->done) { - future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); } } } // Assignment -#ifndef BOOST_NO_RVALUE_REFERENCES - promise(promise && rhs): - future_obtained(rhs.future_obtained) + promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) { - future.swap(rhs.future); - rhs.future_obtained=false; + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; } - promise & operator=(promise&& rhs) + promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT { - future.swap(rhs.future); - future_obtained=rhs.future_obtained; - rhs.future.reset(); - rhs.future_obtained=false; - return *this; - } -#else - promise(boost::detail::thread_move_t<promise> rhs): - future(rhs->future),future_obtained(rhs->future_obtained) - { - rhs->future.reset(); - rhs->future_obtained=false; - } - promise & operator=(boost::detail::thread_move_t<promise> rhs) - { - future=rhs->future; - future_obtained=rhs->future_obtained; - rhs->future.reset(); - rhs->future_obtained=false; + future_=BOOST_THREAD_RV(rhs).future_; + future_obtained=BOOST_THREAD_RV(rhs).future_obtained; + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; return *this; } - operator boost::detail::thread_move_t<promise>() - { - return boost::detail::thread_move_t<promise>(*this); - } -#endif - void swap(promise& other) { - future.swap(other.future); + future_.swap(other.future_); std::swap(future_obtained,other.future_obtained); } // Result retrieval - unique_future<R> get_future() + BOOST_THREAD_FUTURE<R> get_future() { lazy_init(); - if(future_obtained) + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + if (future_obtained) { boost::throw_exception(future_already_retrieved()); } future_obtained=true; - return unique_future<R>(future); + return BOOST_THREAD_FUTURE<R>(future_); } void set_value(typename detail::future_traits<R>::source_reference_type r) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_finished_with_result_internal(r); + future_->mark_finished_with_result_internal(r); } // void set_value(R && r); void set_value(typename detail::future_traits<R>::rvalue_source_type r) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r)); + future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r)); } void set_exception(boost::exception_ptr p) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_exceptional_finish_internal(p); + future_->mark_exceptional_finish_internal(p); } + // setting the result with deferred notification + //void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED + //void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED + //void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED + template<typename F> void set_wait_callback(F f) { lazy_init(); - future->set_wait_callback(f,this); + future_->set_wait_callback(f,this); } - + }; template <> class promise<void> { typedef boost::shared_ptr<detail::future_object<void> > future_ptr; - - future_ptr future; + + future_ptr future_; bool future_obtained; - - promise(promise & rhs);// = delete; - promise & operator=(promise & rhs);// = delete; void lazy_init() { - if(!atomic_load(&future)) +#if defined BOOST_THREAD_PROMISE_LAZY + if(!atomic_load(&future_)) { future_ptr blank; - atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<void>)); + atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<void>)); } +#endif } public: -// template <class Allocator> explicit promise(Allocator a); + BOOST_THREAD_MOVABLE_ONLY(promise) + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + promise(boost::allocator_arg_t, Allocator a) + { + typedef typename Allocator::template rebind<detail::future_object<void> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<void>(), D(a2, 1) ); + future_obtained = false; + } +#endif promise(): - future(),future_obtained(false) +#if defined BOOST_THREAD_PROMISE_LAZY + future_(), +#else + future_(new detail::future_object<void>), +#endif + future_obtained(false) {} - + ~promise() { - if(future) + if(future_) { - boost::lock_guard<boost::mutex> lock(future->mutex); + boost::lock_guard<boost::mutex> lock(future_->mutex); - if(!future->done) + if(!future_->done) { - future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); } } } // Assignment -#ifndef BOOST_NO_RVALUE_REFERENCES - promise(promise && rhs): - future_obtained(rhs.future_obtained) - { - future.swap(rhs.future); - rhs.future_obtained=false; - } - promise & operator=(promise&& rhs) + promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) { - future.swap(rhs.future); - future_obtained=rhs.future_obtained; - rhs.future.reset(); - rhs.future_obtained=false; - return *this; - } -#else - promise(boost::detail::thread_move_t<promise> rhs): - future(rhs->future),future_obtained(rhs->future_obtained) - { - rhs->future.reset(); - rhs->future_obtained=false; + // we need to release the future as shared_ptr doesn't implements move semantics + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; } - promise & operator=(boost::detail::thread_move_t<promise> rhs) + + promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT { - future=rhs->future; - future_obtained=rhs->future_obtained; - rhs->future.reset(); - rhs->future_obtained=false; + future_=BOOST_THREAD_RV(rhs).future_; + future_obtained=BOOST_THREAD_RV(rhs).future_obtained; + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; return *this; } - operator boost::detail::thread_move_t<promise>() - { - return boost::detail::thread_move_t<promise>(*this); - } -#endif - void swap(promise& other) { - future.swap(other.future); + future_.swap(other.future_); std::swap(future_obtained,other.future_obtained); } // Result retrieval - unique_future<void> get_future() + BOOST_THREAD_FUTURE<void> get_future() { lazy_init(); - + + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } if(future_obtained) { boost::throw_exception(future_already_retrieved()); } future_obtained=true; - return unique_future<void>(future); + return BOOST_THREAD_FUTURE<void>(future_); } void set_value() { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_finished_with_result_internal(); + future_->mark_finished_with_result_internal(); } void set_exception(boost::exception_ptr p) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_exceptional_finish_internal(p); + future_->mark_exceptional_finish_internal(p); } template<typename F> void set_wait_callback(F f) { lazy_init(); - future->set_wait_callback(f,this); + future_->set_wait_callback(f,this); } - + }; +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + namespace container + { + template <class R, class Alloc> + struct uses_allocator<promise<R> , Alloc> : true_type + { + }; + } +#endif + + BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END + namespace detail { template<typename R> @@ -1177,6 +1389,10 @@ namespace boost started(false) {} + void reset() + { + started=false; + } void run() { { @@ -1199,30 +1415,44 @@ namespace boost this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise())); } } - - + + virtual void do_run()=0; }; - - + + + + template<typename R,typename F> struct task_object: task_base<R> { + private: + task_object(task_object&); + public: F f; task_object(F const& f_): f(f_) {} - task_object(boost::detail::thread_move_t<F> f_): - f(f_) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::forward<F>(f_)) + {} +#else + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) {} - +#endif void do_run() { try { this->mark_finished_with_result(f()); } + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } catch(...) { this->mark_exceptional_finish(); @@ -1230,18 +1460,55 @@ namespace boost } }; + template<typename R> + struct task_object<R,R (*)()>: + task_base<R> + { + private: + task_object(task_object&); + public: + R (*f)(); + task_object(R (*f_)()): + f(f_) + {} + void do_run() + { + try + { + this->mark_finished_with_result(f()); + } + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + template<typename F> struct task_object<void,F>: task_base<void> { + private: + task_object(task_object&); + public: F f; task_object(F const& f_): f(f_) {} - task_object(boost::detail::thread_move_t<F> f_): - f(f_) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::forward<F>(f_)) {} - +#else + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) + {} +#endif + void do_run() { try @@ -1249,6 +1516,39 @@ namespace boost f(); this->mark_finished_with_result(); } + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + + template<> + struct task_object<void,void (*)()>: + task_base<void> + { + private: + task_object(task_object&); + public: + void (*f)(); + task_object(void (*f_)()): + f(f_) + {} + void do_run() + { + try + { + f(); + this->mark_finished_with_result(); + } + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } catch(...) { this->mark_exceptional_finish(); @@ -1257,41 +1557,92 @@ namespace boost }; } - template<typename R> class packaged_task { + typedef boost::shared_ptr<detail::task_base<R> > task_ptr; boost::shared_ptr<detail::task_base<R> > task; bool future_obtained; - packaged_task(packaged_task&);// = delete; - packaged_task& operator=(packaged_task&);// = delete; - public: + typedef R result_type; + BOOST_THREAD_MOVABLE_ONLY(packaged_task) + packaged_task(): future_obtained(false) {} - + // construction and destruction - template <class F> - explicit packaged_task(F const& f): - task(new detail::task_object<R,F>(f)),future_obtained(false) - {} + explicit packaged_task(R(*f)()): task(new detail::task_object<R,R(*)()>(f)),future_obtained(false) {} - +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template <class F> + explicit packaged_task(BOOST_THREAD_RV_REF(F) f): + task(new detail::task_object<R, + typename remove_cv<typename remove_reference<F>::type>::type + >(boost::forward<F>(f))),future_obtained(false) + {} +#else template <class F> - explicit packaged_task(boost::detail::thread_move_t<F> f): + explicit packaged_task(F const& f): task(new detail::task_object<R,F>(f)),future_obtained(false) {} + template <class F> + explicit packaged_task(BOOST_THREAD_RV_REF(F) f): + task(new detail::task_object<R,F>(boost::move(f))),future_obtained(false) + {} +#endif -// template <class F, class Allocator> -// explicit packaged_task(F const& f, Allocator a); -// template <class F, class Allocator> -// explicit packaged_task(F&& f, Allocator a); +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + packaged_task(boost::allocator_arg_t, Allocator a, R(*f)()) + { + typedef R(*FR)(); + typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(f), D(a2, 1) ); + future_obtained = false; + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template <class F, class Allocator> + packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f) + { + typedef typename remove_cv<typename remove_reference<F>::type>::type FR; + typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + + task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(boost::forward<F>(f)), D(a2, 1) ); + future_obtained = false; + } +#else + template <class F, class Allocator> + packaged_task(boost::allocator_arg_t, Allocator a, const F& f) + { + typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + + task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(f), D(a2, 1) ); + future_obtained = false; + } + template <class F, class Allocator> + packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f) + { + typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + + task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(boost::move(f)), D(a2, 1) ); + future_obtained = false; + } +#endif //BOOST_NO_CXX11_RVALUE_REFERENCES +#endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS ~packaged_task() { @@ -1302,46 +1653,39 @@ namespace boost } // assignment -#ifndef BOOST_NO_RVALUE_REFERENCES - packaged_task(packaged_task&& other): - future_obtained(other.future_obtained) + packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT : + future_obtained(BOOST_THREAD_RV(other).future_obtained) { - task.swap(other.task); - other.future_obtained=false; + task.swap(BOOST_THREAD_RV(other).task); + BOOST_THREAD_RV(other).future_obtained=false; } - packaged_task& operator=(packaged_task&& other) + packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT { - packaged_task temp(static_cast<packaged_task&&>(other)); + packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other)); swap(temp); return *this; } -#else - packaged_task(boost::detail::thread_move_t<packaged_task> other): - future_obtained(other->future_obtained) - { - task.swap(other->task); - other->future_obtained=false; - } - packaged_task& operator=(boost::detail::thread_move_t<packaged_task> other) - { - packaged_task temp(other); - swap(temp); - return *this; - } - operator boost::detail::thread_move_t<packaged_task>() + + void reset() { - return boost::detail::thread_move_t<packaged_task>(*this); + if (!valid()) + throw future_error(system::make_error_code(future_errc::no_state)); + task->reset(); + future_obtained=false; } -#endif - void swap(packaged_task& other) + void swap(packaged_task& other) BOOST_NOEXCEPT { task.swap(other.task); std::swap(future_obtained,other.future_obtained); } + bool valid() const BOOST_NOEXCEPT + { + return task.get()!=0; + } // result retrieval - unique_future<R> get_future() + BOOST_THREAD_FUTURE<R> get_future() { if(!task) { @@ -1350,14 +1694,16 @@ namespace boost else if(!future_obtained) { future_obtained=true; - return unique_future<R>(task); + return BOOST_THREAD_FUTURE<R>(task); } else { boost::throw_exception(future_already_retrieved()); } + return BOOST_THREAD_FUTURE<R>(); + } - + // execution void operator()() @@ -1374,10 +1720,149 @@ namespace boost { task->set_wait_callback(f,this); } - + }; -} +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + namespace container + { + template <class R, class Alloc> + struct uses_allocator<packaged_task<R>, Alloc> + : public true_type {}; + } +#endif + + BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END + + + template <class R> + BOOST_THREAD_FUTURE<R> + async(launch policy, R(*f)()) + { + if (int(policy) & int(launch::async)) + { + packaged_task<R> pt( f ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } + else if (int(policy) & int(launch::deferred)) + { + packaged_task<R> pt( f ); + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + return ::boost::move(ret); + } else { + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } + } + + template <class R> + BOOST_THREAD_FUTURE<R> + async(R(*f)()) + { + return async(launch::any, f); + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template <class F> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> + async(launch policy, BOOST_THREAD_FWD_REF(F) f) + { + typedef typename boost::result_of<typename decay<F>::type()>::type R; + if (int(policy) & int(launch::async)) + { + packaged_task<R> pt( boost::forward<F>(f) ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } + else if (int(policy) & int(launch::deferred)) + { + packaged_task<R> pt( boost::forward<F>(f) ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + return ::boost::move(ret); + } else { + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } + } + template <class F> + BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> + async(BOOST_THREAD_RV_REF(F) f) + { + return async(launch::any, boost::forward<F>(f)); + } +#else + +// template <class F> +// BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> +// async(launch policy, F const& f) +// { +// typedef typename boost::result_of<typename decay<F>::type()>::type R; +// if (int(policy) & int(launch::async)) +// { +// packaged_task<R> pt( f ); +// +// BOOST_THREAD_FUTURE<R> ret = pt.get_future(); +// boost::thread( boost::move(pt) ).detach(); +// return ::boost::move(ret); +// } +// else if (int(policy) & int(launch::deferred)) +// { +// packaged_task<R> pt( f ); +// +// BOOST_THREAD_FUTURE<R> ret = pt.get_future(); +// return ::boost::move(ret); +// } else { +// BOOST_THREAD_FUTURE<R> ret; +// return ::boost::move(ret); +// } +// } +// template <class F> +// BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> +// async(F const& f) +// { +// return async(launch::any, f); +// } + + template <class F> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> + async(launch policy, BOOST_THREAD_FWD_REF(F) f) + { + typedef typename boost::result_of<typename decay<F>::type()>::type R; + if (int(policy) & int(launch::async)) + { + packaged_task<R> pt( boost::forward<F>(f) ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } + else if (int(policy) & int(launch::deferred)) + { + packaged_task<R> pt( boost::forward<F>(f) ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + return ::boost::move(ret); + } else { + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } + } + template <class F> + BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> + async(BOOST_THREAD_FWD_REF(F) f) + { + return async(launch::any, boost::forward<F>(f)); + } #endif + +} + +#endif // BOOST_NO_EXCEPTION +#endif // header |