1 // (C) Copyright 2008-10 Anthony Williams
2 // (C) Copyright 2011-2015 Vicente J. Botet Escriba
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef BOOST_THREAD_FUTURE_HPP
9 #define BOOST_THREAD_FUTURE_HPP
11 #include <boost/thread/detail/config.hpp>
13 // boost::thread::future requires exception handling
14 // due to boost::exception::exception_ptr dependency
16 //#define BOOST_THREAD_CONTINUATION_SYNC
18 #ifdef BOOST_NO_EXCEPTIONS
22 struct shared_state_base {
23 void notify_deferred() {}
29 #include <boost/thread/condition_variable.hpp>
30 #include <boost/thread/detail/move.hpp>
31 #include <boost/thread/detail/invoker.hpp>
32 #include <boost/thread/detail/invoke.hpp>
33 #include <boost/thread/detail/is_convertible.hpp>
34 #include <boost/thread/exceptional_ptr.hpp>
35 #include <boost/thread/futures/future_error.hpp>
36 #include <boost/thread/futures/future_error_code.hpp>
37 #include <boost/thread/futures/future_status.hpp>
38 #include <boost/thread/futures/is_future_type.hpp>
39 #include <boost/thread/futures/launch.hpp>
40 #include <boost/thread/futures/wait_for_all.hpp>
41 #include <boost/thread/futures/wait_for_any.hpp>
42 #include <boost/thread/lock_algorithms.hpp>
43 #include <boost/thread/lock_types.hpp>
44 #include <boost/thread/mutex.hpp>
45 #include <boost/thread/thread_only.hpp>
46 #include <boost/thread/thread_time.hpp>
47 #include <boost/thread/executor.hpp>
48 #include <boost/thread/executors/generic_executor_ref.hpp>
50 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
51 #include <boost/optional.hpp>
53 #include <boost/thread/csbl/memory/unique_ptr.hpp>
56 #include <boost/assert.hpp>
57 #include <boost/bind.hpp>
58 #ifdef BOOST_THREAD_USES_CHRONO
59 #include <boost/chrono/system_clocks.hpp>
61 #include <boost/core/enable_if.hpp>
62 #include <boost/core/ref.hpp>
63 #include <boost/enable_shared_from_this.hpp>
64 #include <boost/exception_ptr.hpp>
65 #include <boost/function.hpp>
66 #include <boost/next_prior.hpp>
67 #include <boost/scoped_array.hpp>
68 #include <boost/shared_ptr.hpp>
69 #include <boost/smart_ptr/make_shared.hpp>
70 #include <boost/throw_exception.hpp>
71 #include <boost/type_traits/conditional.hpp>
72 #include <boost/type_traits/decay.hpp>
73 #include <boost/type_traits/is_copy_constructible.hpp>
74 #include <boost/type_traits/is_fundamental.hpp>
75 #include <boost/type_traits/is_void.hpp>
76 #include <boost/utility/result_of.hpp>
79 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
80 #include <boost/thread/detail/memory.hpp>
81 #include <boost/container/scoped_allocator.hpp>
82 #if ! defined BOOST_NO_CXX11_ALLOCATOR
87 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
88 #include <boost/thread/csbl/tuple.hpp>
89 #include <boost/thread/csbl/vector.hpp>
97 #if defined BOOST_THREAD_PROVIDES_FUTURE
98 #define BOOST_THREAD_FUTURE future
100 #define BOOST_THREAD_FUTURE unique_future
106 shared_ptr<T> static_shared_from_this(T* that)
108 return static_pointer_cast<T>(that->shared_from_this());
111 shared_ptr<T const> static_shared_from_this(T const* that)
113 return static_pointer_cast<T const>(that->shared_from_this());
116 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
118 namespace executors {
121 using executors::executor;
123 typedef shared_ptr<executor> executor_ptr_type;
130 boost::unique_lock<boost::mutex>& lock_;
132 relocker(boost::unique_lock<boost::mutex>& lk):
139 if (! lock_.owns_lock()) {
144 if (! lock_.owns_lock()) {
149 relocker& operator=(relocker const&);
152 struct shared_state_base : enable_shared_from_this<shared_state_base>
154 typedef std::list<boost::condition_variable_any*> waiter_list;
155 typedef waiter_list::iterator notify_when_ready_handle;
156 // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
157 typedef shared_ptr<shared_state_base> continuation_ptr_type;
158 typedef std::vector<continuation_ptr_type> continuations_type;
160 boost::exception_ptr exception;
166 mutable boost::mutex mutex;
167 boost::condition_variable waiters;
168 waiter_list external_waiters;
169 boost::function<void()> callback;
170 // This declaration should be only included conditionally, but is included to maintain the same layout.
171 continuations_type continuations;
172 executor_ptr_type ex_;
174 // This declaration should be only included conditionally, but is included to maintain the same layout.
175 virtual void launch_continuation()
183 is_constructed(false),
184 policy_(launch::none),
189 shared_state_base(exceptional_ptr const& ex):
194 is_constructed(false),
195 policy_(launch::none),
201 virtual ~shared_state_base()
210 executor_ptr_type get_executor()
215 void set_executor_policy(executor_ptr_type aex)
220 void set_executor_policy(executor_ptr_type aex, boost::lock_guard<boost::mutex>&)
225 void set_executor_policy(executor_ptr_type aex, boost::unique_lock<boost::mutex>&)
231 bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; }
233 boost::unique_lock<boost::mutex> lk(this->mutex);
236 void invalidate(boost::unique_lock<boost::mutex>&) { is_valid_ = false; }
238 boost::unique_lock<boost::mutex> lk(this->mutex);
241 void validate(boost::unique_lock<boost::mutex>&) { is_valid_ = true; }
243 boost::unique_lock<boost::mutex> lk(this->mutex);
250 policy_ = launch::deferred;
254 is_deferred_ = false;
255 policy_ = launch::async;
257 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
260 is_deferred_ = false;
261 policy_ = launch::executor;
268 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
270 boost::unique_lock<boost::mutex> lock(this->mutex);
272 return external_waiters.insert(external_waiters.end(),&cv);
275 void unnotify_when_ready(notify_when_ready_handle it)
277 boost::lock_guard<boost::mutex> lock(this->mutex);
278 external_waiters.erase(it);
282 // this inline definition results in ODR. See https://github.com/boostorg/thread/issues/193
283 // to avoid it, we define the function on the derived templates using the macro BOOST_THREAD_DO_CONTINUATION
284 #define BOOST_THREAD_DO_CONTINUATION
285 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
286 void do_continuation(boost::unique_lock<boost::mutex>& lock)
288 if (! continuations.empty()) {
289 continuations_type the_continuations = continuations;
290 continuations.clear();
292 for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) {
293 (*it)->launch_continuation();
298 void do_continuation(boost::unique_lock<boost::mutex>&)
304 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
305 #define BOOST_THREAD_DO_CONTINUATION \
306 void do_continuation(boost::unique_lock<boost::mutex>& lock) \
308 if (! this->continuations.empty()) { \
309 continuations_type the_continuations = this->continuations; \
310 this->continuations.clear(); \
311 relocker rlk(lock); \
312 for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { \
313 (*it)->launch_continuation(); \
318 #define BOOST_THREAD_DO_CONTINUATION \
319 void do_continuation(boost::unique_lock<boost::mutex>&) \
324 virtual void do_continuation(boost::unique_lock<boost::mutex>&) = 0;
327 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
328 virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
330 continuations.push_back(continuation);
332 do_continuation(lock);
336 void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
339 waiters.notify_all();
340 for(waiter_list::const_iterator it=external_waiters.begin(),
341 end=external_waiters.end();it!=end;++it)
345 do_continuation(lock);
347 void notify_deferred()
349 boost::unique_lock<boost::mutex> lock(this->mutex);
350 mark_finished_internal(lock);
353 void do_callback(boost::unique_lock<boost::mutex>& lock)
355 if(callback && !done)
357 boost::function<void()> local_callback=callback;
358 relocker relock(lock);
363 virtual bool run_if_is_deferred()
365 boost::unique_lock<boost::mutex> lk(this->mutex);
375 virtual bool run_if_is_deferred_or_ready()
377 boost::unique_lock<boost::mutex> lk(this->mutex);
388 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true)
396 waiters.wait(lk, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
397 if(rethrow && exception)
399 boost::rethrow_exception(exception);
403 virtual void wait(boost::unique_lock<boost::mutex>& lock, bool rethrow=true)
405 wait_internal(lock, rethrow);
408 void wait(bool rethrow=true)
410 boost::unique_lock<boost::mutex> lock(this->mutex);
414 #if defined BOOST_THREAD_USES_DATETIME
415 template<typename Duration>
416 bool timed_wait(Duration const& rel_time)
418 boost::unique_lock<boost::mutex> lock(this->mutex);
423 return waiters.timed_wait(lock, rel_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
426 bool timed_wait_until(boost::system_time const& target_time)
428 boost::unique_lock<boost::mutex> lock(this->mutex);
433 return waiters.timed_wait(lock, target_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
436 #ifdef BOOST_THREAD_USES_CHRONO
438 template <class Clock, class Duration>
440 wait_until(const chrono::time_point<Clock, Duration>& abs_time)
442 boost::unique_lock<boost::mutex> lock(this->mutex);
444 return future_status::deferred;
446 if(!waiters.wait_until(lock, abs_time, boost::bind(&shared_state_base::is_done, boost::ref(*this))))
448 return future_status::timeout;
450 return future_status::ready;
453 void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
456 mark_finished_internal(lock);
459 void mark_exceptional_finish()
461 boost::unique_lock<boost::mutex> lock(this->mutex);
462 mark_exceptional_finish_internal(boost::current_exception(), lock);
465 void set_exception_deferred(exception_ptr e)
467 unique_lock<boost::mutex> lk(this->mutex);
470 throw_exception(promise_already_satisfied());
473 this->is_constructed = true;
475 void set_exception_at_thread_exit(exception_ptr e)
477 set_exception_deferred(e);
478 // unique_lock<boost::mutex> lk(this->mutex);
479 // if (has_value(lk))
481 // throw_exception(promise_already_satisfied());
484 // this->is_constructed = true;
485 detail::make_ready_at_thread_exit(shared_from_this());
488 bool has_value() const
490 boost::lock_guard<boost::mutex> lock(this->mutex);
491 return done && ! exception;
494 bool has_value(unique_lock<boost::mutex>& ) const
496 return done && ! exception;
499 bool has_exception() const
501 boost::lock_guard<boost::mutex> lock(this->mutex);
502 return done && exception;
505 launch launch_policy(boost::unique_lock<boost::mutex>&) const
510 future_state::state get_state(boost::unique_lock<boost::mutex>&) const
514 return future_state::waiting;
518 return future_state::ready;
521 future_state::state get_state() const
523 boost::lock_guard<boost::mutex> guard(this->mutex);
526 return future_state::waiting;
530 return future_state::ready;
534 exception_ptr get_exception_ptr()
536 boost::unique_lock<boost::mutex> lock(this->mutex);
537 wait_internal(lock, false);
541 template<typename F,typename U>
542 void set_wait_callback(F f,U* u)
544 boost::lock_guard<boost::mutex> lock(this->mutex);
545 callback=boost::bind(f,boost::ref(*u));
548 virtual void execute(boost::unique_lock<boost::mutex>&) {}
551 shared_state_base(shared_state_base const&);
552 shared_state_base& operator=(shared_state_base const&);
555 // Used to create stand-alone futures
558 detail::shared_state_base
560 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
561 typedef boost::optional<T> storage_type;
563 typedef boost::csbl::unique_ptr<T> storage_type;
565 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
566 typedef T const& source_reference_type;
567 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
568 typedef T move_dest_type;
569 #elif defined BOOST_THREAD_USES_MOVE
570 typedef typename conditional<boost::is_fundamental<T>::value,T,T const&>::type source_reference_type;
571 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
572 typedef T move_dest_type;
574 typedef T& source_reference_type;
575 typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
576 typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
579 typedef const T& shared_future_get_result_type;
586 shared_state(exceptional_ptr const& ex):
587 detail::shared_state_base(ex), result()
590 // locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
591 BOOST_THREAD_DO_CONTINUATION
593 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
595 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
598 result.reset(new T(result_));
600 this->mark_finished_internal(lock);
603 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
605 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
606 result = boost::move(result_);
607 #elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
608 result.reset(new T(boost::move(result_)));
610 result.reset(new T(static_cast<rvalue_source_type>(result_)));
612 this->mark_finished_internal(lock);
616 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
617 template <class ...Args>
618 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock, BOOST_THREAD_FWD_REF(Args)... args)
620 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
621 result.emplace(boost::forward<Args>(args)...);
623 result.reset(new T(boost::forward<Args>(args)...));
625 this->mark_finished_internal(lock);
629 void mark_finished_with_result(source_reference_type result_)
631 boost::unique_lock<boost::mutex> lock(this->mutex);
632 this->mark_finished_with_result_internal(result_, lock);
635 void mark_finished_with_result(rvalue_source_type result_)
637 boost::unique_lock<boost::mutex> lock(this->mutex);
639 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
640 mark_finished_with_result_internal(boost::move(result_), lock);
642 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
646 storage_type& get_storage(boost::unique_lock<boost::mutex>& lk)
651 virtual move_dest_type get(boost::unique_lock<boost::mutex>& lk)
653 return boost::move(*get_storage(lk));
657 boost::unique_lock<boost::mutex> lk(this->mutex);
658 return this->get(lk);
661 virtual shared_future_get_result_type get_sh(boost::unique_lock<boost::mutex>& lk)
663 return *get_storage(lk);
665 shared_future_get_result_type get_sh()
667 boost::unique_lock<boost::mutex> lk(this->mutex);
668 return this->get_sh(lk);
670 void set_value_deferred(source_reference_type result_)
672 unique_lock<boost::mutex> lk(this->mutex);
673 if (this->has_value(lk))
675 throw_exception(promise_already_satisfied());
677 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
680 result.reset(new T(result_));
683 this->is_constructed = true;
685 void set_value_deferred(rvalue_source_type result_)
687 unique_lock<boost::mutex> lk(this->mutex);
688 if (this->has_value(lk))
690 throw_exception(promise_already_satisfied());
693 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
694 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
695 result = boost::move(result_);
697 result.reset(new T(boost::move(result_)));
700 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
701 result = boost::move(result_);
703 result.reset(new T(static_cast<rvalue_source_type>(result_)));
706 this->is_constructed = true;
709 void set_value_at_thread_exit(source_reference_type result_)
711 set_value_deferred(result_);
712 // unique_lock<boost::mutex> lk(this->mutex);
713 // if (this->has_value(lk))
715 // throw_exception(promise_already_satisfied());
717 //#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
720 // result.reset(new T(result_));
723 // this->is_constructed = true;
724 detail::make_ready_at_thread_exit(shared_from_this());
726 void set_value_at_thread_exit(rvalue_source_type result_)
728 set_value_deferred(boost::move(result_));
729 // unique_lock<boost::mutex> lk(this->mutex);
730 // if (this->has_value(lk))
731 // throw_exception(promise_already_satisfied());
733 //#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
734 //#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
735 // result = boost::move(result_);
737 // result.reset(new T(boost::move(result_)));
740 //#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
741 // result = boost::move(result_);
743 // result.reset(new T(static_cast<rvalue_source_type>(result_)));
746 // this->is_constructed = true;
747 detail::make_ready_at_thread_exit(shared_from_this());
751 shared_state(shared_state const&);
752 shared_state& operator=(shared_state const&);
756 struct shared_state<T&>:
757 detail::shared_state_base
759 typedef T* storage_type;
760 typedef T& source_reference_type;
761 typedef T& move_dest_type;
762 typedef T& shared_future_get_result_type;
770 shared_state(exceptional_ptr const& ex):
771 detail::shared_state_base(ex), result(0)
774 // locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
775 BOOST_THREAD_DO_CONTINUATION
777 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
780 mark_finished_internal(lock);
783 void mark_finished_with_result(source_reference_type result_)
785 boost::unique_lock<boost::mutex> lock(this->mutex);
786 mark_finished_with_result_internal(result_, lock);
789 virtual T& get(boost::unique_lock<boost::mutex>& lock)
796 boost::unique_lock<boost::mutex> lk(this->mutex);
800 virtual T& get_sh(boost::unique_lock<boost::mutex>& lock)
807 boost::unique_lock<boost::mutex> lock(this->mutex);
811 void set_value_deferred(T& result_)
813 unique_lock<boost::mutex> lk(this->mutex);
814 if (this->has_value(lk))
816 throw_exception(promise_already_satisfied());
819 this->is_constructed = true;
822 void set_value_at_thread_exit(T& result_)
824 set_value_deferred(result_);
825 // unique_lock<boost::mutex> lk(this->mutex);
826 // if (this->has_value(lk))
827 // throw_exception(promise_already_satisfied());
829 // this->is_constructed = true;
830 detail::make_ready_at_thread_exit(shared_from_this());
834 shared_state(shared_state const&);
835 shared_state& operator=(shared_state const&);
839 struct shared_state<void>:
840 detail::shared_state_base
842 typedef void shared_future_get_result_type;
843 typedef void move_dest_type;
848 shared_state(exceptional_ptr const& ex):
849 detail::shared_state_base(ex)
852 // locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
853 BOOST_THREAD_DO_CONTINUATION
855 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
857 mark_finished_internal(lock);
860 void mark_finished_with_result()
862 boost::unique_lock<boost::mutex> lock(this->mutex);
863 mark_finished_with_result_internal(lock);
866 virtual void get(boost::unique_lock<boost::mutex>& lock)
868 this->wait_internal(lock);
872 boost::unique_lock<boost::mutex> lock(this->mutex);
876 virtual void get_sh(boost::unique_lock<boost::mutex>& lock)
878 this->wait_internal(lock);
882 boost::unique_lock<boost::mutex> lock(this->mutex);
886 void set_value_deferred()
888 unique_lock<boost::mutex> lk(this->mutex);
889 if (this->has_value(lk))
891 throw_exception(promise_already_satisfied());
893 this->is_constructed = true;
895 void set_value_at_thread_exit()
897 set_value_deferred();
898 // unique_lock<boost::mutex> lk(this->mutex);
899 // if (this->has_value(lk))
901 // throw_exception(promise_already_satisfied());
903 // this->is_constructed = true;
904 detail::make_ready_at_thread_exit(shared_from_this());
907 shared_state(shared_state const&);
908 shared_state& operator=(shared_state const&);
911 /////////////////////////
912 /// future_async_shared_state_base
913 /////////////////////////
914 template<typename Rp>
915 struct future_async_shared_state_base: shared_state<Rp>
917 typedef shared_state<Rp> base_type;
919 #ifdef BOOST_THREAD_FUTURE_BLOCKING
923 if (this_thread::get_id() == thr_.get_id())
928 if (thr_.joinable()) thr_.join();
932 future_async_shared_state_base()
937 ~future_async_shared_state_base()
939 #ifdef BOOST_THREAD_FUTURE_BLOCKING
941 #elif defined BOOST_THREAD_ASYNC_FUTURE_WAITS
942 unique_lock<boost::mutex> lk(this->mutex);
943 this->waiters.wait(lk, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
947 virtual void wait(boost::unique_lock<boost::mutex>& lk, bool rethrow)
949 #ifdef BOOST_THREAD_FUTURE_BLOCKING
955 this->base_type::wait(lk, rethrow);
959 /////////////////////////
960 /// future_async_shared_state
961 /////////////////////////
962 template<typename Rp, typename Fp>
963 struct future_async_shared_state: future_async_shared_state_base<Rp>
965 future_async_shared_state()
969 void init(BOOST_THREAD_FWD_REF(Fp) f)
971 #ifdef BOOST_THREAD_FUTURE_BLOCKING
972 this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f));
974 boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f)).detach();
978 static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f)
982 that->mark_finished_with_result(f());
986 that->mark_exceptional_finish();
991 template<typename Fp>
992 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void>
994 void init(BOOST_THREAD_FWD_REF(Fp) f)
996 #ifdef BOOST_THREAD_FUTURE_BLOCKING
997 this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
999 boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
1003 static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f)
1008 that->mark_finished_with_result();
1012 that->mark_exceptional_finish();
1017 template<typename Rp, typename Fp>
1018 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&>
1020 void init(BOOST_THREAD_FWD_REF(Fp) f)
1022 #ifdef BOOST_THREAD_FUTURE_BLOCKING
1023 this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
1025 boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
1029 static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f)
1033 that->mark_finished_with_result(f());
1037 that->mark_exceptional_finish();
1042 //////////////////////////
1043 /// future_deferred_shared_state
1044 //////////////////////////
1045 template<typename Rp, typename Fp>
1046 struct future_deferred_shared_state: shared_state<Rp>
1050 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
1051 : func_(boost::move(f))
1053 this->set_deferred();
1056 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1059 Fp local_fuct=boost::move(func_);
1060 relocker relock(lck);
1061 Rp res = local_fuct();
1063 this->mark_finished_with_result_internal(boost::move(res), lck);
1067 this->mark_exceptional_finish_internal(current_exception(), lck);
1071 template<typename Rp, typename Fp>
1072 struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
1076 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
1077 : func_(boost::move(f))
1079 this->set_deferred();
1082 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1085 this->mark_finished_with_result_internal(func_(), lck);
1089 this->mark_exceptional_finish_internal(current_exception(), lck);
1094 template<typename Fp>
1095 struct future_deferred_shared_state<void,Fp>: shared_state<void>
1099 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
1100 : func_(boost::move(f))
1102 this->set_deferred();
1105 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1108 Fp local_fuct=boost::move(func_);
1109 relocker relock(lck);
1112 this->mark_finished_with_result_internal(lck);
1116 this->mark_exceptional_finish_internal(current_exception(), lck);
1124 typedef std::vector<int>::size_type count_type;
1126 struct registered_waiter
1128 boost::shared_ptr<detail::shared_state_base> future_;
1129 detail::shared_state_base::notify_when_ready_handle handle;
1132 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future,
1133 detail::shared_state_base::notify_when_ready_handle handle_,
1135 future_(a_future),handle(handle_),index(index_)
1139 struct all_futures_lock
1142 typedef std::ptrdiff_t count_type_portable;
1144 typedef count_type count_type_portable;
1146 count_type_portable count;
1147 boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
1149 all_futures_lock(std::vector<registered_waiter>& futures):
1150 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
1152 for(count_type_portable i=0;i<count;++i)
1154 locks[i]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(futures[i].future_->mutex));
1160 boost::lock(locks.get(),locks.get()+count);
1165 for(count_type_portable i=0;i<count;++i)
1172 boost::condition_variable_any cv;
1173 std::vector<registered_waiter> futures_;
1174 count_type future_count;
1181 template<typename F>
1186 registered_waiter waiter(f.future_,f.future_->notify_when_ready(cv),future_count);
1188 futures_.push_back(waiter);
1190 f.future_->unnotify_when_ready(waiter.handle);
1197 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
1198 template<typename F1, typename... Fs>
1199 void add(F1& f1, Fs&... fs)
1201 add(f1); add(fs...);
1207 all_futures_lock lk(futures_);
1210 for(count_type i=0;i<futures_.size();++i)
1212 if(futures_[i].future_->done)
1214 return futures_[i].index;
1223 for(count_type i=0;i<futures_.size();++i)
1225 futures_[i].future_->unnotify_when_ready(futures_[i].handle);
1232 template <typename R>
1233 class BOOST_THREAD_FUTURE;
1235 template <typename R>
1236 class shared_future;
1238 template<typename T>
1239 struct is_future_type<BOOST_THREAD_FUTURE<T> > : true_type
1243 template<typename T>
1244 struct is_future_type<shared_future<T> > : true_type
1248 // template<typename Iterator>
1249 // typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
1254 // detail::future_waiter waiter;
1255 // for(Iterator current=begin;current!=end;++current)
1257 // waiter.add(*current);
1259 // return boost::next(begin,waiter.wait());
1262 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
1263 template<typename F1,typename F2>
1264 typename boost::enable_if<is_future_type<F1>,typename detail::future_waiter::count_type>::type wait_for_any(F1& f1,F2& f2)
1266 detail::future_waiter waiter;
1269 return waiter.wait();
1272 template<typename F1,typename F2,typename F3>
1273 typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3)
1275 detail::future_waiter waiter;
1279 return waiter.wait();
1282 template<typename F1,typename F2,typename F3,typename F4>
1283 typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
1285 detail::future_waiter waiter;
1290 return waiter.wait();
1293 template<typename F1,typename F2,typename F3,typename F4,typename F5>
1294 typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
1296 detail::future_waiter waiter;
1302 return waiter.wait();
1305 template<typename F1, typename... Fs>
1306 typename boost::enable_if<is_future_type<F1>, typename detail::future_waiter::count_type>::type
1307 wait_for_any(F1& f1, Fs&... fs)
1309 detail::future_waiter waiter;
1310 waiter.add(f1, fs...);
1311 return waiter.wait();
1313 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1315 template <typename R>
1318 template <typename R>
1319 class packaged_task;
1323 /// Common implementation for all the futures independently of the return type
1328 /// Common implementation for future and shared_future.
1329 template <typename R>
1330 class basic_future : public base_future
1335 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
1336 typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
1338 static //BOOST_CONSTEXPR
1339 future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) {
1340 return future_ptr(new detail::shared_state<R>(ex));
1345 basic_future(future_ptr a_future):
1351 typedef future_state::state state;
1353 BOOST_THREAD_MOVABLE_ONLY(basic_future)
1354 basic_future(): future_() {}
1358 basic_future(exceptional_ptr const& ex)
1359 : future_(make_exceptional_future_ptr(ex))
1366 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
1367 future_(BOOST_THREAD_RV(other).future_)
1369 BOOST_THREAD_RV(other).future_.reset();
1371 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
1373 future_=BOOST_THREAD_RV(other).future_;
1374 BOOST_THREAD_RV(other).future_.reset();
1377 void swap(basic_future& that) BOOST_NOEXCEPT
1379 future_.swap(that.future_);
1381 // functions to check state, and wait for ready
1382 state get_state(boost::unique_lock<boost::mutex>& lk) const
1386 return future_state::uninitialized;
1388 return future_->get_state(lk);
1390 state get_state() const
1394 return future_state::uninitialized;
1396 return future_->get_state();
1399 bool is_ready() const
1401 return get_state()==future_state::ready;
1404 bool is_ready(boost::unique_lock<boost::mutex>& lk) const
1406 return get_state(lk)==future_state::ready;
1408 bool has_exception() const
1410 return future_ && future_->has_exception();
1413 bool has_value() const
1415 return future_ && future_->has_value();
1418 launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
1420 if ( future_ ) return future_->launch_policy(lk);
1421 else return launch(launch::none);
1424 launch launch_policy() const
1427 boost::unique_lock<boost::mutex> lk(this->future_->mutex);
1428 return future_->launch_policy(lk);
1430 else return launch(launch::none);
1433 exception_ptr get_exception_ptr()
1436 ? future_->get_exception_ptr()
1440 bool valid() const BOOST_NOEXCEPT
1442 return future_.get() != 0 && future_->valid();
1449 boost::throw_exception(future_uninitialized());
1451 future_->wait(false);
1454 typedef detail::shared_state_base::notify_when_ready_handle notify_when_ready_handle;
1456 boost::mutex& mutex() {
1459 boost::throw_exception(future_uninitialized());
1461 return future_->mutex;
1464 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
1468 boost::throw_exception(future_uninitialized());
1470 return future_->notify_when_ready(cv);
1473 void unnotify_when_ready(notify_when_ready_handle h)
1477 boost::throw_exception(future_uninitialized());
1479 return future_->unnotify_when_ready(h);
1482 #if defined BOOST_THREAD_USES_DATETIME
1483 template<typename Duration>
1484 bool timed_wait(Duration const& rel_time) const
1488 boost::throw_exception(future_uninitialized());
1490 return future_->timed_wait(rel_time);
1493 bool timed_wait_until(boost::system_time const& abs_time) const
1497 boost::throw_exception(future_uninitialized());
1499 return future_->timed_wait_until(abs_time);
1502 #ifdef BOOST_THREAD_USES_CHRONO
1503 template <class Rep, class Period>
1505 wait_for(const chrono::duration<Rep, Period>& rel_time) const
1507 return wait_until(chrono::steady_clock::now() + rel_time);
1510 template <class Clock, class Duration>
1512 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
1516 boost::throw_exception(future_uninitialized());
1518 return future_->wait_until(abs_time);
1525 BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
1529 #if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
1530 template <class Rp, class Fp>
1531 BOOST_THREAD_FUTURE<Rp>
1532 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1534 template <class Rp, class Fp>
1535 BOOST_THREAD_FUTURE<Rp>
1536 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1537 #endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
1538 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1539 template<typename F, typename Rp, typename Fp>
1540 struct future_deferred_continuation_shared_state;
1541 template<typename F, typename Rp, typename Fp>
1542 struct future_async_continuation_shared_state;
1544 template <class F, class Rp, class Fp>
1545 BOOST_THREAD_FUTURE<Rp>
1546 make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1548 template <class F, class Rp, class Fp>
1549 BOOST_THREAD_FUTURE<Rp>
1550 make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1552 template <class F, class Rp, class Fp>
1553 BOOST_THREAD_FUTURE<Rp>
1554 make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1556 template<typename F, typename Rp, typename Fp>
1557 BOOST_THREAD_FUTURE<Rp>
1558 make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1560 template<typename F, typename Rp, typename Fp>
1561 BOOST_THREAD_FUTURE<Rp>
1562 make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1564 template<typename F, typename Rp, typename Fp>
1565 BOOST_THREAD_FUTURE<Rp>
1566 make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1569 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1570 template<typename Ex, typename F, typename Rp, typename Fp>
1571 BOOST_THREAD_FUTURE<Rp>
1572 make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1574 template<typename Ex, typename F, typename Rp, typename Fp>
1575 BOOST_THREAD_FUTURE<Rp>
1576 make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1578 template <class Rp, class Fp, class Executor>
1579 BOOST_THREAD_FUTURE<Rp>
1580 make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1583 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1584 template<typename F, typename Rp>
1585 struct future_unwrap_shared_state;
1586 template <class F, class Rp>
1587 inline BOOST_THREAD_FUTURE<Rp>
1588 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1591 #if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1592 template< typename InputIterator>
1593 typename boost::disable_if<is_future_type<InputIterator>,
1594 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1596 when_all(InputIterator first, InputIterator last);
1598 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1600 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1601 template< typename T0, typename ...T>
1602 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1603 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1606 template< typename InputIterator>
1607 typename boost::disable_if<is_future_type<InputIterator>,
1608 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1610 when_any(InputIterator first, InputIterator last);
1612 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1614 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1615 template< typename T0, typename ...T>
1616 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1617 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1619 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1622 template <typename R>
1623 class BOOST_THREAD_FUTURE : public detail::basic_future<R>
1626 typedef detail::basic_future<R> base_type;
1627 typedef typename base_type::future_ptr future_ptr;
1629 friend class shared_future<R>;
1630 friend class promise<R>;
1631 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1632 template <typename, typename, typename>
1633 friend struct detail::future_async_continuation_shared_state;
1634 template <typename, typename, typename>
1635 friend struct detail::future_deferred_continuation_shared_state;
1637 template <class F, class Rp, class Fp>
1638 friend BOOST_THREAD_FUTURE<Rp>
1639 detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1641 template <class F, class Rp, class Fp>
1642 friend BOOST_THREAD_FUTURE<Rp>
1643 detail::make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1645 template <class F, class Rp, class Fp>
1646 friend BOOST_THREAD_FUTURE<Rp>
1647 detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1649 template<typename F, typename Rp, typename Fp>
1650 friend BOOST_THREAD_FUTURE<Rp>
1651 detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1653 template<typename F, typename Rp, typename Fp>
1654 friend BOOST_THREAD_FUTURE<Rp>
1655 detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1657 template<typename F, typename Rp, typename Fp>
1658 friend BOOST_THREAD_FUTURE<Rp>
1659 detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1661 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1662 template<typename Ex, typename F, typename Rp, typename Fp>
1663 friend BOOST_THREAD_FUTURE<Rp>
1664 detail::make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1666 template<typename Ex, typename F, typename Rp, typename Fp>
1667 friend BOOST_THREAD_FUTURE<Rp>
1668 detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1670 template <class Rp, class Fp, class Executor>
1671 friend BOOST_THREAD_FUTURE<Rp>
1672 detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1675 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1676 template<typename F, typename Rp>
1677 friend struct detail::future_unwrap_shared_state;
1678 template <class F, class Rp>
1679 friend BOOST_THREAD_FUTURE<Rp>
1680 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1682 #if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1683 template< typename InputIterator>
1684 friend typename boost::disable_if<is_future_type<InputIterator>,
1685 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1687 when_all(InputIterator first, InputIterator last);
1689 //friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1691 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1692 template< typename T0, typename ...T>
1693 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1694 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1697 template< typename InputIterator>
1698 friend typename boost::disable_if<is_future_type<InputIterator>,
1699 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1701 when_any(InputIterator first, InputIterator last);
1703 //friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1705 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1706 template< typename T0, typename ...T>
1707 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1708 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1710 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1711 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1712 template <class> friend class packaged_task; // todo check if this works in windows
1714 friend class packaged_task<R>;
1716 friend class detail::future_waiter;
1718 template <class Rp, class Fp>
1719 friend BOOST_THREAD_FUTURE<Rp>
1720 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1722 template <class Rp, class Fp>
1723 friend BOOST_THREAD_FUTURE<Rp>
1724 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1726 typedef typename base_type::move_dest_type move_dest_type;
1728 BOOST_THREAD_FUTURE(future_ptr a_future):
1734 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1735 typedef future_state::state state;
1736 typedef R value_type; // EXTENSION
1738 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
1740 BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
1743 ~BOOST_THREAD_FUTURE() {
1746 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
1747 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1750 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1751 inline explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
1754 explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) :
1755 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1758 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1760 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1764 shared_future<R> share()
1766 return shared_future<R>(::boost::move(*this));
1769 void swap(BOOST_THREAD_FUTURE& other)
1771 static_cast<base_type*>(this)->swap(other);
1774 // todo this function must be private and friendship provided to the internal users.
1777 this->future_->set_async();
1779 // todo this function must be private and friendship provided to the internal users.
1782 this->future_->set_deferred();
1784 bool run_if_is_deferred() {
1785 return this->future_->run_if_is_deferred();
1787 bool run_if_is_deferred_or_ready() {
1788 return this->future_->run_if_is_deferred_or_ready();
1790 // retrieving the value
1791 move_dest_type get()
1793 if (this->future_.get() == 0)
1795 boost::throw_exception(future_uninitialized());
1797 unique_lock<boost::mutex> lk(this->future_->mutex);
1798 if (! this->future_->valid(lk))
1800 boost::throw_exception(future_uninitialized());
1802 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1803 this->future_->invalidate(lk);
1805 return this->future_->get(lk);
1808 template <typename R2>
1809 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1810 get_or(BOOST_THREAD_RV_REF(R2) v)
1813 if (this->future_.get() == 0)
1815 boost::throw_exception(future_uninitialized());
1817 unique_lock<boost::mutex> lk(this->future_->mutex);
1818 if (! this->future_->valid(lk))
1820 boost::throw_exception(future_uninitialized());
1822 this->future_->wait(lk, false);
1823 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1824 this->future_->invalidate(lk);
1827 if (this->future_->has_value(lk)) {
1828 return this->future_->get(lk);
1831 return boost::move(v);
1835 template <typename R2>
1836 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1837 get_or(R2 const& v) // EXTENSION
1839 if (this->future_.get() == 0)
1841 boost::throw_exception(future_uninitialized());
1843 unique_lock<boost::mutex> lk(this->future_->mutex);
1844 if (! this->future_->valid(lk))
1846 boost::throw_exception(future_uninitialized());
1848 this->future_->wait(lk, false);
1849 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1850 this->future_->invalidate(lk);
1852 if (this->future_->has_value(lk)) {
1853 return this->future_->get(lk);
1860 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1861 template<typename F>
1862 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1863 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1864 template<typename F>
1865 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1866 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1867 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1868 template<typename Ex, typename F>
1869 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1870 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1873 template <typename R2>
1874 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1875 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION
1876 template <typename R2>
1877 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1878 fallback_to(R2 const& v); // EXTENSION
1884 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
1886 template <typename R2>
1887 class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
1889 typedef BOOST_THREAD_FUTURE<R2> R;
1892 typedef detail::basic_future<R> base_type;
1893 typedef typename base_type::future_ptr future_ptr;
1895 friend class shared_future<R>;
1896 friend class promise<R>;
1897 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1898 template <typename, typename, typename>
1899 friend struct detail::future_async_continuation_shared_state;
1900 template <typename, typename, typename>
1901 friend struct detail::future_deferred_continuation_shared_state;
1903 template <class F, class Rp, class Fp>
1904 friend BOOST_THREAD_FUTURE<Rp>
1905 detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1907 template <class F, class Rp, class Fp>
1908 friend BOOST_THREAD_FUTURE<Rp>
1909 detail::make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1911 template <class F, class Rp, class Fp>
1912 friend BOOST_THREAD_FUTURE<Rp>
1913 detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1915 template<typename F, typename Rp, typename Fp>
1916 friend BOOST_THREAD_FUTURE<Rp>
1917 detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1919 template<typename F, typename Rp, typename Fp>
1920 friend BOOST_THREAD_FUTURE<Rp>
1921 detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1923 template<typename F, typename Rp, typename Fp>
1924 friend BOOST_THREAD_FUTURE<Rp>
1925 detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1927 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1928 template<typename Ex, typename F, typename Rp, typename Fp>
1929 friend BOOST_THREAD_FUTURE<Rp>
1930 detail::make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1932 template<typename Ex, typename F, typename Rp, typename Fp>
1933 friend BOOST_THREAD_FUTURE<Rp>
1934 detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1936 template <class Rp, class Fp, class Executor>
1937 friend BOOST_THREAD_FUTURE<Rp>
1938 detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1942 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1943 template<typename F, typename Rp>
1944 friend struct detail::future_unwrap_shared_state;
1945 template <class F, class Rp>
1946 friend BOOST_THREAD_FUTURE<Rp>
1947 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1949 #if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1950 template< typename InputIterator>
1951 friend typename boost::disable_if<is_future_type<InputIterator>,
1952 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1954 when_all(InputIterator first, InputIterator last);
1956 friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1958 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1959 template< typename T0, typename ...T>
1960 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1961 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1964 template< typename InputIterator>
1965 friend typename boost::disable_if<is_future_type<InputIterator>,
1966 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1968 when_any(InputIterator first, InputIterator last);
1970 friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1972 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1973 template< typename T0, typename ...T>
1974 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1975 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1977 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1979 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1980 template <class> friend class packaged_task; // todo check if this works in windows
1982 friend class packaged_task<R>;
1984 friend class detail::future_waiter;
1986 template <class Rp, class Fp>
1987 friend BOOST_THREAD_FUTURE<Rp>
1988 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1990 template <class Rp, class Fp>
1991 friend BOOST_THREAD_FUTURE<Rp>
1992 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1994 typedef typename base_type::move_dest_type move_dest_type;
1996 BOOST_THREAD_FUTURE(future_ptr a_future):
2002 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
2003 typedef future_state::state state;
2004 typedef R value_type; // EXTENSION
2006 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
2008 BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
2011 ~BOOST_THREAD_FUTURE() {
2014 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
2015 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2019 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
2021 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2025 shared_future<R> share()
2027 return shared_future<R>(::boost::move(*this));
2030 void swap(BOOST_THREAD_FUTURE& other)
2032 static_cast<base_type*>(this)->swap(other);
2035 // todo this function must be private and friendship provided to the internal users.
2038 this->future_->set_async();
2040 // todo this function must be private and friendship provided to the internal users.
2043 this->future_->set_deferred();
2045 bool run_if_is_deferred() {
2046 return this->future_->run_if_is_deferred();
2048 bool run_if_is_deferred_or_ready() {
2049 return this->future_->run_if_is_deferred_or_ready();
2051 // retrieving the value
2052 move_dest_type get()
2054 if (this->future_.get() == 0)
2056 boost::throw_exception(future_uninitialized());
2058 unique_lock<boost::mutex> lk(this->future_->mutex);
2059 if (! this->future_->valid(lk))
2061 boost::throw_exception(future_uninitialized());
2063 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
2064 this->future_->invalidate(lk);
2066 return this->future_->get(lk);
2068 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
2070 if (this->future_.get() == 0)
2072 boost::throw_exception(future_uninitialized());
2074 unique_lock<boost::mutex> lk(this->future_->mutex);
2075 if (! this->future_->valid(lk))
2077 boost::throw_exception(future_uninitialized());
2079 this->future_->wait(lk, false);
2080 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
2081 this->future_->invalidate(lk);
2083 if (this->future_->has_value(lk)) return this->future_->get(lk);
2084 else return boost::move(v);
2087 move_dest_type get_or(R const& v) // EXTENSION
2089 if (this->future_.get() == 0)
2091 boost::throw_exception(future_uninitialized());
2093 unique_lock<boost::mutex> lk(this->future_->mutex);
2094 if (! this->future_->valid(lk))
2096 boost::throw_exception(future_uninitialized());
2098 this->future_->wait(lk, false);
2099 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
2100 this->future_->invalidate(lk);
2102 if (this->future_->has_value(lk)) return this->future_->get(lk);
2107 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2108 template<typename F>
2109 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2110 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2111 template<typename F>
2112 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2113 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2114 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2115 template<typename Ex, typename F>
2116 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2117 then(Ex &ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2121 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
2123 BOOST_THREAD_FUTURE<R2>
2124 unwrap(); // EXTENSION
2129 template <typename R>
2130 class shared_future : public detail::basic_future<R>
2132 typedef detail::basic_future<R> base_type;
2133 typedef typename base_type::future_ptr future_ptr;
2135 friend class detail::future_waiter;
2136 friend class promise<R>;
2138 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2139 template <typename, typename, typename>
2140 friend struct detail::future_async_continuation_shared_state;
2141 template <typename, typename, typename>
2142 friend struct detail::future_deferred_continuation_shared_state;
2144 template <class F, class Rp, class Fp>
2145 friend BOOST_THREAD_FUTURE<Rp>
2146 detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
2148 template <class F, class Rp, class Fp>
2149 friend BOOST_THREAD_FUTURE<Rp>
2150 detail::make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
2152 template <class F, class Rp, class Fp>
2153 friend BOOST_THREAD_FUTURE<Rp>
2154 detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
2156 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2157 template <class> friend class packaged_task;// todo check if this works in windows
2159 friend class packaged_task<R>;
2161 shared_future(future_ptr a_future):
2166 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future)
2167 typedef R value_type; // EXTENSION
2169 shared_future(shared_future const& other):
2170 base_type(other.future_)
2173 typedef future_state::state state;
2175 BOOST_CONSTEXPR shared_future()
2178 shared_future(exceptional_ptr const& ex):
2183 shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other)
2185 this->future_ = other.future_;
2189 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
2190 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2193 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
2194 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2198 shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
2200 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2203 shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
2205 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2209 void swap(shared_future& other) BOOST_NOEXCEPT
2211 static_cast<base_type*>(this)->swap(other);
2213 bool run_if_is_deferred() {
2214 return this->future_->run_if_is_deferred();
2216 bool run_if_is_deferred_or_ready() {
2217 return this->future_->run_if_is_deferred_or_ready();
2219 // retrieving the value
2220 typename detail::shared_state<R>::shared_future_get_result_type get() const
2224 boost::throw_exception(future_uninitialized());
2226 return this->future_->get_sh();
2229 template <typename R2>
2230 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
2231 get_or(BOOST_THREAD_RV_REF(R2) v) const // EXTENSION
2235 boost::throw_exception(future_uninitialized());
2237 this->future_->wait();
2238 if (this->future_->has_value()) return this->future_->get_sh();
2239 else return boost::move(v);
2242 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2243 template<typename F>
2244 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2245 then(BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2246 template<typename F>
2247 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2248 then(launch policy, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2249 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2250 template<typename Ex, typename F>
2251 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2252 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2258 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
2260 template <typename R>
2263 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
2265 typedef typename detail::shared_state<R>::source_reference_type source_reference_type;
2266 typedef typename detail::shared_state<R>::rvalue_source_type rvalue_source_type;
2267 typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
2268 typedef typename detail::shared_state<R>::shared_future_get_result_type shared_future_get_result_type;
2271 bool future_obtained;
2275 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2276 #include <boost/thread/detail/atomic_undef_macros.hpp>
2277 if(!atomic_load(&future_))
2280 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
2282 #include <boost/thread/detail/atomic_redef_macros.hpp>
2287 BOOST_THREAD_MOVABLE_ONLY(promise)
2288 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2289 template <class Allocator>
2290 promise(boost::allocator_arg_t, Allocator a)
2292 typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2;
2294 typedef thread_detail::allocator_destructor<A2> D;
2296 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) );
2297 future_obtained = false;
2301 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2304 future_(new detail::shared_state<R>()),
2306 future_obtained(false)
2313 boost::unique_lock<boost::mutex> lock(future_->mutex);
2315 if(!future_->done && !future_->is_constructed)
2317 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2323 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2324 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2326 BOOST_THREAD_RV(rhs).future_.reset();
2327 BOOST_THREAD_RV(rhs).future_obtained=false;
2329 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2331 future_=BOOST_THREAD_RV(rhs).future_;
2332 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2333 BOOST_THREAD_RV(rhs).future_.reset();
2334 BOOST_THREAD_RV(rhs).future_obtained=false;
2338 void swap(promise& other)
2340 future_.swap(other.future_);
2341 std::swap(future_obtained,other.future_obtained);
2344 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2345 void set_executor(executor_ptr_type aex)
2348 if (future_.get()==0)
2350 boost::throw_exception(promise_moved());
2352 boost::lock_guard<boost::mutex> lk(future_->mutex);
2353 future_->set_executor_policy(aex, lk);
2357 BOOST_THREAD_FUTURE<R> get_future()
2360 if (future_.get()==0)
2362 boost::throw_exception(promise_moved());
2364 if (future_obtained)
2366 boost::throw_exception(future_already_retrieved());
2368 future_obtained=true;
2369 return BOOST_THREAD_FUTURE<R>(future_);
2372 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2374 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type
2375 set_value(TR const & r)
2378 boost::unique_lock<boost::mutex> lock(future_->mutex);
2381 boost::throw_exception(promise_already_satisfied());
2383 future_->mark_finished_with_result_internal(r, lock);
2386 void set_value(source_reference_type r)
2389 boost::unique_lock<boost::mutex> lock(future_->mutex);
2392 boost::throw_exception(promise_already_satisfied());
2394 future_->mark_finished_with_result_internal(r, lock);
2398 void set_value(rvalue_source_type r)
2401 boost::unique_lock<boost::mutex> lock(future_->mutex);
2404 boost::throw_exception(promise_already_satisfied());
2406 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2407 future_->mark_finished_with_result_internal(boost::move(r), lock);
2409 future_->mark_finished_with_result_internal(static_cast<rvalue_source_type>(r), lock);
2413 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2415 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type
2416 set_value_deferred(TR const & r)
2419 if (future_.get()==0)
2421 boost::throw_exception(promise_moved());
2423 future_->set_value_deferred(r);
2426 void set_value_deferred(source_reference_type r)
2429 if (future_.get()==0)
2431 boost::throw_exception(promise_moved());
2433 future_->set_value_deferred(r);
2437 void set_value_deferred(rvalue_source_type r)
2440 if (future_.get()==0)
2442 boost::throw_exception(promise_moved());
2444 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2445 future_->set_value_deferred(boost::move(r));
2447 future_->set_value_deferred(static_cast<rvalue_source_type>(r));
2451 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
2452 template <class ...Args>
2453 void emplace(BOOST_THREAD_FWD_REF(Args) ...args)
2456 boost::unique_lock<boost::mutex> lock(future_->mutex);
2459 boost::throw_exception(promise_already_satisfied());
2461 future_->mark_finished_with_result_internal(lock, boost::forward<Args>(args)...);
2466 void set_exception(boost::exception_ptr p)
2469 boost::unique_lock<boost::mutex> lock(future_->mutex);
2472 boost::throw_exception(promise_already_satisfied());
2474 future_->mark_exceptional_finish_internal(p, lock);
2476 template <typename E>
2477 void set_exception(E ex)
2479 set_exception(boost::copy_exception(ex));
2481 void set_exception_deferred(boost::exception_ptr p)
2484 if (future_.get()==0)
2486 boost::throw_exception(promise_moved());
2488 future_->set_exception_deferred(p);
2490 template <typename E>
2491 void set_exception_deferred(E ex)
2493 set_exception_deferred(boost::copy_exception(ex));
2496 // setting the result with deferred notification
2497 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2499 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value_at_thread_exit(TR const& r)
2501 if (future_.get()==0)
2503 boost::throw_exception(promise_moved());
2505 future_->set_value_at_thread_exit(r);
2508 void set_value_at_thread_exit(source_reference_type r)
2510 if (future_.get()==0)
2512 boost::throw_exception(promise_moved());
2514 future_->set_value_at_thread_exit(r);
2517 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
2519 if (future_.get()==0)
2521 boost::throw_exception(promise_moved());
2523 future_->set_value_at_thread_exit(boost::move(r));
2525 void set_exception_at_thread_exit(exception_ptr e)
2527 if (future_.get()==0)
2529 boost::throw_exception(promise_moved());
2531 future_->set_exception_at_thread_exit(e);
2533 template <typename E>
2534 void set_exception_at_thread_exit(E ex)
2536 set_exception_at_thread_exit(boost::copy_exception(ex));
2539 template<typename F>
2540 void set_wait_callback(F f)
2543 future_->set_wait_callback(f,this);
2545 void notify_deferred()
2547 if (future_.get()==0)
2549 boost::throw_exception(promise_moved());
2551 future_->notify_deferred();
2556 template <typename R>
2559 typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr;
2562 bool future_obtained;
2566 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2567 #include <boost/thread/detail/atomic_undef_macros.hpp>
2568 if(!atomic_load(&future_))
2571 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
2573 #include <boost/thread/detail/atomic_redef_macros.hpp>
2578 BOOST_THREAD_MOVABLE_ONLY(promise)
2579 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2580 template <class Allocator>
2581 promise(boost::allocator_arg_t, Allocator a)
2583 typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2;
2585 typedef thread_detail::allocator_destructor<A2> D;
2587 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
2588 future_obtained = false;
2592 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2595 future_(new detail::shared_state<R&>()),
2597 future_obtained(false)
2604 boost::unique_lock<boost::mutex> lock(future_->mutex);
2606 if(!future_->done && !future_->is_constructed)
2608 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2614 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2615 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2617 BOOST_THREAD_RV(rhs).future_.reset();
2618 BOOST_THREAD_RV(rhs).future_obtained=false;
2620 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2622 future_=BOOST_THREAD_RV(rhs).future_;
2623 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2624 BOOST_THREAD_RV(rhs).future_.reset();
2625 BOOST_THREAD_RV(rhs).future_obtained=false;
2629 void swap(promise& other)
2631 future_.swap(other.future_);
2632 std::swap(future_obtained,other.future_obtained);
2636 BOOST_THREAD_FUTURE<R&> get_future()
2639 if (future_.get()==0)
2641 boost::throw_exception(promise_moved());
2643 if (future_obtained)
2645 boost::throw_exception(future_already_retrieved());
2647 future_obtained=true;
2648 return BOOST_THREAD_FUTURE<R&>(future_);
2651 void set_value(R& r)
2654 boost::unique_lock<boost::mutex> lock(future_->mutex);
2657 boost::throw_exception(promise_already_satisfied());
2659 future_->mark_finished_with_result_internal(r, lock);
2661 void set_value_deferred(R& r)
2664 if (future_.get()==0)
2666 boost::throw_exception(promise_already_satisfied());
2668 future_->set_value_deferred(r);
2670 void set_exception(boost::exception_ptr p)
2673 boost::unique_lock<boost::mutex> lock(future_->mutex);
2676 boost::throw_exception(promise_already_satisfied());
2678 future_->mark_exceptional_finish_internal(p, lock);
2680 template <typename E>
2681 void set_exception(E ex)
2683 set_exception(boost::copy_exception(ex));
2685 void set_exception_deferred(boost::exception_ptr p)
2688 if (future_.get()==0)
2690 boost::throw_exception(promise_moved());
2692 future_->set_exception_deferred(p);
2694 template <typename E>
2695 void set_exception_deferred(E ex)
2697 set_exception_deferred(boost::copy_exception(ex));
2699 // setting the result with deferred notification
2700 void set_value_at_thread_exit(R& r)
2702 if (future_.get()==0)
2704 boost::throw_exception(promise_moved());
2706 future_->set_value_at_thread_exit(r);
2709 void set_exception_at_thread_exit(exception_ptr e)
2711 if (future_.get()==0)
2713 boost::throw_exception(promise_moved());
2715 future_->set_exception_at_thread_exit(e);
2717 template <typename E>
2718 void set_exception_at_thread_exit(E ex)
2720 set_exception_at_thread_exit(boost::copy_exception(ex));
2723 template<typename F>
2724 void set_wait_callback(F f)
2727 future_->set_wait_callback(f,this);
2729 void notify_deferred()
2731 if (future_.get()==0)
2733 boost::throw_exception(promise_moved());
2735 future_->notify_deferred();
2742 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr;
2745 bool future_obtained;
2749 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2750 if(!atomic_load(&future_))
2753 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>));
2758 BOOST_THREAD_MOVABLE_ONLY(promise)
2760 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2761 template <class Allocator>
2762 promise(boost::allocator_arg_t, Allocator a)
2764 typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2;
2766 typedef thread_detail::allocator_destructor<A2> D;
2768 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
2769 future_obtained = false;
2773 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2776 future_(new detail::shared_state<void>),
2778 future_obtained(false)
2785 boost::unique_lock<boost::mutex> lock(future_->mutex);
2787 if(!future_->done && !future_->is_constructed)
2789 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2795 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2796 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2798 // we need to release the future as shared_ptr doesn't implements move semantics
2799 BOOST_THREAD_RV(rhs).future_.reset();
2800 BOOST_THREAD_RV(rhs).future_obtained=false;
2803 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2805 future_=BOOST_THREAD_RV(rhs).future_;
2806 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2807 BOOST_THREAD_RV(rhs).future_.reset();
2808 BOOST_THREAD_RV(rhs).future_obtained=false;
2812 void swap(promise& other)
2814 future_.swap(other.future_);
2815 std::swap(future_obtained,other.future_obtained);
2819 BOOST_THREAD_FUTURE<void> get_future()
2823 if (future_.get()==0)
2825 boost::throw_exception(promise_moved());
2829 boost::throw_exception(future_already_retrieved());
2831 future_obtained=true;
2832 //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<void>(future_));
2833 return BOOST_THREAD_FUTURE<void>(future_);
2839 boost::unique_lock<boost::mutex> lock(future_->mutex);
2842 boost::throw_exception(promise_already_satisfied());
2844 future_->mark_finished_with_result_internal(lock);
2846 void set_value_deferred()
2849 if (future_.get()==0)
2851 boost::throw_exception(promise_moved());
2853 future_->set_value_deferred();
2856 void set_exception(boost::exception_ptr p)
2859 boost::unique_lock<boost::mutex> lock(future_->mutex);
2862 boost::throw_exception(promise_already_satisfied());
2864 future_->mark_exceptional_finish_internal(p,lock);
2866 template <typename E>
2867 void set_exception(E ex)
2869 set_exception(boost::copy_exception(ex));
2871 void set_exception_deferred(boost::exception_ptr p)
2874 if (future_.get()==0)
2876 boost::throw_exception(promise_moved());
2878 future_->set_exception_deferred(p);
2880 template <typename E>
2881 void set_exception_deferred(E ex)
2883 set_exception_deferred(boost::copy_exception(ex));
2885 // setting the result with deferred notification
2886 void set_value_at_thread_exit()
2888 if (future_.get()==0)
2890 boost::throw_exception(promise_moved());
2892 future_->set_value_at_thread_exit();
2895 void set_exception_at_thread_exit(exception_ptr e)
2897 if (future_.get()==0)
2899 boost::throw_exception(promise_moved());
2901 future_->set_exception_at_thread_exit(e);
2903 template <typename E>
2904 void set_exception_at_thread_exit(E ex)
2906 set_exception_at_thread_exit(boost::copy_exception(ex));
2909 template<typename F>
2910 void set_wait_callback(F f)
2913 future_->set_wait_callback(f,this);
2915 void notify_deferred()
2917 if (future_.get()==0)
2919 boost::throw_exception(promise_moved());
2921 future_->notify_deferred();
2925 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2926 namespace boost { namespace container {
2927 template <class R, class Alloc>
2928 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
2932 #if ! defined BOOST_NO_CXX11_ALLOCATOR
2934 template <class R, class Alloc>
2935 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
2945 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
2949 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2950 template<typename R>
2951 struct task_base_shared_state;
2952 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2953 template<typename R, typename ...ArgTypes>
2954 struct task_base_shared_state<R(ArgTypes...)>:
2956 template<typename R>
2957 struct task_base_shared_state<R()>:
2960 template<typename R>
2961 struct task_base_shared_state:
2963 detail::shared_state<R>
2967 task_base_shared_state():
2973 // todo The packaged_task::reset must be as if an assignemnt froma new packaged_task with the same function
2974 // the reset function is an optimization that avoids reallocating a new task.
2978 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2979 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2980 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2982 virtual void do_run()=0;
2987 boost::lock_guard<boost::mutex> lk(this->mutex);
2990 boost::throw_exception(task_already_started());
2994 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2995 do_run(boost::move(args)...);
3001 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3002 virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
3003 void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3005 virtual void do_apply()=0;
3010 boost::lock_guard<boost::mutex> lk(this->mutex);
3013 boost::throw_exception(task_already_started());
3017 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3018 do_apply(boost::move(args)...);
3024 void owner_destroyed()
3026 boost::unique_lock<boost::mutex> lk(this->mutex);
3030 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
3035 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3036 template<typename F, typename R>
3037 struct task_shared_state;
3038 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3039 template<typename F, typename R, typename ...ArgTypes>
3040 struct task_shared_state<F, R(ArgTypes...)>:
3041 task_base_shared_state<R(ArgTypes...)>
3043 template<typename F, typename R>
3044 struct task_shared_state<F, R()>:
3045 task_base_shared_state<R()>
3048 template<typename F, typename R>
3049 struct task_shared_state:
3050 task_base_shared_state<R>
3054 task_shared_state(task_shared_state&);
3057 task_shared_state(F const& f_):
3060 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
3066 return boost::move(f);
3069 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3070 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3074 this->set_value_at_thread_exit(f(boost::move(args)...));
3081 this->set_value_at_thread_exit(f());
3086 this->set_exception_at_thread_exit(current_exception());
3090 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3091 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3095 this->mark_finished_with_result(f(boost::move(args)...));
3102 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3104 this->mark_finished_with_result(boost::move(res));
3106 this->mark_finished_with_result(f());
3112 this->mark_exceptional_finish();
3117 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3118 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3119 template<typename F, typename R, typename ...ArgTypes>
3120 struct task_shared_state<F, R&(ArgTypes...)>:
3121 task_base_shared_state<R&(ArgTypes...)>
3123 template<typename F, typename R>
3124 struct task_shared_state<F, R&()>:
3125 task_base_shared_state<R&()>
3128 template<typename F, typename R>
3129 struct task_shared_state<F,R&>:
3130 task_base_shared_state<R&>
3134 task_shared_state(task_shared_state&);
3137 task_shared_state(F const& f_):
3140 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
3149 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3150 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3154 this->set_value_at_thread_exit(f(boost::move(args)...));
3161 this->set_value_at_thread_exit(f());
3166 this->set_exception_at_thread_exit(current_exception());
3170 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3171 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3175 this->mark_finished_with_result(f(boost::move(args)...));
3183 this->mark_finished_with_result(res);
3188 this->mark_exceptional_finish();
3193 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
3195 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3196 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3197 template<typename R, typename ...ArgTypes>
3198 struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>:
3199 task_base_shared_state<R(ArgTypes...)>
3201 template<typename R>
3202 struct task_shared_state<R (*)(), R()>:
3203 task_base_shared_state<R()>
3206 template<typename R>
3207 struct task_shared_state<R (*)(), R> :
3208 task_base_shared_state<R>
3212 task_shared_state(task_shared_state&);
3213 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3214 typedef R (*CallableType)(ArgTypes ... );
3216 typedef R (*CallableType)();
3220 task_shared_state(CallableType f_):
3224 CallableType callable()
3229 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3230 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3234 this->set_value_at_thread_exit(f(boost::move(args)...));
3242 this->set_value_at_thread_exit(boost::move(r));
3247 this->set_exception_at_thread_exit(current_exception());
3252 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3253 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3257 this->mark_finished_with_result(f(boost::move(args)...));
3265 this->mark_finished_with_result(boost::move(res));
3270 this->mark_exceptional_finish();
3274 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3275 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3276 template<typename R, typename ...ArgTypes>
3277 struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>:
3278 task_base_shared_state<R&(ArgTypes...)>
3280 template<typename R>
3281 struct task_shared_state<R& (*)(), R&()>:
3282 task_base_shared_state<R&()>
3285 template<typename R>
3286 struct task_shared_state<R& (*)(), R&> :
3287 task_base_shared_state<R&>
3291 task_shared_state(task_shared_state&);
3293 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3294 typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... );
3296 typedef R& (*CallableType)();
3299 task_shared_state(CallableType f_):
3303 CallableType callable()
3305 return boost::move(f);
3308 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3309 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3313 this->set_value_at_thread_exit(f(boost::move(args)...));
3320 this->set_value_at_thread_exit(f());
3325 this->set_exception_at_thread_exit(current_exception());
3330 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3331 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3335 this->mark_finished_with_result(f(boost::move(args)...));
3342 this->mark_finished_with_result(f());
3347 this->mark_exceptional_finish();
3352 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3353 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3354 template<typename F, typename ...ArgTypes>
3355 struct task_shared_state<F, void(ArgTypes...)>:
3356 task_base_shared_state<void(ArgTypes...)>
3358 template<typename F>
3359 struct task_shared_state<F, void()>:
3360 task_base_shared_state<void()>
3363 template<typename F>
3364 struct task_shared_state<F,void>:
3365 task_base_shared_state<void>
3369 task_shared_state(task_shared_state&);
3371 typedef F CallableType;
3373 task_shared_state(F const& f_):
3376 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
3381 return boost::move(f);
3383 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3384 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3388 f(boost::move(args)...);
3396 this->set_value_at_thread_exit();
3400 this->set_exception_at_thread_exit(current_exception());
3404 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3405 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3409 f(boost::move(args)...);
3417 this->mark_finished_with_result();
3421 this->mark_exceptional_finish();
3426 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3427 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3428 template<typename ...ArgTypes>
3429 struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>:
3430 task_base_shared_state<void(ArgTypes...)>
3433 struct task_shared_state<void (*)(), void()>:
3434 task_base_shared_state<void()>
3438 struct task_shared_state<void (*)(),void>:
3439 task_base_shared_state<void>
3443 task_shared_state(task_shared_state&);
3444 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3445 typedef void (*CallableType)(ArgTypes...);
3447 typedef void (*CallableType)();
3451 task_shared_state(CallableType f_):
3454 CallableType callable()
3458 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3459 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3463 f(boost::move(args)...);
3471 this->set_value_at_thread_exit();
3475 this->set_exception_at_thread_exit(current_exception());
3479 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3480 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3484 f(boost::move(args)...);
3492 this->mark_finished_with_result();
3496 this->mark_exceptional_finish();
3502 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3503 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3504 template<typename R, typename ...ArgTypes>
3505 class packaged_task<R(ArgTypes...)>
3507 typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr;
3508 boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task;
3510 template<typename R>
3511 class packaged_task<R()>
3513 typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr;
3514 boost::shared_ptr<detail::task_base_shared_state<R()> > task;
3517 template<typename R>
3520 typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr;
3521 boost::shared_ptr<detail::task_base_shared_state<R> > task;
3523 bool future_obtained;
3527 typedef R result_type;
3528 BOOST_THREAD_MOVABLE_ONLY(packaged_task)
3531 future_obtained(false)
3534 // construction and destruction
3535 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
3537 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3538 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3539 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
3541 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3542 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3543 task= task_ptr(new task_shared_state_type(f, boost::move(args)...));
3544 future_obtained=false;
3547 explicit packaged_task(R(*f)())
3550 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3551 task= task_ptr(new task_shared_state_type(f));
3552 future_obtained=false;
3556 explicit packaged_task(R(*f)())
3559 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3560 task= task_ptr(new task_shared_state_type(f));
3561 future_obtained=false;
3565 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
3567 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
3568 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3571 typedef typename decay<F>::type FR;
3572 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3573 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3574 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3576 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3579 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3581 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
3582 future_obtained = false;
3588 explicit packaged_task(F const& f
3589 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3592 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3593 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3594 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3596 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3599 typedef detail::task_shared_state<F,R> task_shared_state_type;
3601 task = task_ptr(new task_shared_state_type(f));
3602 future_obtained=false;
3605 explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
3607 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3608 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3609 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3610 task = task_ptr(new task_shared_state_type(boost::move(f)));
3612 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3613 task = task_ptr(new task_shared_state_type(boost::move(f)));
3616 typedef detail::task_shared_state<F,R> task_shared_state_type;
3617 task = task_ptr(new task_shared_state_type(boost::move(f)));
3619 future_obtained=false;
3624 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3625 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
3626 template <class Allocator>
3627 packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
3630 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3631 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3632 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3634 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3637 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3639 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3641 typedef thread_detail::allocator_destructor<A2> D;
3643 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3644 future_obtained = false;
3646 #endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
3648 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3649 template <class F, class Allocator>
3650 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
3652 typedef typename decay<F>::type FR;
3654 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3655 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3656 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3658 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3661 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3663 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3665 typedef thread_detail::allocator_destructor<A2> D;
3667 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
3668 future_obtained = false;
3670 #else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3671 template <class F, class Allocator>
3672 packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
3674 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3675 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3676 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3678 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3681 typedef detail::task_shared_state<F,R> task_shared_state_type;
3683 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3685 typedef thread_detail::allocator_destructor<A2> D;
3687 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3688 future_obtained = false;
3690 template <class F, class Allocator>
3691 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
3693 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3694 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3695 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3697 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3700 typedef detail::task_shared_state<F,R> task_shared_state_type;
3702 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3704 typedef thread_detail::allocator_destructor<A2> D;
3706 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) );
3707 future_obtained = false;
3710 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
3711 #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3715 task->owner_destroyed();
3720 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
3721 : future_obtained(BOOST_THREAD_RV(other).future_obtained) {
3722 task.swap(BOOST_THREAD_RV(other).task);
3723 BOOST_THREAD_RV(other).future_obtained=false;
3725 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT {
3727 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3728 packaged_task temp(boost::move(other));
3730 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
3736 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
3737 void set_executor(executor_ptr_type aex)
3740 boost::throw_exception(task_moved());
3741 boost::lock_guard<boost::mutex> lk(task->mutex);
3742 task->set_executor_policy(aex, lk);
3747 boost::throw_exception(future_error(system::make_error_code(future_errc::no_state)));
3749 // As if *this = packaged_task(task->callable());
3752 future_obtained=false;
3755 void swap(packaged_task& other) BOOST_NOEXCEPT {
3756 task.swap(other.task);
3757 std::swap(future_obtained,other.future_obtained);
3759 bool valid() const BOOST_NOEXCEPT {
3760 return task.get()!=0;
3764 BOOST_THREAD_FUTURE<R> get_future() {
3766 boost::throw_exception(task_moved());
3767 } else if(!future_obtained) {
3768 future_obtained=true;
3769 return BOOST_THREAD_FUTURE<R>(task);
3771 boost::throw_exception(future_already_retrieved());
3776 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3777 void operator()(ArgTypes... args) {
3779 boost::throw_exception(task_moved());
3781 task->run(boost::move(args)...);
3783 void make_ready_at_thread_exit(ArgTypes... args) {
3785 boost::throw_exception(task_moved());
3787 if (task->has_value()) {
3788 boost::throw_exception(promise_already_satisfied());
3790 task->apply(boost::move(args)...);
3795 boost::throw_exception(task_moved());
3799 void make_ready_at_thread_exit() {
3801 boost::throw_exception(task_moved());
3803 if (task->has_value()) boost::throw_exception(promise_already_satisfied());
3807 template<typename F>
3808 void set_wait_callback(F f) {
3809 task->set_wait_callback(f,this);
3813 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3814 namespace boost { namespace container {
3815 template <class R, class Alloc>
3816 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
3819 #if ! defined BOOST_NO_CXX11_ALLOCATOR
3821 template <class R, class Alloc>
3822 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
3830 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
3834 ////////////////////////////////
3835 // make_future_deferred_shared_state
3836 ////////////////////////////////
3837 template <class Rp, class Fp>
3838 BOOST_THREAD_FUTURE<Rp>
3839 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
3840 shared_ptr<future_deferred_shared_state<Rp, Fp> >
3841 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
3842 return BOOST_THREAD_FUTURE<Rp>(h);
3845 ////////////////////////////////
3846 // make_future_async_shared_state
3847 ////////////////////////////////
3848 template <class Rp, class Fp>
3849 BOOST_THREAD_FUTURE<Rp>
3850 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
3851 shared_ptr<future_async_shared_state<Rp, Fp> >
3852 h(new future_async_shared_state<Rp, Fp>());
3853 h->init(boost::forward<Fp>(f));
3854 return BOOST_THREAD_FUTURE<Rp>(h);
3858 ////////////////////////////////
3859 // template <class F, class... ArgTypes>
3860 // future<R> async(launch policy, F&&, ArgTypes&&...);
3861 ////////////////////////////////
3863 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
3865 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3866 template <class R, class... ArgTypes>
3867 BOOST_THREAD_FUTURE<R>
3868 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3869 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3870 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3871 typedef typename BF::result_type Rp;
3873 if (underlying_cast<int>(policy) & int(launch::async)) {
3874 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3877 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3880 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3881 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3884 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3889 //BOOST_THREAD_FUTURE<R> ret;
3890 //return ::boost::move(ret);
3894 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3897 BOOST_THREAD_FUTURE<R>
3898 async(launch policy, R(*f)()) {
3899 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3900 typedef packaged_task<R()> packaged_task_type;
3902 typedef packaged_task<R> packaged_task_type;
3905 if (underlying_cast<int>(policy) & int(launch::async)) {
3906 packaged_task_type pt( f );
3907 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
3909 boost::thread( boost::move(pt) ).detach();
3910 return ::boost::move(ret);
3911 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3913 //BOOST_THREAD_FUTURE<R> ret;
3914 //return ::boost::move(ret);
3917 //BOOST_THREAD_FUTURE<R> ret;
3918 //return ::boost::move(ret);
3922 #endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
3924 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3926 template <class F, class ...ArgTypes>
3927 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3928 typename decay<ArgTypes>::type...
3930 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3931 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3932 typedef typename BF::result_type Rp;
3934 if (underlying_cast<int>(policy) & int(launch::async)) {
3935 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3937 thread_detail::decay_copy(boost::forward<F>(f))
3938 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3941 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3942 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3944 thread_detail::decay_copy(boost::forward<F>(f))
3945 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3950 //BOOST_THREAD_FUTURE<R> ret;
3951 //return ::boost::move(ret);
3955 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3958 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3959 async(launch policy, BOOST_THREAD_FWD_REF(F) f) {
3960 typedef typename boost::result_of<typename decay<F>::type()>::type R;
3961 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3962 typedef packaged_task<R()> packaged_task_type;
3963 #else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3964 typedef packaged_task<R> packaged_task_type;
3965 #endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3967 if (underlying_cast<int>(policy) & int(launch::async)) {
3968 packaged_task_type pt( boost::forward<F>(f) );
3969 BOOST_THREAD_FUTURE<R> ret = pt.get_future();
3971 boost::thread( boost::move(pt) ).detach();
3972 return ::boost::move(ret);
3973 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3975 //BOOST_THREAD_FUTURE<R> ret;
3976 //return ::boost::move(ret);
3977 // return boost::detail::make_future_deferred_shared_state<Rp>(
3979 // thread_detail::decay_copy(boost::forward<F>(f))
3984 //BOOST_THREAD_FUTURE<R> ret;
3985 //return ::boost::move(ret);
3988 #endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3990 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
3993 /////////////////////////
3994 /// shared_state_nullary_task
3995 /////////////////////////
3996 template<typename Rp, typename Fp>
3997 struct shared_state_nullary_task
4000 typedef shared_ptr<shared_state_base > storage_type;
4005 shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f)
4006 : that(st), f_(boost::move(f))
4009 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
4010 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
4011 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
4012 : that(x.that), f_(x.f_)
4014 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
4023 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
4024 : that(x.that), f_(boost::move(x.f_))
4028 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
4032 f_=boost::move(x.f_);
4039 shared_ptr<shared_state<Rp> > that_ = static_pointer_cast<shared_state<Rp> >(that);
4041 that_->mark_finished_with_result(f_());
4043 that_->mark_exceptional_finish();
4046 ~shared_state_nullary_task()
4051 template<typename Fp>
4052 struct shared_state_nullary_task<void, Fp>
4054 typedef shared_ptr<shared_state_base > storage_type;
4058 shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f)
4059 : that(st), f_(boost::move(f))
4062 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
4063 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
4064 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
4065 : that(x.that), f_(x.f_)
4067 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
4076 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT
4077 : that(x.that), f_(boost::move(x.f_))
4081 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
4084 f_=boost::move(x.f_);
4091 shared_ptr<shared_state<void> > that_ = static_pointer_cast<shared_state<void> >(that);
4094 that_->mark_finished_with_result();
4096 that_->mark_exceptional_finish();
4102 BOOST_THREAD_DCL_MOVABLE_BEG2(R,F) detail::shared_state_nullary_task<R,F> BOOST_THREAD_DCL_MOVABLE_END
4105 /////////////////////////
4106 /// future_executor_shared_state_base
4107 /////////////////////////
4108 template<typename Rp>
4109 struct future_executor_shared_state: shared_state<Rp>
4111 typedef shared_state<Rp> base_type;
4114 future_executor_shared_state() {
4117 template <class Fp, class Executor>
4118 void init(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f)
4120 typedef typename decay<Fp>::type Cont;
4121 this->set_executor_policy(executor_ptr_type(new executor_ref<Executor>(ex)));
4122 shared_state_nullary_task<Rp,Cont> t(this->shared_from_this(), boost::forward<Fp>(f));
4123 ex.submit(boost::move(t));
4126 ~future_executor_shared_state() {}
4129 ////////////////////////////////
4130 // make_future_executor_shared_state
4131 ////////////////////////////////
4132 template <class Rp, class Fp, class Executor>
4133 BOOST_THREAD_FUTURE<Rp>
4134 make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) {
4135 shared_ptr<future_executor_shared_state<Rp> >
4136 h(new future_executor_shared_state<Rp>());
4137 h->init(ex, boost::forward<Fp>(f));
4138 return BOOST_THREAD_FUTURE<Rp>(h);
4143 ////////////////////////////////
4144 // template <class Executor, class F, class... ArgTypes>
4145 // future<R> async(Executor& ex, F&&, ArgTypes&&...);
4146 ////////////////////////////////
4148 //#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4149 #if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
4151 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4153 template <class Executor, class R, class... ArgTypes>
4154 BOOST_THREAD_FUTURE<R>
4155 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4156 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
4157 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
4158 typedef typename BF::result_type Rp;
4160 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4163 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
4167 #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4169 template <class Executor, class F, class ...ArgTypes>
4170 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4171 typename decay<ArgTypes>::type...
4173 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4174 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
4175 typedef typename BF::result_type Rp;
4177 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4179 thread_detail::decay_copy(boost::forward<F>(f))
4180 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
4185 #else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4186 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4188 template <class Executor, class R>
4189 BOOST_THREAD_FUTURE<R>
4190 async(Executor& ex, R(*f)()) {
4192 typedef detail::invoker<F> BF;
4193 typedef typename BF::result_type Rp;
4195 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4202 template <class Executor, class R, class A1>
4203 BOOST_THREAD_FUTURE<R>
4204 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) {
4205 typedef R(*F)(BOOST_THREAD_FWD_REF(A1));
4206 typedef detail::invoker<F, typename decay<A1>::type> BF;
4207 typedef typename BF::result_type Rp;
4209 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4212 , thread_detail::decay_copy(boost::forward<A1>(a1))
4216 #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4218 template <class Executor, class F>
4219 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
4220 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) {
4221 typedef detail::invoker<typename decay<F>::type> BF;
4222 typedef typename BF::result_type Rp;
4224 return boost::detail::make_future_executor_shared_state<Rp>(ex,
4226 thread_detail::decay_copy(boost::forward<F>(f))
4231 template <class Executor, class F, class A1>
4232 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4233 typename decay<A1>::type
4235 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) {
4236 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type> BF;
4237 typedef typename BF::result_type Rp;
4239 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4241 thread_detail::decay_copy(boost::forward<F>(f))
4242 , thread_detail::decay_copy(boost::forward<A1>(a1))
4247 template <class Executor, class F, class A1, class A2>
4248 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4249 typename decay<A1>::type, typename decay<A2>::type
4251 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) {
4252 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type, typename decay<A2>::type> BF;
4253 typedef typename BF::result_type Rp;
4255 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4257 thread_detail::decay_copy(boost::forward<F>(f))
4258 , thread_detail::decay_copy(boost::forward<A1>(a1))
4259 , thread_detail::decay_copy(boost::forward<A2>(a2))
4264 #endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4267 ////////////////////////////////
4268 // template <class F, class... ArgTypes>
4269 // future<R> async(F&&, ArgTypes&&...);
4270 ////////////////////////////////
4272 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4273 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
4274 template <class R, class... ArgTypes>
4275 BOOST_THREAD_FUTURE<R>
4276 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4277 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
4281 BOOST_THREAD_FUTURE<R>
4283 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
4288 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
4289 template <class F, class ...ArgTypes>
4290 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4291 typename decay<ArgTypes>::type...
4293 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4294 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
4298 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
4299 async(BOOST_THREAD_FWD_REF(F) f) {
4300 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
4304 ////////////////////////////////
4305 // make_future deprecated
4306 ////////////////////////////////
4307 template <typename T>
4308 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) {
4309 typedef typename decay<T>::type future_value_type;
4310 promise<future_value_type> p;
4311 p.set_value(boost::forward<future_value_type>(value));
4312 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4315 #if defined BOOST_THREAD_USES_MOVE
4316 inline BOOST_THREAD_FUTURE<void> make_future() {
4319 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4323 ////////////////////////////////
4324 // make_ready_future
4325 ////////////////////////////////
4328 struct deduced_type_impl
4334 struct deduced_type_impl<reference_wrapper<T> const>
4339 struct deduced_type_impl<reference_wrapper<T> >
4343 #if __cplusplus > 201103L
4345 struct deduced_type_impl<std::reference_wrapper<T> >
4353 typedef typename detail::deduced_type_impl<typename decay<T>::type>::type type;
4359 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4360 template <int = 0, int..., class T>
4364 BOOST_THREAD_FUTURE<typename detail::deduced_type<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) {
4365 typedef typename detail::deduced_type<T>::type future_value_type;
4366 promise<future_value_type> p;
4367 p.set_value(boost::forward<T>(value));
4368 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4371 // explicit overloads
4373 BOOST_THREAD_FUTURE<T> make_ready_future(typename remove_reference<T>::type & x)
4377 return p.get_future();
4381 BOOST_THREAD_FUTURE<T> make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference<T>::type) x)
4384 p.set_value(forward<typename remove_reference<T>::type>(x));
4385 return p.get_future();
4388 // variadic overload
4389 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4390 template <class T, class ...Args>
4391 BOOST_THREAD_FUTURE<T> make_ready_future(Args&&... args)
4394 p.emplace(forward<Args>(args)...);
4395 return p.get_future();
4400 template <typename T, typename T1>
4401 BOOST_THREAD_FUTURE<T> make_ready_no_decay_future(T1 value) {
4402 typedef T future_value_type;
4403 promise<future_value_type> p;
4405 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4408 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined BOOST_THREAD_USES_MOVE
4409 inline BOOST_THREAD_FUTURE<void> make_ready_future() {
4412 return p.get_future();
4417 template <typename T>
4418 BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) {
4420 p.set_exception(ex);
4421 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4424 template <typename T, typename E>
4425 BOOST_THREAD_FUTURE<T> make_exceptional_future(E ex) {
4427 p.set_exception(boost::copy_exception(ex));
4428 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4431 template <typename T>
4432 BOOST_THREAD_FUTURE<T> make_exceptional_future() {
4434 p.set_exception(boost::current_exception());
4435 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4437 template <typename T>
4438 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) {
4439 return make_exceptional_future<T>(ex);
4443 template<typename CLOSURE>
4444 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
4445 typedef decltype(closure()) T;
4448 p.set_value(closure());
4450 p.set_exception(std::current_exception());
4452 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4456 ////////////////////////////////
4457 // make_shared_future deprecated
4458 ////////////////////////////////
4459 template <typename T>
4460 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) {
4461 typedef typename decay<T>::type future_type;
4462 promise<future_type> p;
4463 p.set_value(boost::forward<T>(value));
4464 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
4467 inline shared_future<void> make_shared_future() {
4469 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
4472 ////////////////////////////////
4473 // detail::future_async_continuation_shared_state
4474 ////////////////////////////////
4475 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
4479 //////////////////////
4480 // detail::continuation_shared_state
4481 //////////////////////
4482 template<typename F, typename Rp, typename Fp, class ShSt=shared_state<Rp> >
4483 struct continuation_shared_state: ShSt
4489 continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4490 : parent(boost::move(f)),
4491 continuation(boost::move(c))
4495 void init(boost::unique_lock<boost::mutex> &lock)
4497 parent.future_->set_continuation_ptr(this->shared_from_this(), lock);
4502 this->mark_finished_with_result(this->continuation(boost::move(this->parent)));
4504 this->mark_exceptional_finish();
4506 // make sure parent is really cleared to prevent memory "leaks"
4510 void call(boost::unique_lock<boost::mutex>& lck) {
4512 relocker relock(lck);
4514 // neither continuation nor parent are protected by the lock - call() must only
4515 // be called once, and no one else must modify it.
4516 Rp res = this->continuation(boost::move(this->parent));
4518 // make sure parent is really cleared to prevent memory "leaks"
4523 this->mark_finished_with_result_internal(boost::move(res), lck);
4525 this->mark_exceptional_finish_internal(current_exception(), lck);
4527 // make sure parent is really cleared to prevent memory "leaks"
4528 relocker relock(lck);
4533 static void run(shared_ptr<boost::detail::shared_state_base> that_)
4535 continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get());
4539 ~continuation_shared_state() {}
4542 template<typename F, typename Fp, class ShSt>
4543 struct continuation_shared_state<F, void, Fp, ShSt>: ShSt
4549 continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4550 : parent(boost::move(f)),
4551 continuation(boost::move(c))
4555 void init(boost::unique_lock<boost::mutex> &lock)
4557 parent.future_->set_continuation_ptr(this->shared_from_this(), lock);
4563 this->continuation(boost::move(this->parent));
4564 this->mark_finished_with_result();
4566 this->mark_exceptional_finish();
4568 // make sure parent is really cleared to prevent memory "leaks"
4572 void call(boost::unique_lock<boost::mutex>& lck) {
4575 relocker relock(lck);
4576 // neither continuation nor parent are protected by the lock - call() must only
4577 // be called once, and no one else must modify it.
4578 this->continuation(boost::move(this->parent));
4580 // make sure parent is really cleared to prevent memory "leaks"
4583 this->mark_finished_with_result_internal(lck);
4585 this->mark_exceptional_finish_internal(current_exception(), lck);
4587 // make sure parent is really cleared to prevent memory "leaks"
4588 relocker relock(lck);
4593 static void run(shared_ptr<boost::detail::shared_state_base> that_)
4595 continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get());
4599 ~continuation_shared_state() {}
4601 /////////////////////////
4602 /// future_async_continuation_shared_state
4603 /////////////////////////
4605 template<typename F, typename Rp, typename Fp>
4606 struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
4608 typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
4610 future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4611 : base_type(boost::move(f), boost::forward<Fp>(c))
4614 void launch_continuation() {
4615 #if defined BOOST_THREAD_FUTURE_BLOCKING
4616 boost::lock_guard<boost::mutex> lk(this->mutex);
4617 this->thr_ = boost::thread(&future_async_continuation_shared_state::run, static_shared_from_this(this));
4619 boost::thread(&base_type::run, static_shared_from_this(this)).detach();
4624 /////////////////////////
4625 /// future_sync_continuation_shared_state
4626 /////////////////////////
4628 template<typename F, typename Rp, typename Fp>
4629 struct future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
4631 typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
4633 future_sync_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4634 : base_type(boost::move(f), boost::forward<Fp>(c))
4637 void launch_continuation() {
4643 /////////////////////////
4644 /// future_executor_continuation_shared_state
4645 /////////////////////////
4646 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4648 template <typename FutureExecutorContinuationSharedState>
4650 shared_ptr<FutureExecutorContinuationSharedState> that_;
4652 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
4653 BOOST_THREAD_COPYABLE_AND_MOVABLE(run_it)
4654 run_it(run_it const& x) //BOOST_NOEXCEPT
4657 run_it& operator=(BOOST_THREAD_COPY_ASSIGN_REF(run_it) x) //BOOST_NOEXCEPT
4665 run_it(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT
4670 run_it& operator=(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT {
4678 run_it(shared_ptr<FutureExecutorContinuationSharedState> that) : that_ (that) {}
4687 BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::run_it<F> BOOST_THREAD_DCL_MOVABLE_END
4691 template<typename F, typename Rp, typename Fp>
4692 struct future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4694 typedef continuation_shared_state<F,Rp,Fp> base_type;
4697 future_executor_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4698 : base_type(boost::move(f), boost::forward<Fp>(c))
4703 void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
4705 this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
4706 this->base_type::init(lk);
4709 void launch_continuation() {
4710 run_it<base_type> fct(static_shared_from_this(this));
4711 this->get_executor()->submit(boost::move(fct));
4714 ~future_executor_continuation_shared_state() {}
4718 /////////////////////////
4719 /// shared_future_async_continuation_shared_state
4720 /////////////////////////
4722 template<typename F, typename Rp, typename Fp>
4723 struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
4725 typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
4728 shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4729 : base_type(boost::move(f), boost::forward<Fp>(c))
4733 void launch_continuation() {
4734 #if defined BOOST_THREAD_FUTURE_BLOCKING
4735 boost::lock_guard<boost::mutex> lk(this->mutex);
4736 this->thr_ = boost::thread(&base_type::run, static_shared_from_this(this));
4738 boost::thread(&base_type::run, static_shared_from_this(this)).detach();
4743 /////////////////////////
4744 /// shared_future_async_continuation_shared_state
4745 /////////////////////////
4747 template<typename F, typename Rp, typename Fp>
4748 struct shared_future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
4750 typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
4753 shared_future_sync_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4754 : base_type(boost::move(f), boost::forward<Fp>(c))
4758 void launch_continuation() {
4764 /////////////////////////
4765 /// shared_future_executor_continuation_shared_state
4766 /////////////////////////
4767 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4769 template<typename F, typename Rp, typename Fp>
4770 struct shared_future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4772 typedef continuation_shared_state<F,Rp,Fp> base_type;
4776 shared_future_executor_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4777 : base_type(boost::move(f), boost::forward<Fp>(c))
4782 void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
4784 this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
4785 this->base_type::init(lk);
4788 void launch_continuation() {
4789 run_it<base_type> fct(static_shared_from_this(this));
4790 this->get_executor()->submit(boost::move(fct));
4793 ~shared_future_executor_continuation_shared_state() {}
4797 //////////////////////////
4798 /// future_deferred_continuation_shared_state
4799 //////////////////////////
4800 template<typename F, typename Rp, typename Fp>
4801 struct future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4803 typedef continuation_shared_state<F,Rp,Fp> base_type;
4805 future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4806 : base_type(boost::move(f), boost::forward<Fp>(c))
4808 this->set_deferred();
4811 virtual void execute(boost::unique_lock<boost::mutex>& lk) {
4812 this->parent.wait();
4816 virtual void launch_continuation() { }
4819 //////////////////////////
4820 /// shared_future_deferred_continuation_shared_state
4821 //////////////////////////
4822 template<typename F, typename Rp, typename Fp>
4823 struct shared_future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4825 typedef continuation_shared_state<F,Rp,Fp> base_type;
4828 shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4829 : base_type(boost::move(f), boost::forward<Fp>(c))
4831 this->set_deferred();
4834 virtual void execute(boost::unique_lock<boost::mutex>& lk) {
4835 this->parent.wait();
4839 virtual void launch_continuation() { }
4842 ////////////////////////////////
4843 // make_future_deferred_continuation_shared_state
4844 ////////////////////////////////
4845 template<typename F, typename Rp, typename Fp>
4846 BOOST_THREAD_FUTURE<Rp>
4847 make_future_deferred_continuation_shared_state(
4848 boost::unique_lock<boost::mutex> &lock,
4849 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) {
4850 typedef typename decay<Fp>::type Cont;
4851 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Cont> >
4852 h(new future_deferred_continuation_shared_state<F, Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4854 return BOOST_THREAD_FUTURE<Rp>(h);
4857 ////////////////////////////////
4858 // make_future_async_continuation_shared_state
4859 ////////////////////////////////
4860 template<typename F, typename Rp, typename Fp>
4861 BOOST_THREAD_FUTURE<Rp>
4862 make_future_async_continuation_shared_state(
4863 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4864 BOOST_THREAD_FWD_REF(Fp) c) {
4865 typedef typename decay<Fp>::type Cont;
4866 shared_ptr<future_async_continuation_shared_state<F,Rp, Cont> >
4867 h(new future_async_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4870 return BOOST_THREAD_FUTURE<Rp>(h);
4872 ////////////////////////////////
4873 // make_future_sync_continuation_shared_state
4874 ////////////////////////////////
4875 template<typename F, typename Rp, typename Fp>
4876 BOOST_THREAD_FUTURE<Rp>
4877 make_future_sync_continuation_shared_state(
4878 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4879 BOOST_THREAD_FWD_REF(Fp) c) {
4880 typedef typename decay<Fp>::type Cont;
4881 shared_ptr<future_sync_continuation_shared_state<F,Rp, Cont> >
4882 h(new future_sync_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4885 return BOOST_THREAD_FUTURE<Rp>(h);
4888 ////////////////////////////////
4889 // make_future_executor_continuation_shared_state
4890 ////////////////////////////////
4891 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4893 template<typename Ex, typename F, typename Rp, typename Fp>
4894 BOOST_THREAD_FUTURE<Rp>
4895 make_future_executor_continuation_shared_state(Ex& ex,
4896 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4897 BOOST_THREAD_FWD_REF(Fp) c) {
4898 typedef typename decay<Fp>::type Cont;
4899 shared_ptr<future_executor_continuation_shared_state<F,Rp, Cont> >
4900 h(new future_executor_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4903 return BOOST_THREAD_FUTURE<Rp>(h);
4907 ////////////////////////////////
4908 // make_shared_future_deferred_continuation_shared_state
4909 ////////////////////////////////
4910 template<typename F, typename Rp, typename Fp>
4911 BOOST_THREAD_FUTURE<Rp>
4912 make_shared_future_deferred_continuation_shared_state(
4913 boost::unique_lock<boost::mutex> &lock,
4914 F f, BOOST_THREAD_FWD_REF(Fp) c) {
4915 typedef typename decay<Fp>::type Cont;
4916 shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Cont> >
4917 h(new shared_future_deferred_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c)));
4920 return BOOST_THREAD_FUTURE<Rp>(h);
4922 ////////////////////////////////
4923 // make_shared_future_async_continuation_shared_state
4924 ////////////////////////////////
4925 template<typename F, typename Rp, typename Fp>
4926 BOOST_THREAD_FUTURE<Rp>
4927 make_shared_future_async_continuation_shared_state(
4928 boost::unique_lock<boost::mutex> &lock, F f,
4929 BOOST_THREAD_FWD_REF(Fp) c) {
4930 typedef typename decay<Fp>::type Cont;
4931 shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Cont> >
4932 h(new shared_future_async_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
4935 return BOOST_THREAD_FUTURE<Rp>(h);
4937 ////////////////////////////////
4938 // make_shared_future_sync_continuation_shared_state
4939 ////////////////////////////////
4940 template<typename F, typename Rp, typename Fp>
4941 BOOST_THREAD_FUTURE<Rp>
4942 make_shared_future_sync_continuation_shared_state(
4943 boost::unique_lock<boost::mutex> &lock, F f,
4944 BOOST_THREAD_FWD_REF(Fp) c) {
4945 typedef typename decay<Fp>::type Cont;
4946 shared_ptr<shared_future_sync_continuation_shared_state<F,Rp, Cont> >
4947 h(new shared_future_sync_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
4950 return BOOST_THREAD_FUTURE<Rp>(h);
4952 ////////////////////////////////
4953 // make_shared_future_executor_continuation_shared_state
4954 ////////////////////////////////
4955 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4956 template<typename Ex, typename F, typename Rp, typename Fp>
4957 BOOST_THREAD_FUTURE<Rp>
4958 make_shared_future_executor_continuation_shared_state(Ex& ex,
4959 boost::unique_lock<boost::mutex> &lock, F f,
4960 BOOST_THREAD_FWD_REF(Fp) c) {
4961 typedef typename decay<Fp>::type Cont;
4962 shared_ptr<shared_future_executor_continuation_shared_state<F, Rp, Cont> >
4963 h(new shared_future_executor_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c)));
4966 return BOOST_THREAD_FUTURE<Rp>(h);
4971 ////////////////////////////////
4972 // template<typename F>
4973 // auto future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4974 ////////////////////////////////
4975 template <typename R>
4976 template <typename F>
4977 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
4978 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
4979 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4980 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
4982 // keep state alive as we move ourself but hold the lock
4983 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4984 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4986 if (underlying_cast<int>(policy) & int(launch::async)) {
4987 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4988 lock, boost::move(*this), boost::forward<F>(func)
4990 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
4991 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4992 lock, boost::move(*this), boost::forward<F>(func)
4994 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
4995 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4996 lock, boost::move(*this), boost::forward<F>(func)
4998 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4999 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
5000 assert(this->future_->get_executor());
5001 typedef executor Ex;
5002 Ex& ex = *(this->future_->get_executor());
5003 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5004 lock, boost::move(*this), boost::forward<F>(func)
5007 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
5009 launch policy_ = this->launch_policy(lock);
5010 if (underlying_cast<int>(policy_) & int(launch::async)) {
5011 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5012 lock, boost::move(*this), boost::forward<F>(func)
5014 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
5015 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5016 lock, boost::move(*this), boost::forward<F>(func)
5018 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
5019 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5020 lock, boost::move(*this), boost::forward<F>(func)
5022 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5023 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
5024 assert(this->future_->get_executor());
5025 typedef executor Ex;
5026 Ex& ex = *(this->future_->get_executor());
5027 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5028 lock, boost::move(*this), boost::forward<F>(func)
5032 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5033 lock, boost::move(*this), boost::forward<F>(func)
5037 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5038 lock, boost::move(*this), boost::forward<F>(func)
5042 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5043 ////////////////////////////////
5044 // template<typename Ex, typename F>
5045 // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5046 ////////////////////////////////
5047 template <typename R>
5048 template <typename Ex, typename F>
5049 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
5050 BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
5051 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5052 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5054 // keep state alive as we move ourself but hold the lock
5055 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5056 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5058 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5059 lock, boost::move(*this), boost::forward<F>(func)
5063 ////////////////////////////////
5064 // template<typename F>
5065 // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5066 ////////////////////////////////
5067 template <typename R>
5068 template <typename F>
5069 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
5070 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) {
5072 #ifndef BOOST_THREAD_CONTINUATION_SYNC
5073 return this->then(this->launch_policy(), boost::forward<F>(func));
5075 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5076 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5078 // keep state alive as we move ourself but hold the lock
5079 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5080 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5082 launch policy = this->launch_policy(lock);
5083 if (underlying_cast<int>(policy) & int(launch::deferred)) {
5084 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5085 lock, boost::move(*this), boost::forward<F>(func)
5088 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5089 lock, boost::move(*this), boost::forward<F>(func)
5096 ////////////////////////////////
5097 // template<typename F>
5098 // auto future<future<R2> >::then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5099 ////////////////////////////////
5100 template <typename R2>
5101 template <typename F>
5102 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
5103 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
5104 typedef BOOST_THREAD_FUTURE<R2> R;
5105 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5106 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5108 // keep state alive as we move ourself but hold the lock
5109 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5110 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5112 if (underlying_cast<int>(policy) & int(launch::async)) {
5113 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5114 lock, boost::move(*this), boost::forward<F>(func)
5116 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
5117 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5118 lock, boost::move(*this), boost::forward<F>(func)
5120 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
5121 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5122 lock, boost::move(*this), boost::forward<F>(func)
5124 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5125 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
5126 assert(this->future_->get_executor());
5127 typedef executor Ex;
5128 Ex& ex = *(this->future_->get_executor());
5129 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5130 lock, boost::move(*this), boost::forward<F>(func)
5133 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
5134 launch policy_ = this->launch_policy(lock);
5136 if (underlying_cast<int>(policy_) & int(launch::async)) {
5137 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5138 lock, boost::move(*this), boost::forward<F>(func)
5140 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
5141 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5142 lock, boost::move(*this), boost::forward<F>(func)
5144 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
5145 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5146 lock, boost::move(*this), boost::forward<F>(func)
5148 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5149 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
5150 assert(this->future_->get_executor());
5151 typedef executor Ex;
5152 Ex& ex = *(this->future_->get_executor());
5153 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5154 lock, boost::move(*this), boost::forward<F>(func)
5158 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5159 lock, boost::move(*this), boost::forward<F>(func)
5163 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5164 lock, boost::move(*this), boost::forward<F>(func)
5169 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5170 ////////////////////////////////
5171 // template<typename Ex, typename F>
5172 // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5173 ////////////////////////////////
5174 template <typename R2>
5175 template <typename Ex, typename F>
5176 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
5177 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
5178 typedef BOOST_THREAD_FUTURE<R2> R;
5179 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5180 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5182 // keep state alive as we move ourself but hold the lock
5183 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5184 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5186 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5187 lock, boost::move(*this), boost::forward<F>(func)
5192 ////////////////////////////////
5193 // template<typename F>
5194 // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5195 ////////////////////////////////
5196 template <typename R2>
5197 template <typename F>
5198 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
5199 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) {
5201 #ifndef BOOST_THREAD_CONTINUATION_SYNC
5202 return this->then(this->launch_policy(), boost::forward<F>(func));
5204 typedef BOOST_THREAD_FUTURE<R2> R;
5205 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5206 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5208 // keep state alive as we move ourself but hold the lock
5209 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5210 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5212 launch policy = this->launch_policy(lock);
5214 if (underlying_cast<int>(policy) & int(launch::deferred)) {
5215 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5216 lock, boost::move(*this), boost::forward<F>(func)
5219 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5220 lock, boost::move(*this), boost::forward<F>(func)
5226 ////////////////////////////////
5227 // template<typename F>
5228 // auto shared_future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5229 ////////////////////////////////
5230 template <typename R>
5231 template <typename F>
5232 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5233 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const
5235 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5236 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5238 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5239 if (underlying_cast<int>(policy) & int(launch::async)) {
5240 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5241 lock, *this, boost::forward<F>(func)
5243 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
5244 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5245 lock, *this, boost::forward<F>(func)
5247 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
5248 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5249 lock, *this, boost::forward<F>(func)
5251 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5252 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
5253 typedef executor Ex;
5254 Ex& ex = *(this->future_->get_executor());
5255 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5256 lock, *this, boost::forward<F>(func)
5259 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
5261 launch policy_ = this->launch_policy(lock);
5262 if (underlying_cast<int>(policy_) & int(launch::async)) {
5263 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5264 lock, *this, boost::forward<F>(func)
5266 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
5267 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5268 lock, *this, boost::forward<F>(func)
5270 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
5271 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5272 lock, *this, boost::forward<F>(func)
5274 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5275 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
5276 typedef executor Ex;
5277 Ex& ex = *(this->future_->get_executor());
5278 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5279 lock, *this, boost::forward<F>(func)
5283 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5284 lock, *this, boost::forward<F>(func)
5289 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5290 lock, *this, boost::forward<F>(func)
5294 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5295 ////////////////////////////////
5296 // template<typename Ex, typename F>
5297 // auto shared_future<R>::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5298 ////////////////////////////////
5299 template <typename R>
5300 template <typename Ex, typename F>
5301 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5302 shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const
5304 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5305 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5307 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5308 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5309 lock, *this, boost::forward<F>(func)
5314 ////////////////////////////////
5315 // template<typename F>
5316 // auto shared_future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5317 ////////////////////////////////
5318 template <typename R>
5319 template <typename F>
5320 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5321 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const {
5322 #ifndef BOOST_THREAD_CONTINUATION_SYNC
5323 return this->then(this->launch_policy(), boost::forward<F>(func));
5325 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5326 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5328 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5329 launch policy = this->launch_policy(lock);
5330 if (underlying_cast<int>(policy) & int(launch::deferred)) {
5331 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5332 lock, *this, boost::forward<F>(func)
5335 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5336 lock, *this, boost::forward<F>(func)
5344 template <typename T>
5345 struct mfallbacker_to
5348 typedef T result_type;
5349 mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
5350 : value_(boost::move(v))
5353 T operator()(BOOST_THREAD_FUTURE<T> fut) {
5354 return fut.get_or(boost::move(value_));
5357 template <typename T>
5358 struct cfallbacker_to
5361 typedef T result_type;
5362 cfallbacker_to(T const& v)
5366 T operator()(BOOST_THREAD_FUTURE<T> fut) const {
5367 return fut.get_or(value_);
5372 ////////////////////////////////
5373 // future<R> future<R>::fallback_to(R&& v);
5374 ////////////////////////////////
5376 template <typename R>
5377 template <typename R2>
5378 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
5379 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) {
5380 return then(detail::mfallbacker_to<R>(boost::move(v)));
5383 template <typename R>
5384 template <typename R2>
5385 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
5386 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) {
5387 return then(detail::cfallbacker_to<R>(v));
5392 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
5395 /////////////////////////
5396 /// future_unwrap_shared_state
5397 /////////////////////////
5399 template<typename F, typename Rp>
5400 struct future_unwrap_shared_state: shared_state<Rp>
5403 typename F::value_type unwrapped;
5405 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
5406 : wrapped(boost::move(f)) {
5409 void launch_continuation()
5411 boost::unique_lock<boost::mutex> lk(this->mutex);
5412 // assert(wrapped.is_ready());
5413 if (! unwrapped.valid() )
5415 if (wrapped.has_exception()) {
5416 this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk);
5418 unwrapped = wrapped.get();
5419 if (unwrapped.valid())
5422 boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex);
5423 unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2);
5425 this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk);
5429 // assert(unwrapped.is_ready());
5430 if (unwrapped.has_exception()) {
5431 this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk);
5433 this->mark_finished_with_result_internal(unwrapped.get(), lk);
5439 template<typename F>
5440 struct future_unwrap_shared_state<F,void>: shared_state<void>
5443 typename F::value_type unwrapped;
5445 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
5446 : wrapped(boost::move(f)) {
5449 void launch_continuation()
5451 boost::unique_lock<boost::mutex> lk(this->mutex);
5452 // assert(wrapped.is_ready());
5453 if (! unwrapped.valid() )
5455 if (wrapped.has_exception()) {
5456 this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk);
5458 unwrapped = wrapped.get();
5459 if (unwrapped.valid())
5462 boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex);
5463 unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2);
5465 this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk);
5469 // assert(unwrapped.is_ready());
5470 if (unwrapped.has_exception()) {
5471 this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk);
5473 this->mark_finished_with_result_internal(lk);
5479 template <class F, class Rp>
5480 BOOST_THREAD_FUTURE<Rp>
5481 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) {
5482 shared_ptr<future_unwrap_shared_state<F, Rp> >
5483 h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
5484 h->wrapped.future_->set_continuation_ptr(h, lock);
5486 return BOOST_THREAD_FUTURE<Rp>(h);
5490 template <typename R>
5491 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other)
5492 : base_type(other.unwrap()) {}
5494 template <typename R2>
5495 BOOST_THREAD_FUTURE<R2>
5496 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
5498 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5500 // keep state alive as we move ourself but hold the lock
5501 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5502 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5504 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
5508 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
5511 struct input_iterator_tag {};
5512 struct vector_tag {};
5513 struct values_tag {};
5514 template <typename T>
5515 struct alias_t { typedef T type; };
5517 BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {};
5518 BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {};
5519 BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {};
5520 ////////////////////////////////
5521 // detail::future_async_when_all_shared_state
5522 ////////////////////////////////
5523 template<typename F>
5524 struct future_when_all_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
5526 typedef csbl::vector<F> vector_type;
5527 typedef typename F::value_type value_type;
5530 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
5531 future_when_all_vector_shared_state* that = static_cast<future_when_all_vector_shared_state*>(that_.get());
5533 boost::wait_for_all(that->vec_.begin(), that->vec_.end());
5534 that->mark_finished_with_result(boost::move(that->vec_));
5536 that->mark_exceptional_finish();
5539 bool run_deferred() {
5542 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
5543 if (! it->run_if_is_deferred())
5551 if (! run_deferred())
5553 future_when_all_vector_shared_state::run(this->shared_from_this());
5556 #ifdef BOOST_THREAD_FUTURE_BLOCKING
5557 this->thr_ = boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this());
5559 boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this()).detach();
5564 template< typename InputIterator>
5565 future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
5566 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
5570 future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
5571 : vec_(boost::move(v))
5575 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5576 template< typename T0, typename ...T>
5577 future_when_all_vector_shared_state(values_tag, BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5578 vec_.push_back(boost::forward<T0>(f));
5579 typename alias_t<char[]>::type{
5580 ( //first part of magic unpacker
5581 vec_.push_back(boost::forward<T>(futures)),'0'
5583 }; //second part of magic unpacker
5587 ~future_when_all_vector_shared_state() {}
5590 ////////////////////////////////
5591 // detail::future_async_when_any_shared_state
5592 ////////////////////////////////
5593 template<typename F>
5594 struct future_when_any_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
5596 typedef csbl::vector<F> vector_type;
5597 typedef typename F::value_type value_type;
5600 static void run(shared_ptr<boost::detail::shared_state_base> that_)
5602 future_when_any_vector_shared_state* that = static_cast<future_when_any_vector_shared_state*>(that_.get());
5604 boost::wait_for_any(that->vec_.begin(), that->vec_.end());
5605 that->mark_finished_with_result(boost::move(that->vec_));
5607 that->mark_exceptional_finish();
5610 bool run_deferred() {
5612 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
5613 if (it->run_if_is_deferred_or_ready())
5623 future_when_any_vector_shared_state::run(this->shared_from_this());
5627 #ifdef BOOST_THREAD_FUTURE_BLOCKING
5628 this->thr_ = boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this());
5630 boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this()).detach();
5635 template< typename InputIterator>
5636 future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
5637 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
5641 future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
5642 : vec_(boost::move(v))
5646 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5647 template< typename T0, typename ...T>
5648 future_when_any_vector_shared_state(values_tag,
5649 BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures
5651 vec_.push_back(boost::forward<T0>(f));
5652 typename alias_t<char[]>::type{
5653 ( //first part of magic unpacker
5654 vec_.push_back(boost::forward<T>(futures))
5658 }; //second part of magic unpacker
5662 ~future_when_any_vector_shared_state() {}
5665 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5666 struct wait_for_all_fctr {
5667 template <class ...T>
5668 void operator()(T&&... v) {
5669 boost::wait_for_all(boost::forward<T>(v)...);
5673 struct wait_for_any_fctr {
5674 template <class ...T>
5675 void operator()(T&&... v) {
5676 boost::wait_for_any(boost::forward<T>(v)...);
5681 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
5682 struct accumulate_run_if_is_deferred {
5683 bool operator ()(Tuple& t)
5685 return (! csbl::get<i-1>(t).run_if_is_deferred()) || accumulate_run_if_is_deferred<Tuple,i-1>()(t);
5688 template <class Tuple>
5689 struct accumulate_run_if_is_deferred<Tuple, 0> {
5690 bool operator ()(Tuple& )
5697 template< typename Tuple, typename T0, typename ...T>
5698 struct future_when_all_tuple_shared_state: future_async_shared_state_base<Tuple>
5701 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
5703 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
5704 future_when_all_tuple_shared_state* that = static_cast<future_when_all_tuple_shared_state*>(that_.get());
5706 // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor());
5707 that->wait_for_all(Index());
5709 that->mark_finished_with_result(boost::move(that->tup_));
5711 that->mark_exceptional_finish();
5715 template <size_t ...Indices>
5716 void wait_for_all(tuple_indices<Indices...>) {
5717 #if defined BOOST_THREAD_PROVIDES_INVOKE
5718 return invoke<void>(wait_for_all_fctr(), csbl::get<Indices>(tup_)...);
5720 return wait_for_all_fctr()(csbl::get<Indices>(tup_)...);
5724 bool run_deferred() {
5726 return accumulate_run_if_is_deferred<Tuple>()(tup_);
5729 if (! run_deferred())
5731 future_when_all_tuple_shared_state::run(this->shared_from_this());
5734 #ifdef BOOST_THREAD_FUTURE_BLOCKING
5735 this->thr_ = boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this());
5737 boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()).detach();
5742 template< typename F, typename ...Fs>
5743 future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) :
5744 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
5748 ~future_when_all_tuple_shared_state() {}
5753 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
5754 struct apply_any_run_if_is_deferred_or_ready {
5755 bool operator ()(Tuple& t)
5757 if (csbl::get<i-1>(t).run_if_is_deferred_or_ready()) return true;
5758 return apply_any_run_if_is_deferred_or_ready<Tuple,i-1>()(t);
5761 template <class Tuple>
5762 struct apply_any_run_if_is_deferred_or_ready<Tuple, 0> {
5763 bool operator ()(Tuple& )
5769 template< typename Tuple, typename T0, typename ...T >
5770 struct future_when_any_tuple_shared_state: future_async_shared_state_base<Tuple>
5773 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
5775 static void run(shared_ptr<boost::detail::shared_state_base> that_)
5777 future_when_any_tuple_shared_state* that = static_cast<future_when_any_tuple_shared_state*>(that_.get());
5779 // TODO make use of apply(that->tup_, wait_for_any_fctr);
5780 that->wait_for_any(Index());
5782 that->mark_finished_with_result(boost::move(that->tup_));
5784 that->mark_exceptional_finish();
5787 template <size_t ...Indices>
5788 void wait_for_any(tuple_indices<Indices...>) {
5789 #if defined BOOST_THREAD_PROVIDES_INVOKE
5790 return invoke<void>(wait_for_any_fctr(), csbl::get<Indices>(tup_)...);
5792 return wait_for_any_fctr()(csbl::get<Indices>(tup_)...);
5795 bool run_deferred() {
5796 return apply_any_run_if_is_deferred_or_ready<Tuple>()(tup_);
5801 future_when_any_tuple_shared_state::run(this->shared_from_this());
5805 #ifdef BOOST_THREAD_FUTURE_BLOCKING
5806 this->thr_ = boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this());
5808 boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()).detach();
5813 template< typename F, typename ...Fs>
5814 future_when_any_tuple_shared_state(values_tag,
5815 BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures
5817 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
5821 ~future_when_any_tuple_shared_state() {}
5827 template< typename InputIterator>
5828 typename boost::disable_if<is_future_type<InputIterator>,
5829 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
5831 when_all(InputIterator first, InputIterator last) {
5832 typedef typename InputIterator::value_type value_type;
5833 typedef csbl::vector<value_type> container_type;
5834 typedef detail::future_when_all_vector_shared_state<value_type> factory_type;
5836 if (first==last) return make_ready_future(container_type());
5837 shared_ptr<factory_type >
5838 h(new factory_type(detail::input_iterator_tag_value, first,last));
5840 return BOOST_THREAD_FUTURE<container_type>(h);
5843 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all() {
5844 return make_ready_future(csbl::tuple<>());
5847 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5848 template< typename T0, typename ...T>
5849 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
5850 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5851 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
5852 typedef detail::future_when_all_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
5854 shared_ptr<factory_type>
5855 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
5857 return BOOST_THREAD_FUTURE<container_type>(h);
5861 template< typename InputIterator>
5862 typename boost::disable_if<is_future_type<InputIterator>,
5863 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
5865 when_any(InputIterator first, InputIterator last) {
5866 typedef typename InputIterator::value_type value_type;
5867 typedef csbl::vector<value_type> container_type;
5868 typedef detail::future_when_any_vector_shared_state<value_type> factory_type;
5870 if (first==last) return make_ready_future(container_type());
5871 shared_ptr<factory_type >
5872 h(new factory_type(detail::input_iterator_tag_value, first,last));
5874 return BOOST_THREAD_FUTURE<container_type>(h);
5877 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any() {
5878 return make_ready_future(csbl::tuple<>());
5881 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5882 template< typename T0, typename ...T>
5883 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
5884 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5885 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
5886 typedef detail::future_when_any_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
5888 shared_ptr<factory_type>
5889 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
5891 return BOOST_THREAD_FUTURE<container_type>(h);
5894 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
5897 #endif // BOOST_NO_EXCEPTIONS