Index: boost/thread/future.hpp =================================================================== --- boost/thread/future.hpp (revision 82757) +++ boost/thread/future.hpp (working copy) @@ -505,15 +505,19 @@ struct future_traits { typedef boost::scoped_ptr storage_type; + struct dummy; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES typedef T const& source_reference_type; - struct dummy; - typedef typename boost::mpl::if_,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; - typedef typename boost::mpl::if_,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type; + //typedef typename boost::mpl::if_,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; + typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; + //typedef typename boost::mpl::if_,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type; + typedef T move_dest_type; #elif defined BOOST_THREAD_USES_MOVE - typedef T& source_reference_type; - typedef typename boost::mpl::if_,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; - typedef typename boost::mpl::if_,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; + typedef typename boost::mpl::if_c::value,T,T&>::type source_reference_type; + //typedef typename boost::mpl::if_c::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; + //typedef typename boost::mpl::if_c::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; + typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; + typedef T move_dest_type; #else typedef T& source_reference_type; typedef typename boost::mpl::if_,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; @@ -529,7 +533,11 @@ static void init(storage_type& storage,rvalue_source_type t) { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + storage.reset(new T(boost::forward(t))); +#else storage.reset(new T(static_cast(t))); +#endif } static void cleanup(storage_type& storage) @@ -607,7 +615,11 @@ void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock& lock) { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + future_traits::init(result,boost::forward(result_)); +#else future_traits::init(result,static_cast(result_)); +#endif mark_finished_internal(lock); } @@ -620,20 +632,27 @@ void mark_finished_with_result(rvalue_source_type result_) { boost::unique_lock lock(mutex); +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + mark_finished_with_result_internal(boost::forward(result_), lock); +#else mark_finished_with_result_internal(static_cast(result_), lock); +#endif + } move_dest_type get() { wait(); - return static_cast(*result); + //return static_cast(*result); + return boost::move(*result); } shared_future_get_result_type get_sh() { wait(); - return static_cast(*result); + //return static_cast(*result); + return *result; } // todo move this to detail::future_object_base @@ -651,23 +670,26 @@ } - void set_value_at_thread_exit(const T & result_) + void set_value_at_thread_exit(source_reference_type result_) { unique_lock lk(this->mutex); if (this->has_value(lk)) { throw_exception(promise_already_satisfied()); } - future_traits::init(result,result_); + //future_traits::init(result,result_); + result.reset(new T(result_)); + this->is_constructed = true; get_current_thread_data()->make_ready_at_thread_exit(shared_from_this()); } - void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_) + void set_value_at_thread_exit(rvalue_source_type result_) { unique_lock lk(this->mutex); if (this->has_value(lk)) throw_exception(promise_already_satisfied()); result.reset(new T(boost::move(result_))); + //result.reset(new T(boost::forward(result_))); //future_traits::init(result,static_cast(result_)); this->is_constructed = true; get_current_thread_data()->make_ready_at_thread_exit(shared_from_this()); @@ -683,11 +705,11 @@ struct future_object: detail::future_object_base { - typedef typename future_traits::storage_type storage_type; - typedef typename future_traits::source_reference_type source_reference_type; - typedef typename future_traits::rvalue_source_type rvalue_source_type; - typedef typename future_traits::move_dest_type move_dest_type; - typedef typename future_traits::shared_future_get_result_type shared_future_get_result_type; + typedef typename future_traits::storage_type storage_type; + typedef typename future_traits::source_reference_type source_reference_type; + typedef typename future_traits::rvalue_source_type rvalue_source_type; + typedef typename future_traits::move_dest_type move_dest_type; + typedef typename future_traits::shared_future_get_result_type shared_future_get_result_type; T* result; @@ -699,7 +721,7 @@ { } - void mark_finished_with_result_internal(T& result_, boost::unique_lock& lock) + void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock& lock) { //future_traits::init(result,result_); result= &result_; @@ -708,11 +730,11 @@ // void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock& lock) // { -// future_traits::init(result,static_cast(result_)); +// future_traits::init(result,static_cast(result_)); // mark_finished_internal(lock); // } - void mark_finished_with_result(T& result_) + void mark_finished_with_result(source_reference_type result_) { boost::unique_lock lock(mutex); mark_finished_with_result_internal(result_, lock); @@ -866,7 +888,9 @@ boost::unique_lock lock(this->mutex); this->wait_internal(lock); - return static_cast(*(this->result)); + //return static_cast(*(this->result)); + return boost::move(*(this->result)); + } static void run(future_async_object* that, BOOST_THREAD_FWD_REF(Fp) f) @@ -1417,7 +1441,7 @@ BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT { - base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); + this->base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); return *this; } @@ -1676,7 +1700,11 @@ { boost::throw_exception(promise_already_satisfied()); } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + future_->mark_finished_with_result_internal(boost::forward(r), lock); +#else future_->mark_finished_with_result_internal(static_cast::rvalue_source_type>(r), lock); +#endif } void set_exception(boost::exception_ptr p) @@ -2077,6 +2105,7 @@ #endif } + #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) @@ -2186,7 +2215,13 @@ { try { - this->mark_finished_with_result(f()); +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + R res((f())); + this->mark_finished_with_result(boost::move(res)); +#else + this->mark_finished_with_result(f()); +#endif + } #endif #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS @@ -2202,6 +2237,96 @@ } }; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + struct task_object: + task_base +#else + template + struct task_object: + task_base +#endif +#else + template + struct task_object: + task_base +#endif + { + private: + task_object(task_object&); + public: + F f; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::forward(f_)) + {} +#else + task_object(F const& f_): + f(f_) + {} + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) // TODO forward + {} +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::forward(args)...)); + } +#else + void do_apply() + { + try + { + this->set_value_at_thread_exit(f()); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->set_interrupted_at_thread_exit(); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::forward(args)...)); + } +#else + void do_run() + { + try + { + R& res((f())); + this->mark_finished_with_result(res); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } +#endif + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + + #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK @@ -2241,7 +2366,9 @@ { try { - this->set_value_at_thread_exit(f()); + //this->set_value_at_thread_exit(f()); + R r((f())); + this->set_value_at_thread_exit(boost::move(r)); } #endif #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS @@ -2269,6 +2396,88 @@ { try { + //this->set_value_at_thread_exit(f()); + R res((f())); + this->mark_finished_with_result(boost::move(res)); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } +#endif + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + struct task_object: + task_base +#else + template + struct task_object: + task_base +#endif +#else + template + struct task_object : + task_base +#endif + { + private: + task_object(task_object&); + public: + R& (*f)(); + task_object(R& (*f_)()): + f(f_) + {} + + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::forward(args)...)); + } +#else + void do_apply() + { + try + { + this->set_value_at_thread_exit(f()); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->set_interrupted_at_thread_exit(); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::forward(args)...)); + } +#else + void do_run() + { + try + { this->mark_finished_with_result(f()); } #endif @@ -2691,7 +2900,11 @@ { // todo use forward +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + packaged_task temp(boost::move(other)); +#else packaged_task temp(static_cast(other)); +#endif swap(temp); return *this; } @@ -2725,6 +2938,7 @@ else if(!future_obtained) { future_obtained=true; + //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE(task)); return BOOST_THREAD_FUTURE(task); } else @@ -2858,7 +3072,7 @@ { packaged_task_type pt( f ); - BOOST_THREAD_FUTURE ret = pt.get_future(); + BOOST_THREAD_FUTURE ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future()); #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) boost::thread( boost::move(pt), boost::forward(args)... ).detach(); #else @@ -2912,8 +3126,8 @@ typedef typename boost::result_of::type()>::type R; typedef packaged_task packaged_task_type; - typedef detail::async_func::type> BF; - typedef typename BF::result_type Rp; + //typedef detail::async_func::type> BF; + //typedef typename BF::result_type Rp; #endif #else @@ -2924,8 +3138,8 @@ typedef typename boost::result_of::type()>::type R; typedef packaged_task packaged_task_type; - typedef detail::async_func::type> BF; - typedef typename BF::result_type Rp; + //typedef detail::async_func::type> BF; + //typedef typename BF::result_type Rp; #endif if (int(policy) & int(launch::async))