Index: boost/thread/pthread/condition_variable.hpp =================================================================== --- boost/thread/pthread/condition_variable.hpp (revision 81136) +++ boost/thread/pthread/condition_variable.hpp (working copy) @@ -289,7 +289,7 @@ } template - inline void wait_until( + cv_status wait_until( lock_type& lk, chrono::time_point tp) { @@ -299,7 +299,8 @@ seconds s = duration_cast(d); ts.tv_sec = static_cast(s.count()); ts.tv_nsec = static_cast((d - s).count()); - do_timed_wait(lk, ts); + if (do_timed_wait(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; } #endif Index: boost/thread/pthread/condition_variable_fwd.hpp =================================================================== --- boost/thread/pthread/condition_variable_fwd.hpp (revision 81136) +++ boost/thread/pthread/condition_variable_fwd.hpp (working copy) @@ -212,7 +212,7 @@ void notify_all() BOOST_NOEXCEPT; #ifdef BOOST_THREAD_USES_CHRONO - inline void wait_until( + inline cv_status wait_until( unique_lock& lk, chrono::time_point tp) { @@ -222,7 +222,8 @@ seconds s = duration_cast(d); ts.tv_sec = static_cast(s.count()); ts.tv_nsec = static_cast((d - s).count()); - do_timed_wait(lk, ts); + if (do_timed_wait(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; } #endif //private: // used by boost::thread::try_join_until Index: boost/thread/future.hpp =================================================================== --- boost/thread/future.hpp (revision 81145) +++ boost/thread/future.hpp (working copy) @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #include #include #include + #include #ifdef BOOST_THREAD_USES_CHRONO #include @@ -206,7 +208,7 @@ namespace future_state { - enum state { uninitialized, waiting, ready, moved }; + enum state { uninitialized, waiting, ready, moved, deferred }; } namespace detail @@ -259,6 +261,7 @@ { boost::exception_ptr exception; bool done; + bool is_deferred; #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS bool thread_was_interrupted; #endif @@ -273,8 +276,9 @@ future_object_base(): done(false), + is_deferred(false) #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - thread_was_interrupted(false) + , thread_was_interrupted(false) #endif #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION , continuation_ptr() @@ -283,6 +287,8 @@ virtual ~future_object_base() {} + void set_deferred() {is_deferred = true;} + waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv) { boost::unique_lock lock(mutex); @@ -342,22 +348,33 @@ void wait_internal(boost::unique_lock &lock, bool rethrow=true) { - do_callback(lock); - while(!done) + do_callback(lock); + //if (!done) + { + if (is_deferred) { - waiters.wait(lock); + is_deferred=false; + execute(lock); + //lock.unlock(); } + else + { + while(!done) + { + waiters.wait(lock); + } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - if(rethrow && thread_was_interrupted) - { - throw boost::thread_interrupted(); - } + if(rethrow && thread_was_interrupted) + { + throw boost::thread_interrupted(); + } #endif - if(rethrow && exception) - { - boost::rethrow_exception(exception); + if(rethrow && exception) + { + boost::rethrow_exception(exception); + } } - + } } void wait(bool rethrow=true) { @@ -369,6 +386,9 @@ bool timed_wait_until(boost::system_time const& target_time) { boost::unique_lock lock(mutex); + if (is_deferred) + return false; + do_callback(lock); while(!done) { @@ -388,6 +408,8 @@ wait_until(const chrono::time_point& abs_time) { boost::unique_lock lock(mutex); + if (is_deferred) + return future_status::deferred; do_callback(lock); while(!done) { @@ -434,7 +456,7 @@ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS || thread_was_interrupted #endif -); + ); } template @@ -442,6 +464,7 @@ { callback=boost::bind(f,boost::ref(*u)); } + virtual void execute(boost::unique_lock&) {} private: future_object_base(future_object_base const&); @@ -649,6 +672,145 @@ future_object& operator=(future_object const&); }; + /// future_async_object + template + struct future_async_object: future_object + { + typedef future_object base_type; + Fp func_; + boost::thread thr_; + + public: + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + explicit future_async_object(Fp&& f) + : func_(boost::forward(f)) + #else + explicit future_async_object(Fp f) + : func_(f) + #endif + , thr_(&future_async_object::execute, *this) + { + } + + ~future_async_object() + { + thr_.join(); + } + + virtual void execute(boost::unique_lock& lock) { + try + { + this->mark_finished_with_result_internal(func_(), lock); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lock); + } + + } + + }; + + template + struct future_async_object: public future_object + { + typedef future_object base_type; + Fp func_; + boost::thread thr_; + + public: + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + explicit future_async_object(Fp&& f) + : func_(boost::forward(f)) + #else + explicit future_async_object(Fp f) + : func_(f) + #endif + , thr_(&future_async_object::execute, *this) + { + } + + ~future_async_object() + { + thr_.join(); + } + + virtual void execute(boost::unique_lock& lock) { + try + { + func_(); + this->mark_finished_with_result_internal(lock); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lock); + } + + } + + }; + /// future_deferred_object + template + struct future_deferred_object: future_object + { + typedef future_object base_type; + Fp func_; + + public: + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + explicit future_deferred_object(Fp&& f) + : func_(boost::forward(f)) + #else + explicit future_deferred_object(Fp f) + : func_(f) + #endif + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock& lck) { + try + { + this->mark_finished_with_result_internal(func_(), lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + + template + struct future_deferred_object: future_object + { + typedef future_object base_type; + Fp func_; + + public: + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + explicit future_deferred_object(Fp&& f) + : func_(boost::forward(f)) + #else + explicit future_deferred_object(Fp f) + : func_(f) + #endif + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock& lck) { + try + { + func_(); + this->mark_finished_with_result_internal(lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + // template // struct future_object_alloc: public future_object // { @@ -1019,6 +1181,25 @@ } // detail BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future BOOST_THREAD_DCL_MOVABLE_END + namespace detail + { + template + BOOST_THREAD_FUTURE + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + make_future_async_object(Fp&& f); + #else + make_future_async_object(Fp f); + #endif + + template + BOOST_THREAD_FUTURE + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + make_future_deferred_object(Fp&& f); + #else + make_future_deferred_object(Fp f); + #endif + } + template class BOOST_THREAD_FUTURE : public detail::basic_future { @@ -1039,6 +1220,22 @@ #endif friend class detail::future_waiter; + template + friend BOOST_THREAD_FUTURE + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + detail::make_future_async_object(Fp&& f); + #else + detail::make_future_async_object(Fp f); + #endif + + template + friend BOOST_THREAD_FUTURE + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + detail::make_future_deferred_object(Fp&& f); + #else + detail::make_future_deferred_object(Fp f); + #endif + typedef typename detail::future_traits::move_dest_type move_dest_type; BOOST_THREAD_FUTURE(future_ptr a_future): @@ -2094,6 +2291,47 @@ BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task BOOST_THREAD_DCL_MOVABLE_END + namespace detail + { + //////////////////////////////// + // make_future_deferred_object + //////////////////////////////// + template + BOOST_THREAD_FUTURE + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + make_future_deferred_object(Fp&& f) + #else + make_future_deferred_object(Fp f) + #endif + { + shared_ptr > + h(new future_deferred_object(boost::forward(f))); + return BOOST_THREAD_FUTURE(h); + } + + //////////////////////////////// + // make_future_async_object + //////////////////////////////// + template + BOOST_THREAD_FUTURE + #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + make_future_async_object(Fp&& f) + #else + make_future_async_object(Fp f) + #endif + { + shared_ptr > + h(new future_async_object(boost::forward(f))); + return BOOST_THREAD_FUTURE(h); + } + + } + + //////////////////////////////// + // template + // future async(F&&, ArgTypes&&...); + //////////////////////////////// + #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK @@ -2164,6 +2402,10 @@ typename decay::type... )>::type R; typedef packaged_task packaged_task_type; + + typedef detail::async_func::type, typename decay::type...> BF; + typedef typename BF::result_type Rp; + #else template BOOST_THREAD_FUTURE::type()>::type> @@ -2171,6 +2413,10 @@ { 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; + #endif #else template @@ -2179,6 +2425,9 @@ { 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; #endif if (int(policy) & int(launch::async)) @@ -2195,10 +2444,23 @@ } else if (int(policy) & int(launch::deferred)) { - packaged_task_type pt( boost::forward(f) ); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + return boost::detail::make_future_deferred_object( + BF( + thread_detail::decay_copy(boost::forward(f)) + , thread_detail::decay_copy(boost::forward(args))... + ) + ); +#else + BOOST_THREAD_FUTURE ret; + return ::boost::move(ret); +// return boost::detail::make_future_deferred_object( +// BF( +// thread_detail::decay_copy(boost::forward(f)) +// ) +// ); +#endif - BOOST_THREAD_FUTURE ret = pt.get_future(); - return ::boost::move(ret); } else { BOOST_THREAD_FUTURE ret; return ::boost::move(ret); @@ -2211,6 +2473,10 @@ return async(launch::any, boost::forward(f)); } + + //////////////////////////////// + // make_future + //////////////////////////////// template BOOST_THREAD_FUTURE::type> make_future(BOOST_THREAD_FWD_REF(T) value) { @@ -2228,6 +2494,9 @@ } + //////////////////////////////// + // make_shared_future + //////////////////////////////// template shared_future::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) { @@ -2245,6 +2514,9 @@ } + //////////////////////////////// + // detail::future_continuation + //////////////////////////////// #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION namespace detail { @@ -2318,8 +2590,10 @@ #endif } -// template -// auto then(F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + // template + // auto future::then(F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// template template Index: boost/thread/detail/move.hpp =================================================================== --- boost/thread/detail/move.hpp (revision 81136) +++ boost/thread/detail/move.hpp (working copy) @@ -230,19 +230,26 @@ -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES namespace boost { namespace thread_detail { +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template typename decay::type decay_copy(T&& t) { return boost::forward(t); } +#else + template + typename decay::type + decay_copy(BOOST_THREAD_FWD_REF(T) t) + { + return boost::forward(t); } +#endif + } } -#endif #include Index: libs/thread/test/sync/futures/async/async_pass.cpp =================================================================== --- libs/thread/test/sync/futures/async/async_pass.cpp (revision 81136) +++ libs/thread/test/sync/futures/async/async_pass.cpp (working copy) @@ -145,16 +145,17 @@ Clock::time_point t1 = Clock::now(); BOOST_TEST(t1 - t0 < ms(100)); } -// { -// boost::future f = boost::async(boost::launch::deferred, f0); -// boost::this_thread::sleep_for(ms(300)); -// Clock::time_point t0 = Clock::now(); -// BOOST_TEST(f.get() == 3); -// Clock::time_point t1 = Clock::now(); -// BOOST_TEST(t1 - t0 > ms(100)); -// } -// +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) { + boost::future f = boost::async(boost::launch::deferred, f0); + boost::this_thread::sleep_for(ms(300)); + Clock::time_point t0 = Clock::now(); + BOOST_TEST(f.get() == 3); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(t1 - t0 > ms(100)); + } +#endif + { boost::future f = boost::async(f1); boost::this_thread::sleep_for(ms(300)); Clock::time_point t0 = Clock::now(); @@ -178,16 +179,17 @@ Clock::time_point t1 = Clock::now(); BOOST_TEST(t1 - t0 < ms(100)); } -// { -// boost::future f = boost::async(boost::launch::deferred, f1); -// boost::this_thread::sleep_for(ms(300)); -// Clock::time_point t0 = Clock::now(); -// BOOST_TEST(&f.get() == &i); -// Clock::time_point t1 = Clock::now(); -// BOOST_TEST(t1 - t0 > ms(100)); -// } -// +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) { + boost::future f = boost::async(boost::launch::deferred, f1); + boost::this_thread::sleep_for(ms(300)); + Clock::time_point t0 = Clock::now(); + BOOST_TEST(&f.get() == &i); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(t1 - t0 > ms(100)); + } +#endif + { boost::future f = boost::async(f2); boost::this_thread::sleep_for(ms(300)); Clock::time_point t0 = Clock::now(); @@ -211,14 +213,18 @@ Clock::time_point t1 = Clock::now(); BOOST_TEST(t1 - t0 < ms(100)); } -// { -// boost::future f = boost::async(boost::launch::deferred, f2); -// boost::this_thread::sleep_for(ms(300)); -// Clock::time_point t0 = Clock::now(); -// f.get(); -// Clock::time_point t1 = Clock::now(); -// BOOST_TEST(t1 - t0 > ms(100)); -// } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + boost::future f = boost::async(boost::launch::deferred, f2); + boost::this_thread::sleep_for(ms(300)); + Clock::time_point t0 = Clock::now(); + f.get(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(t1 - t0 > ms(100)); + } +#endif + + // todo fixme #if 0 && defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) { boost::future > > f = boost::async(boost::launch::async, &f3, 3); @@ -230,6 +236,7 @@ } #endif + // todo fixme #if 0 && defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) { boost::future > > f = boost::async(&f4, boost::interprocess::unique_ptr >(new int(3)));