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 #ifndef BOOST_NO_EXCEPTIONS
20 #include <boost/thread/condition_variable.hpp>
21 #include <boost/thread/detail/move.hpp>
22 #include <boost/thread/detail/invoker.hpp>
23 #include <boost/thread/detail/invoke.hpp>
24 #include <boost/thread/detail/is_convertible.hpp>
25 #include <boost/thread/exceptional_ptr.hpp>
26 #include <boost/thread/futures/future_error.hpp>
27 #include <boost/thread/futures/future_error_code.hpp>
28 #include <boost/thread/futures/future_status.hpp>
29 #include <boost/thread/futures/is_future_type.hpp>
30 #include <boost/thread/futures/launch.hpp>
31 #include <boost/thread/futures/wait_for_all.hpp>
32 #include <boost/thread/futures/wait_for_any.hpp>
33 #include <boost/thread/lock_algorithms.hpp>
34 #include <boost/thread/lock_types.hpp>
35 #include <boost/thread/mutex.hpp>
36 #include <boost/thread/thread_only.hpp>
37 #include <boost/thread/thread_time.hpp>
38 #include <boost/thread/executor.hpp>
39 #include <boost/thread/executors/generic_executor_ref.hpp>
41 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
42 #include <boost/optional.hpp>
44 #include <boost/thread/csbl/memory/unique_ptr.hpp>
47 #include <boost/assert.hpp>
48 #include <boost/bind.hpp>
49 #ifdef BOOST_THREAD_USES_CHRONO
50 #include <boost/chrono/system_clocks.hpp>
52 #include <boost/core/enable_if.hpp>
53 #include <boost/core/ref.hpp>
54 #include <boost/enable_shared_from_this.hpp>
55 #include <boost/exception_ptr.hpp>
56 #include <boost/function.hpp>
57 #include <boost/next_prior.hpp>
58 #include <boost/scoped_array.hpp>
59 #include <boost/shared_ptr.hpp>
60 #include <boost/smart_ptr/make_shared.hpp>
61 #include <boost/throw_exception.hpp>
62 #include <boost/type_traits/conditional.hpp>
63 #include <boost/type_traits/decay.hpp>
64 #include <boost/type_traits/is_copy_constructible.hpp>
65 #include <boost/type_traits/is_fundamental.hpp>
66 #include <boost/type_traits/is_void.hpp>
67 #include <boost/utility/result_of.hpp>
70 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
71 #include <boost/thread/detail/memory.hpp>
72 #include <boost/container/scoped_allocator.hpp>
73 #if ! defined BOOST_NO_CXX11_ALLOCATOR
78 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
79 #include <boost/thread/csbl/tuple.hpp>
80 #include <boost/thread/csbl/vector.hpp>
88 #if defined BOOST_THREAD_PROVIDES_FUTURE
89 #define BOOST_THREAD_FUTURE future
91 #define BOOST_THREAD_FUTURE unique_future
97 shared_ptr<T> static_shared_from_this(T* that)
99 return static_pointer_cast<T>(that->shared_from_this());
102 shared_ptr<T const> static_shared_from_this(T const* that)
104 return static_pointer_cast<T const>(that->shared_from_this());
107 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
109 namespace executors {
113 typedef shared_ptr<executor> executor_ptr_type;
120 boost::unique_lock<boost::mutex>& lock_;
122 relocker(boost::unique_lock<boost::mutex>& lk):
129 if (! lock_.owns_lock()) {
134 if (! lock_.owns_lock()) {
139 relocker& operator=(relocker const&);
142 struct shared_state_base : enable_shared_from_this<shared_state_base>
144 typedef std::list<boost::condition_variable_any*> waiter_list;
145 typedef waiter_list::iterator notify_when_ready_handle;
146 // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
147 typedef shared_ptr<shared_state_base> continuation_ptr_type;
148 typedef std::vector<continuation_ptr_type> continuations_type;
150 boost::exception_ptr exception;
156 mutable boost::mutex mutex;
157 boost::condition_variable waiters;
158 waiter_list external_waiters;
159 boost::function<void()> callback;
160 // This declaration should be only included conditionally, but is included to maintain the same layout.
161 continuations_type continuations;
162 executor_ptr_type ex_;
164 // This declaration should be only included conditionally, but is included to maintain the same layout.
165 virtual void launch_continuation()
173 is_constructed(false),
174 policy_(launch::none),
179 shared_state_base(exceptional_ptr const& ex):
184 is_constructed(false),
185 policy_(launch::none),
191 virtual ~shared_state_base()
200 executor_ptr_type get_executor()
205 void set_executor_policy(executor_ptr_type aex)
210 void set_executor_policy(executor_ptr_type aex, boost::lock_guard<boost::mutex>&)
215 void set_executor_policy(executor_ptr_type aex, boost::unique_lock<boost::mutex>&)
221 bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; }
223 boost::unique_lock<boost::mutex> lk(this->mutex);
226 void invalidate(boost::unique_lock<boost::mutex>&) { is_valid_ = false; }
228 boost::unique_lock<boost::mutex> lk(this->mutex);
231 void validate(boost::unique_lock<boost::mutex>&) { is_valid_ = true; }
233 boost::unique_lock<boost::mutex> lk(this->mutex);
240 policy_ = launch::deferred;
244 is_deferred_ = false;
245 policy_ = launch::async;
247 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
250 is_deferred_ = false;
251 policy_ = launch::executor;
258 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
260 boost::unique_lock<boost::mutex> lock(this->mutex);
262 return external_waiters.insert(external_waiters.end(),&cv);
265 void unnotify_when_ready(notify_when_ready_handle it)
267 boost::lock_guard<boost::mutex> lock(this->mutex);
268 external_waiters.erase(it);
272 // this inline definition results in ODR. See https://github.com/boostorg/thread/issues/193
273 // to avoid it, we define the function on the derived templates using the macro BOOST_THREAD_DO_CONTINUATION
274 #define BOOST_THREAD_DO_CONTINUATION
275 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
276 void do_continuation(boost::unique_lock<boost::mutex>& lock)
278 if (! continuations.empty()) {
279 continuations_type the_continuations = continuations;
280 continuations.clear();
282 for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) {
283 (*it)->launch_continuation();
288 void do_continuation(boost::unique_lock<boost::mutex>&)
294 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
295 #define BOOST_THREAD_DO_CONTINUATION \
296 void do_continuation(boost::unique_lock<boost::mutex>& lock) \
298 if (! this->continuations.empty()) { \
299 continuations_type the_continuations = this->continuations; \
300 this->continuations.clear(); \
301 relocker rlk(lock); \
302 for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { \
303 (*it)->launch_continuation(); \
308 #define BOOST_THREAD_DO_CONTINUATION \
309 void do_continuation(boost::unique_lock<boost::mutex>&) \
314 virtual void do_continuation(boost::unique_lock<boost::mutex>&) = 0;
317 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
318 virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
320 continuations.push_back(continuation);
322 do_continuation(lock);
326 void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
329 waiters.notify_all();
330 for(waiter_list::const_iterator it=external_waiters.begin(),
331 end=external_waiters.end();it!=end;++it)
335 do_continuation(lock);
337 void notify_deferred()
339 boost::unique_lock<boost::mutex> lock(this->mutex);
340 mark_finished_internal(lock);
343 void do_callback(boost::unique_lock<boost::mutex>& lock)
345 if(callback && !done)
347 boost::function<void()> local_callback=callback;
348 relocker relock(lock);
353 virtual bool run_if_is_deferred()
355 boost::unique_lock<boost::mutex> lk(this->mutex);
365 virtual bool run_if_is_deferred_or_ready()
367 boost::unique_lock<boost::mutex> lk(this->mutex);
378 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true)
386 waiters.wait(lk, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
387 if(rethrow && exception)
389 boost::rethrow_exception(exception);
393 virtual void wait(boost::unique_lock<boost::mutex>& lock, bool rethrow=true)
395 wait_internal(lock, rethrow);
398 void wait(bool rethrow=true)
400 boost::unique_lock<boost::mutex> lock(this->mutex);
404 #if defined BOOST_THREAD_USES_DATETIME
405 template<typename Duration>
406 bool timed_wait(Duration const& rel_time)
408 boost::unique_lock<boost::mutex> lock(this->mutex);
413 return waiters.timed_wait(lock, rel_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
416 bool timed_wait_until(boost::system_time const& target_time)
418 boost::unique_lock<boost::mutex> lock(this->mutex);
423 return waiters.timed_wait(lock, target_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
426 #ifdef BOOST_THREAD_USES_CHRONO
428 template <class Clock, class Duration>
430 wait_until(const chrono::time_point<Clock, Duration>& abs_time)
432 boost::unique_lock<boost::mutex> lock(this->mutex);
434 return future_status::deferred;
436 if(!waiters.wait_until(lock, abs_time, boost::bind(&shared_state_base::is_done, boost::ref(*this))))
438 return future_status::timeout;
440 return future_status::ready;
443 void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
446 mark_finished_internal(lock);
449 void mark_exceptional_finish()
451 boost::unique_lock<boost::mutex> lock(this->mutex);
452 mark_exceptional_finish_internal(boost::current_exception(), lock);
455 void set_exception_deferred(exception_ptr e)
457 unique_lock<boost::mutex> lk(this->mutex);
460 throw_exception(promise_already_satisfied());
463 this->is_constructed = true;
465 void set_exception_at_thread_exit(exception_ptr e)
467 set_exception_deferred(e);
468 // unique_lock<boost::mutex> lk(this->mutex);
469 // if (has_value(lk))
471 // throw_exception(promise_already_satisfied());
474 // this->is_constructed = true;
475 detail::make_ready_at_thread_exit(shared_from_this());
478 bool has_value() const
480 boost::lock_guard<boost::mutex> lock(this->mutex);
481 return done && ! exception;
484 bool has_value(unique_lock<boost::mutex>& ) const
486 return done && ! exception;
489 bool has_exception() const
491 boost::lock_guard<boost::mutex> lock(this->mutex);
492 return done && exception;
495 launch launch_policy(boost::unique_lock<boost::mutex>&) const
500 future_state::state get_state(boost::unique_lock<boost::mutex>&) const
504 return future_state::waiting;
508 return future_state::ready;
511 future_state::state get_state() const
513 boost::lock_guard<boost::mutex> guard(this->mutex);
516 return future_state::waiting;
520 return future_state::ready;
524 exception_ptr get_exception_ptr()
526 boost::unique_lock<boost::mutex> lock(this->mutex);
527 wait_internal(lock, false);
531 template<typename F,typename U>
532 void set_wait_callback(F f,U* u)
534 boost::lock_guard<boost::mutex> lock(this->mutex);
535 callback=boost::bind(f,boost::ref(*u));
538 virtual void execute(boost::unique_lock<boost::mutex>&) {}
541 shared_state_base(shared_state_base const&);
542 shared_state_base& operator=(shared_state_base const&);
545 // Used to create stand-alone futures
548 detail::shared_state_base
550 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
551 typedef boost::optional<T> storage_type;
553 typedef boost::csbl::unique_ptr<T> storage_type;
555 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
556 typedef T const& source_reference_type;
557 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
558 typedef T move_dest_type;
559 #elif defined BOOST_THREAD_USES_MOVE
560 typedef typename conditional<boost::is_fundamental<T>::value,T,T const&>::type source_reference_type;
561 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
562 typedef T move_dest_type;
564 typedef T& source_reference_type;
565 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;
566 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;
569 typedef const T& shared_future_get_result_type;
576 shared_state(exceptional_ptr const& ex):
577 detail::shared_state_base(ex), result()
580 // locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
581 BOOST_THREAD_DO_CONTINUATION
583 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
585 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
588 result.reset(new T(result_));
590 this->mark_finished_internal(lock);
593 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
595 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
596 result = boost::move(result_);
597 #elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
598 result.reset(new T(boost::move(result_)));
600 result.reset(new T(static_cast<rvalue_source_type>(result_)));
602 this->mark_finished_internal(lock);
606 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
607 template <class ...Args>
608 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock, BOOST_THREAD_FWD_REF(Args)... args)
610 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
611 result.emplace(boost::forward<Args>(args)...);
613 result.reset(new T(boost::forward<Args>(args)...));
615 this->mark_finished_internal(lock);
619 void mark_finished_with_result(source_reference_type result_)
621 boost::unique_lock<boost::mutex> lock(this->mutex);
622 this->mark_finished_with_result_internal(result_, lock);
625 void mark_finished_with_result(rvalue_source_type result_)
627 boost::unique_lock<boost::mutex> lock(this->mutex);
629 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
630 mark_finished_with_result_internal(boost::move(result_), lock);
632 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
636 storage_type& get_storage(boost::unique_lock<boost::mutex>& lk)
641 virtual move_dest_type get(boost::unique_lock<boost::mutex>& lk)
643 return boost::move(*get_storage(lk));
647 boost::unique_lock<boost::mutex> lk(this->mutex);
648 return this->get(lk);
651 virtual shared_future_get_result_type get_sh(boost::unique_lock<boost::mutex>& lk)
653 return *get_storage(lk);
655 shared_future_get_result_type get_sh()
657 boost::unique_lock<boost::mutex> lk(this->mutex);
658 return this->get_sh(lk);
660 void set_value_deferred(source_reference_type result_)
662 unique_lock<boost::mutex> lk(this->mutex);
663 if (this->has_value(lk))
665 throw_exception(promise_already_satisfied());
667 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
670 result.reset(new T(result_));
673 this->is_constructed = true;
675 void set_value_deferred(rvalue_source_type result_)
677 unique_lock<boost::mutex> lk(this->mutex);
678 if (this->has_value(lk))
680 throw_exception(promise_already_satisfied());
683 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
684 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
685 result = boost::move(result_);
687 result.reset(new T(boost::move(result_)));
690 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
691 result = boost::move(result_);
693 result.reset(new T(static_cast<rvalue_source_type>(result_)));
696 this->is_constructed = true;
699 void set_value_at_thread_exit(source_reference_type result_)
701 set_value_deferred(result_);
702 // unique_lock<boost::mutex> lk(this->mutex);
703 // if (this->has_value(lk))
705 // throw_exception(promise_already_satisfied());
707 //#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
710 // result.reset(new T(result_));
713 // this->is_constructed = true;
714 detail::make_ready_at_thread_exit(shared_from_this());
716 void set_value_at_thread_exit(rvalue_source_type result_)
718 set_value_deferred(boost::move(result_));
719 // unique_lock<boost::mutex> lk(this->mutex);
720 // if (this->has_value(lk))
721 // throw_exception(promise_already_satisfied());
723 //#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
724 //#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
725 // result = boost::move(result_);
727 // result.reset(new T(boost::move(result_)));
730 //#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
731 // result = boost::move(result_);
733 // result.reset(new T(static_cast<rvalue_source_type>(result_)));
736 // this->is_constructed = true;
737 detail::make_ready_at_thread_exit(shared_from_this());
741 shared_state(shared_state const&);
742 shared_state& operator=(shared_state const&);
746 struct shared_state<T&>:
747 detail::shared_state_base
749 typedef T* storage_type;
750 typedef T& source_reference_type;
751 typedef T& move_dest_type;
752 typedef T& shared_future_get_result_type;
760 shared_state(exceptional_ptr const& ex):
761 detail::shared_state_base(ex), result(0)
764 // locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
765 BOOST_THREAD_DO_CONTINUATION
767 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
770 mark_finished_internal(lock);
773 void mark_finished_with_result(source_reference_type result_)
775 boost::unique_lock<boost::mutex> lock(this->mutex);
776 mark_finished_with_result_internal(result_, lock);
779 virtual T& get(boost::unique_lock<boost::mutex>& lock)
786 boost::unique_lock<boost::mutex> lk(this->mutex);
790 virtual T& get_sh(boost::unique_lock<boost::mutex>& lock)
797 boost::unique_lock<boost::mutex> lock(this->mutex);
801 void set_value_deferred(T& result_)
803 unique_lock<boost::mutex> lk(this->mutex);
804 if (this->has_value(lk))
806 throw_exception(promise_already_satisfied());
809 this->is_constructed = true;
812 void set_value_at_thread_exit(T& result_)
814 set_value_deferred(result_);
815 // unique_lock<boost::mutex> lk(this->mutex);
816 // if (this->has_value(lk))
817 // throw_exception(promise_already_satisfied());
819 // this->is_constructed = true;
820 detail::make_ready_at_thread_exit(shared_from_this());
824 shared_state(shared_state const&);
825 shared_state& operator=(shared_state const&);
829 struct shared_state<void>:
830 detail::shared_state_base
832 typedef void shared_future_get_result_type;
833 typedef void move_dest_type;
838 shared_state(exceptional_ptr const& ex):
839 detail::shared_state_base(ex)
842 // locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
843 BOOST_THREAD_DO_CONTINUATION
845 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
847 mark_finished_internal(lock);
850 void mark_finished_with_result()
852 boost::unique_lock<boost::mutex> lock(this->mutex);
853 mark_finished_with_result_internal(lock);
856 virtual void get(boost::unique_lock<boost::mutex>& lock)
858 this->wait_internal(lock);
862 boost::unique_lock<boost::mutex> lock(this->mutex);
866 virtual void get_sh(boost::unique_lock<boost::mutex>& lock)
868 this->wait_internal(lock);
872 boost::unique_lock<boost::mutex> lock(this->mutex);
876 void set_value_deferred()
878 unique_lock<boost::mutex> lk(this->mutex);
879 if (this->has_value(lk))
881 throw_exception(promise_already_satisfied());
883 this->is_constructed = true;
885 void set_value_at_thread_exit()
887 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;
894 detail::make_ready_at_thread_exit(shared_from_this());
897 shared_state(shared_state const&);
898 shared_state& operator=(shared_state const&);
901 /////////////////////////
902 /// future_async_shared_state_base
903 /////////////////////////
904 template<typename Rp>
905 struct future_async_shared_state_base: shared_state<Rp>
907 typedef shared_state<Rp> base_type;
909 #ifdef BOOST_THREAD_FUTURE_BLOCKING
913 if (this_thread::get_id() == thr_.get_id())
918 if (thr_.joinable()) thr_.join();
922 future_async_shared_state_base()
927 ~future_async_shared_state_base()
929 #ifdef BOOST_THREAD_FUTURE_BLOCKING
931 #elif defined BOOST_THREAD_ASYNC_FUTURE_WAITS
932 unique_lock<boost::mutex> lk(this->mutex);
933 this->waiters.wait(lk, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
937 virtual void wait(boost::unique_lock<boost::mutex>& lk, bool rethrow)
939 #ifdef BOOST_THREAD_FUTURE_BLOCKING
945 this->base_type::wait(lk, rethrow);
949 /////////////////////////
950 /// future_async_shared_state
951 /////////////////////////
952 template<typename Rp, typename Fp>
953 struct future_async_shared_state: future_async_shared_state_base<Rp>
955 future_async_shared_state()
959 void init(BOOST_THREAD_FWD_REF(Fp) f)
961 #ifdef BOOST_THREAD_FUTURE_BLOCKING
962 this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f));
964 boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f)).detach();
968 static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f)
972 that->mark_finished_with_result(f());
976 that->mark_exceptional_finish();
981 template<typename Fp>
982 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void>
984 void init(BOOST_THREAD_FWD_REF(Fp) f)
986 #ifdef BOOST_THREAD_FUTURE_BLOCKING
987 this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
989 boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
993 static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f)
998 that->mark_finished_with_result();
1002 that->mark_exceptional_finish();
1007 template<typename Rp, typename Fp>
1008 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&>
1010 void init(BOOST_THREAD_FWD_REF(Fp) f)
1012 #ifdef BOOST_THREAD_FUTURE_BLOCKING
1013 this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
1015 boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
1019 static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f)
1023 that->mark_finished_with_result(f());
1027 that->mark_exceptional_finish();
1032 //////////////////////////
1033 /// future_deferred_shared_state
1034 //////////////////////////
1035 template<typename Rp, typename Fp>
1036 struct future_deferred_shared_state: shared_state<Rp>
1040 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
1041 : func_(boost::move(f))
1043 this->set_deferred();
1046 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1049 Fp local_fuct=boost::move(func_);
1050 relocker relock(lck);
1051 Rp res = local_fuct();
1053 this->mark_finished_with_result_internal(boost::move(res), lck);
1057 this->mark_exceptional_finish_internal(current_exception(), lck);
1061 template<typename Rp, typename Fp>
1062 struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
1066 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
1067 : func_(boost::move(f))
1069 this->set_deferred();
1072 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1075 this->mark_finished_with_result_internal(func_(), lck);
1079 this->mark_exceptional_finish_internal(current_exception(), lck);
1084 template<typename Fp>
1085 struct future_deferred_shared_state<void,Fp>: shared_state<void>
1089 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
1090 : func_(boost::move(f))
1092 this->set_deferred();
1095 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1098 Fp local_fuct=boost::move(func_);
1099 relocker relock(lck);
1102 this->mark_finished_with_result_internal(lck);
1106 this->mark_exceptional_finish_internal(current_exception(), lck);
1114 typedef std::vector<int>::size_type count_type;
1116 struct registered_waiter
1118 boost::shared_ptr<detail::shared_state_base> future_;
1119 detail::shared_state_base::notify_when_ready_handle handle;
1122 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future,
1123 detail::shared_state_base::notify_when_ready_handle handle_,
1125 future_(a_future),handle(handle_),index(index_)
1129 struct all_futures_lock
1132 typedef std::ptrdiff_t count_type_portable;
1134 typedef count_type count_type_portable;
1136 count_type_portable count;
1137 boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
1139 all_futures_lock(std::vector<registered_waiter>& futures):
1140 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
1142 for(count_type_portable i=0;i<count;++i)
1144 locks[i]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(futures[i].future_->mutex));
1150 boost::lock(locks.get(),locks.get()+count);
1155 for(count_type_portable i=0;i<count;++i)
1162 boost::condition_variable_any cv;
1163 std::vector<registered_waiter> futures_;
1164 count_type future_count;
1171 template<typename F>
1176 registered_waiter waiter(f.future_,f.future_->notify_when_ready(cv),future_count);
1178 futures_.push_back(waiter);
1180 f.future_->unnotify_when_ready(waiter.handle);
1187 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
1188 template<typename F1, typename... Fs>
1189 void add(F1& f1, Fs&... fs)
1191 add(f1); add(fs...);
1197 all_futures_lock lk(futures_);
1200 for(count_type i=0;i<futures_.size();++i)
1202 if(futures_[i].future_->done)
1204 return futures_[i].index;
1213 for(count_type i=0;i<futures_.size();++i)
1215 futures_[i].future_->unnotify_when_ready(futures_[i].handle);
1222 template <typename R>
1223 class BOOST_THREAD_FUTURE;
1225 template <typename R>
1226 class shared_future;
1228 template<typename T>
1229 struct is_future_type<BOOST_THREAD_FUTURE<T> > : true_type
1233 template<typename T>
1234 struct is_future_type<shared_future<T> > : true_type
1238 // template<typename Iterator>
1239 // typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
1244 // detail::future_waiter waiter;
1245 // for(Iterator current=begin;current!=end;++current)
1247 // waiter.add(*current);
1249 // return boost::next(begin,waiter.wait());
1252 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
1253 template<typename F1,typename F2>
1254 typename boost::enable_if<is_future_type<F1>,typename detail::future_waiter::count_type>::type wait_for_any(F1& f1,F2& f2)
1256 detail::future_waiter waiter;
1259 return waiter.wait();
1262 template<typename F1,typename F2,typename F3>
1263 typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3)
1265 detail::future_waiter waiter;
1269 return waiter.wait();
1272 template<typename F1,typename F2,typename F3,typename F4>
1273 typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
1275 detail::future_waiter waiter;
1280 return waiter.wait();
1283 template<typename F1,typename F2,typename F3,typename F4,typename F5>
1284 typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
1286 detail::future_waiter waiter;
1292 return waiter.wait();
1295 template<typename F1, typename... Fs>
1296 typename boost::enable_if<is_future_type<F1>, typename detail::future_waiter::count_type>::type
1297 wait_for_any(F1& f1, Fs&... fs)
1299 detail::future_waiter waiter;
1300 waiter.add(f1, fs...);
1301 return waiter.wait();
1303 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1305 template <typename R>
1308 template <typename R>
1309 class packaged_task;
1313 /// Common implementation for all the futures independently of the return type
1318 /// Common implementation for future and shared_future.
1319 template <typename R>
1320 class basic_future : public base_future
1325 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
1326 typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
1328 static //BOOST_CONSTEXPR
1329 future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) {
1330 return future_ptr(new detail::shared_state<R>(ex));
1335 basic_future(future_ptr a_future):
1341 typedef future_state::state state;
1343 BOOST_THREAD_MOVABLE_ONLY(basic_future)
1344 basic_future(): future_() {}
1348 basic_future(exceptional_ptr const& ex)
1349 : future_(make_exceptional_future_ptr(ex))
1356 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
1357 future_(BOOST_THREAD_RV(other).future_)
1359 BOOST_THREAD_RV(other).future_.reset();
1361 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
1363 future_=BOOST_THREAD_RV(other).future_;
1364 BOOST_THREAD_RV(other).future_.reset();
1367 void swap(basic_future& that) BOOST_NOEXCEPT
1369 future_.swap(that.future_);
1371 // functions to check state, and wait for ready
1372 state get_state(boost::unique_lock<boost::mutex>& lk) const
1376 return future_state::uninitialized;
1378 return future_->get_state(lk);
1380 state get_state() const
1384 return future_state::uninitialized;
1386 return future_->get_state();
1389 bool is_ready() const
1391 return get_state()==future_state::ready;
1394 bool is_ready(boost::unique_lock<boost::mutex>& lk) const
1396 return get_state(lk)==future_state::ready;
1398 bool has_exception() const
1400 return future_ && future_->has_exception();
1403 bool has_value() const
1405 return future_ && future_->has_value();
1408 launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
1410 if ( future_ ) return future_->launch_policy(lk);
1411 else return launch(launch::none);
1414 launch launch_policy() const
1417 boost::unique_lock<boost::mutex> lk(this->future_->mutex);
1418 return future_->launch_policy(lk);
1420 else return launch(launch::none);
1423 exception_ptr get_exception_ptr()
1426 ? future_->get_exception_ptr()
1430 bool valid() const BOOST_NOEXCEPT
1432 return future_.get() != 0 && future_->valid();
1439 boost::throw_exception(future_uninitialized());
1441 future_->wait(false);
1444 typedef detail::shared_state_base::notify_when_ready_handle notify_when_ready_handle;
1446 boost::mutex& mutex() {
1449 boost::throw_exception(future_uninitialized());
1451 return future_->mutex;
1454 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
1458 boost::throw_exception(future_uninitialized());
1460 return future_->notify_when_ready(cv);
1463 void unnotify_when_ready(notify_when_ready_handle h)
1467 boost::throw_exception(future_uninitialized());
1469 return future_->unnotify_when_ready(h);
1472 #if defined BOOST_THREAD_USES_DATETIME
1473 template<typename Duration>
1474 bool timed_wait(Duration const& rel_time) const
1478 boost::throw_exception(future_uninitialized());
1480 return future_->timed_wait(rel_time);
1483 bool timed_wait_until(boost::system_time const& abs_time) const
1487 boost::throw_exception(future_uninitialized());
1489 return future_->timed_wait_until(abs_time);
1492 #ifdef BOOST_THREAD_USES_CHRONO
1493 template <class Rep, class Period>
1495 wait_for(const chrono::duration<Rep, Period>& rel_time) const
1497 return wait_until(chrono::steady_clock::now() + rel_time);
1500 template <class Clock, class Duration>
1502 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
1506 boost::throw_exception(future_uninitialized());
1508 return future_->wait_until(abs_time);
1515 BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
1519 #if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
1520 template <class Rp, class Fp>
1521 BOOST_THREAD_FUTURE<Rp>
1522 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1524 template <class Rp, class Fp>
1525 BOOST_THREAD_FUTURE<Rp>
1526 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1527 #endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
1528 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1529 template<typename F, typename Rp, typename Fp>
1530 struct future_deferred_continuation_shared_state;
1531 template<typename F, typename Rp, typename Fp>
1532 struct future_async_continuation_shared_state;
1534 template <class F, class Rp, class Fp>
1535 BOOST_THREAD_FUTURE<Rp>
1536 make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1538 template <class F, class Rp, class Fp>
1539 BOOST_THREAD_FUTURE<Rp>
1540 make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1542 template <class F, class Rp, class Fp>
1543 BOOST_THREAD_FUTURE<Rp>
1544 make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1546 template<typename F, typename Rp, typename Fp>
1547 BOOST_THREAD_FUTURE<Rp>
1548 make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1550 template<typename F, typename Rp, typename Fp>
1551 BOOST_THREAD_FUTURE<Rp>
1552 make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1554 template<typename F, typename Rp, typename Fp>
1555 BOOST_THREAD_FUTURE<Rp>
1556 make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1559 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1560 template<typename Ex, typename F, typename Rp, typename Fp>
1561 BOOST_THREAD_FUTURE<Rp>
1562 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);
1564 template<typename Ex, typename F, typename Rp, typename Fp>
1565 BOOST_THREAD_FUTURE<Rp>
1566 make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1568 template <class Rp, class Fp, class Executor>
1569 BOOST_THREAD_FUTURE<Rp>
1570 make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1573 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1574 template<typename F, typename Rp>
1575 struct future_unwrap_shared_state;
1576 template <class F, class Rp>
1577 inline BOOST_THREAD_FUTURE<Rp>
1578 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1581 #if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1582 template< typename InputIterator>
1583 typename boost::disable_if<is_future_type<InputIterator>,
1584 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1586 when_all(InputIterator first, InputIterator last);
1588 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1590 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1591 template< typename T0, typename ...T>
1592 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1593 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1596 template< typename InputIterator>
1597 typename boost::disable_if<is_future_type<InputIterator>,
1598 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1600 when_any(InputIterator first, InputIterator last);
1602 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1604 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1605 template< typename T0, typename ...T>
1606 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1607 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1609 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1612 template <typename R>
1613 class BOOST_THREAD_FUTURE : public detail::basic_future<R>
1616 typedef detail::basic_future<R> base_type;
1617 typedef typename base_type::future_ptr future_ptr;
1619 friend class shared_future<R>;
1620 friend class promise<R>;
1621 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1622 template <typename, typename, typename>
1623 friend struct detail::future_async_continuation_shared_state;
1624 template <typename, typename, typename>
1625 friend struct detail::future_deferred_continuation_shared_state;
1627 template <class F, class Rp, class Fp>
1628 friend BOOST_THREAD_FUTURE<Rp>
1629 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);
1631 template <class F, class Rp, class Fp>
1632 friend BOOST_THREAD_FUTURE<Rp>
1633 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);
1635 template <class F, class Rp, class Fp>
1636 friend BOOST_THREAD_FUTURE<Rp>
1637 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);
1639 template<typename F, typename Rp, typename Fp>
1640 friend BOOST_THREAD_FUTURE<Rp>
1641 detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1643 template<typename F, typename Rp, typename Fp>
1644 friend BOOST_THREAD_FUTURE<Rp>
1645 detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1647 template<typename F, typename Rp, typename Fp>
1648 friend BOOST_THREAD_FUTURE<Rp>
1649 detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1651 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1652 template<typename Ex, typename F, typename Rp, typename Fp>
1653 friend BOOST_THREAD_FUTURE<Rp>
1654 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);
1656 template<typename Ex, typename F, typename Rp, typename Fp>
1657 friend BOOST_THREAD_FUTURE<Rp>
1658 detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1660 template <class Rp, class Fp, class Executor>
1661 friend BOOST_THREAD_FUTURE<Rp>
1662 detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1665 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1666 template<typename F, typename Rp>
1667 friend struct detail::future_unwrap_shared_state;
1668 template <class F, class Rp>
1669 friend BOOST_THREAD_FUTURE<Rp>
1670 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1672 #if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1673 template< typename InputIterator>
1674 friend typename boost::disable_if<is_future_type<InputIterator>,
1675 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1677 when_all(InputIterator first, InputIterator last);
1679 //friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1681 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1682 template< typename T0, typename ...T>
1683 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1684 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1687 template< typename InputIterator>
1688 friend typename boost::disable_if<is_future_type<InputIterator>,
1689 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1691 when_any(InputIterator first, InputIterator last);
1693 //friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1695 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1696 template< typename T0, typename ...T>
1697 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1698 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1700 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1701 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1702 template <class> friend class packaged_task; // todo check if this works in windows
1704 friend class packaged_task<R>;
1706 friend class detail::future_waiter;
1708 template <class Rp, class Fp>
1709 friend BOOST_THREAD_FUTURE<Rp>
1710 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1712 template <class Rp, class Fp>
1713 friend BOOST_THREAD_FUTURE<Rp>
1714 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1716 typedef typename base_type::move_dest_type move_dest_type;
1718 BOOST_THREAD_FUTURE(future_ptr a_future):
1724 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1725 typedef future_state::state state;
1726 typedef R value_type; // EXTENSION
1728 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
1730 BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
1733 ~BOOST_THREAD_FUTURE() {
1736 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
1737 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1740 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1741 inline explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
1744 explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) :
1745 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1748 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1750 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1754 shared_future<R> share()
1756 return shared_future<R>(::boost::move(*this));
1759 void swap(BOOST_THREAD_FUTURE& other)
1761 static_cast<base_type*>(this)->swap(other);
1764 // todo this function must be private and friendship provided to the internal users.
1767 this->future_->set_async();
1769 // todo this function must be private and friendship provided to the internal users.
1772 this->future_->set_deferred();
1774 bool run_if_is_deferred() {
1775 return this->future_->run_if_is_deferred();
1777 bool run_if_is_deferred_or_ready() {
1778 return this->future_->run_if_is_deferred_or_ready();
1780 // retrieving the value
1781 move_dest_type get()
1783 if (this->future_.get() == 0)
1785 boost::throw_exception(future_uninitialized());
1787 unique_lock<boost::mutex> lk(this->future_->mutex);
1788 if (! this->future_->valid(lk))
1790 boost::throw_exception(future_uninitialized());
1792 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1793 this->future_->invalidate(lk);
1795 return this->future_->get(lk);
1798 template <typename R2>
1799 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1800 get_or(BOOST_THREAD_RV_REF(R2) v)
1803 if (this->future_.get() == 0)
1805 boost::throw_exception(future_uninitialized());
1807 unique_lock<boost::mutex> lk(this->future_->mutex);
1808 if (! this->future_->valid(lk))
1810 boost::throw_exception(future_uninitialized());
1812 this->future_->wait(lk, false);
1813 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1814 this->future_->invalidate(lk);
1817 if (this->future_->has_value(lk)) {
1818 return this->future_->get(lk);
1821 return boost::move(v);
1825 template <typename R2>
1826 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1827 get_or(R2 const& v) // EXTENSION
1829 if (this->future_.get() == 0)
1831 boost::throw_exception(future_uninitialized());
1833 unique_lock<boost::mutex> lk(this->future_->mutex);
1834 if (! this->future_->valid(lk))
1836 boost::throw_exception(future_uninitialized());
1838 this->future_->wait(lk, false);
1839 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1840 this->future_->invalidate(lk);
1842 if (this->future_->has_value(lk)) {
1843 return this->future_->get(lk);
1850 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1851 template<typename F>
1852 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1853 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1854 template<typename F>
1855 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1856 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1857 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1858 template<typename Ex, typename F>
1859 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1860 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1863 template <typename R2>
1864 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1865 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION
1866 template <typename R2>
1867 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1868 fallback_to(R2 const& v); // EXTENSION
1874 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
1876 template <typename R2>
1877 class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
1879 typedef BOOST_THREAD_FUTURE<R2> R;
1882 typedef detail::basic_future<R> base_type;
1883 typedef typename base_type::future_ptr future_ptr;
1885 friend class shared_future<R>;
1886 friend class promise<R>;
1887 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1888 template <typename, typename, typename>
1889 friend struct detail::future_async_continuation_shared_state;
1890 template <typename, typename, typename>
1891 friend struct detail::future_deferred_continuation_shared_state;
1893 template <class F, class Rp, class Fp>
1894 friend BOOST_THREAD_FUTURE<Rp>
1895 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);
1897 template <class F, class Rp, class Fp>
1898 friend BOOST_THREAD_FUTURE<Rp>
1899 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);
1901 template <class F, class Rp, class Fp>
1902 friend BOOST_THREAD_FUTURE<Rp>
1903 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);
1905 template<typename F, typename Rp, typename Fp>
1906 friend BOOST_THREAD_FUTURE<Rp>
1907 detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1909 template<typename F, typename Rp, typename Fp>
1910 friend BOOST_THREAD_FUTURE<Rp>
1911 detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1913 template<typename F, typename Rp, typename Fp>
1914 friend BOOST_THREAD_FUTURE<Rp>
1915 detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1917 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1918 template<typename Ex, typename F, typename Rp, typename Fp>
1919 friend BOOST_THREAD_FUTURE<Rp>
1920 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);
1922 template<typename Ex, typename F, typename Rp, typename Fp>
1923 friend BOOST_THREAD_FUTURE<Rp>
1924 detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1926 template <class Rp, class Fp, class Executor>
1927 friend BOOST_THREAD_FUTURE<Rp>
1928 detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1932 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1933 template<typename F, typename Rp>
1934 friend struct detail::future_unwrap_shared_state;
1935 template <class F, class Rp>
1936 friend BOOST_THREAD_FUTURE<Rp>
1937 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1939 #if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1940 template< typename InputIterator>
1941 friend typename boost::disable_if<is_future_type<InputIterator>,
1942 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1944 when_all(InputIterator first, InputIterator last);
1946 friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1948 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1949 template< typename T0, typename ...T>
1950 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1951 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1954 template< typename InputIterator>
1955 friend typename boost::disable_if<is_future_type<InputIterator>,
1956 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1958 when_any(InputIterator first, InputIterator last);
1960 friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1962 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1963 template< typename T0, typename ...T>
1964 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1965 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1967 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1969 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1970 template <class> friend class packaged_task; // todo check if this works in windows
1972 friend class packaged_task<R>;
1974 friend class detail::future_waiter;
1976 template <class Rp, class Fp>
1977 friend BOOST_THREAD_FUTURE<Rp>
1978 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1980 template <class Rp, class Fp>
1981 friend BOOST_THREAD_FUTURE<Rp>
1982 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1984 typedef typename base_type::move_dest_type move_dest_type;
1986 BOOST_THREAD_FUTURE(future_ptr a_future):
1992 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1993 typedef future_state::state state;
1994 typedef R value_type; // EXTENSION
1996 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
1998 BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
2001 ~BOOST_THREAD_FUTURE() {
2004 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
2005 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2009 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
2011 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2015 shared_future<R> share()
2017 return shared_future<R>(::boost::move(*this));
2020 void swap(BOOST_THREAD_FUTURE& other)
2022 static_cast<base_type*>(this)->swap(other);
2025 // todo this function must be private and friendship provided to the internal users.
2028 this->future_->set_async();
2030 // todo this function must be private and friendship provided to the internal users.
2033 this->future_->set_deferred();
2035 bool run_if_is_deferred() {
2036 return this->future_->run_if_is_deferred();
2038 bool run_if_is_deferred_or_ready() {
2039 return this->future_->run_if_is_deferred_or_ready();
2041 // retrieving the value
2042 move_dest_type get()
2044 if (this->future_.get() == 0)
2046 boost::throw_exception(future_uninitialized());
2048 unique_lock<boost::mutex> lk(this->future_->mutex);
2049 if (! this->future_->valid(lk))
2051 boost::throw_exception(future_uninitialized());
2053 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
2054 this->future_->invalidate(lk);
2056 return this->future_->get(lk);
2058 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
2060 if (this->future_.get() == 0)
2062 boost::throw_exception(future_uninitialized());
2064 unique_lock<boost::mutex> lk(this->future_->mutex);
2065 if (! this->future_->valid(lk))
2067 boost::throw_exception(future_uninitialized());
2069 this->future_->wait(lk, false);
2070 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
2071 this->future_->invalidate(lk);
2073 if (this->future_->has_value(lk)) return this->future_->get(lk);
2074 else return boost::move(v);
2077 move_dest_type get_or(R const& v) // EXTENSION
2079 if (this->future_.get() == 0)
2081 boost::throw_exception(future_uninitialized());
2083 unique_lock<boost::mutex> lk(this->future_->mutex);
2084 if (! this->future_->valid(lk))
2086 boost::throw_exception(future_uninitialized());
2088 this->future_->wait(lk, false);
2089 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
2090 this->future_->invalidate(lk);
2092 if (this->future_->has_value(lk)) return this->future_->get(lk);
2097 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2098 template<typename F>
2099 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2100 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2101 template<typename F>
2102 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2103 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2104 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2105 template<typename Ex, typename F>
2106 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2107 then(Ex &ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2111 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
2113 BOOST_THREAD_FUTURE<R2>
2114 unwrap(); // EXTENSION
2119 template <typename R>
2120 class shared_future : public detail::basic_future<R>
2122 typedef detail::basic_future<R> base_type;
2123 typedef typename base_type::future_ptr future_ptr;
2125 friend class detail::future_waiter;
2126 friend class promise<R>;
2128 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2129 template <typename, typename, typename>
2130 friend struct detail::future_async_continuation_shared_state;
2131 template <typename, typename, typename>
2132 friend struct detail::future_deferred_continuation_shared_state;
2134 template <class F, class Rp, class Fp>
2135 friend BOOST_THREAD_FUTURE<Rp>
2136 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);
2138 template <class F, class Rp, class Fp>
2139 friend BOOST_THREAD_FUTURE<Rp>
2140 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);
2142 template <class F, class Rp, class Fp>
2143 friend BOOST_THREAD_FUTURE<Rp>
2144 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);
2146 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2147 template <class> friend class packaged_task;// todo check if this works in windows
2149 friend class packaged_task<R>;
2151 shared_future(future_ptr a_future):
2156 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future)
2157 typedef R value_type; // EXTENSION
2159 shared_future(shared_future const& other):
2160 base_type(other.future_)
2163 typedef future_state::state state;
2165 BOOST_CONSTEXPR shared_future()
2168 shared_future(exceptional_ptr const& ex):
2173 shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other)
2175 this->future_ = other.future_;
2179 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
2180 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2183 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
2184 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2188 shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
2190 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2193 shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
2195 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2199 void swap(shared_future& other) BOOST_NOEXCEPT
2201 static_cast<base_type*>(this)->swap(other);
2203 bool run_if_is_deferred() {
2204 return this->future_->run_if_is_deferred();
2206 bool run_if_is_deferred_or_ready() {
2207 return this->future_->run_if_is_deferred_or_ready();
2209 // retrieving the value
2210 typename detail::shared_state<R>::shared_future_get_result_type get() const
2214 boost::throw_exception(future_uninitialized());
2216 return this->future_->get_sh();
2219 template <typename R2>
2220 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
2221 get_or(BOOST_THREAD_RV_REF(R2) v) const // EXTENSION
2225 boost::throw_exception(future_uninitialized());
2227 this->future_->wait();
2228 if (this->future_->has_value()) return this->future_->get_sh();
2229 else return boost::move(v);
2232 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2233 template<typename F>
2234 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2235 then(BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2236 template<typename F>
2237 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2238 then(launch policy, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2239 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2240 template<typename Ex, typename F>
2241 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2242 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2248 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
2250 template <typename R>
2253 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
2255 typedef typename detail::shared_state<R>::source_reference_type source_reference_type;
2256 typedef typename detail::shared_state<R>::rvalue_source_type rvalue_source_type;
2257 typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
2258 typedef typename detail::shared_state<R>::shared_future_get_result_type shared_future_get_result_type;
2261 bool future_obtained;
2265 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2266 #include <boost/thread/detail/atomic_undef_macros.hpp>
2267 if(!atomic_load(&future_))
2270 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
2272 #include <boost/thread/detail/atomic_redef_macros.hpp>
2277 BOOST_THREAD_MOVABLE_ONLY(promise)
2278 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2279 template <class Allocator>
2280 promise(boost::allocator_arg_t, Allocator a)
2282 typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2;
2284 typedef thread_detail::allocator_destructor<A2> D;
2286 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) );
2287 future_obtained = false;
2291 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2294 future_(new detail::shared_state<R>()),
2296 future_obtained(false)
2303 boost::unique_lock<boost::mutex> lock(future_->mutex);
2305 if(!future_->done && !future_->is_constructed)
2307 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2313 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2314 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2316 BOOST_THREAD_RV(rhs).future_.reset();
2317 BOOST_THREAD_RV(rhs).future_obtained=false;
2319 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2321 future_=BOOST_THREAD_RV(rhs).future_;
2322 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2323 BOOST_THREAD_RV(rhs).future_.reset();
2324 BOOST_THREAD_RV(rhs).future_obtained=false;
2328 void swap(promise& other)
2330 future_.swap(other.future_);
2331 std::swap(future_obtained,other.future_obtained);
2334 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2335 void set_executor(executor_ptr_type aex)
2338 if (future_.get()==0)
2340 boost::throw_exception(promise_moved());
2342 boost::lock_guard<boost::mutex> lk(future_->mutex);
2343 future_->set_executor_policy(aex, lk);
2347 BOOST_THREAD_FUTURE<R> get_future()
2350 if (future_.get()==0)
2352 boost::throw_exception(promise_moved());
2354 if (future_obtained)
2356 boost::throw_exception(future_already_retrieved());
2358 future_obtained=true;
2359 return BOOST_THREAD_FUTURE<R>(future_);
2362 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2364 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type
2365 set_value(TR const & r)
2368 boost::unique_lock<boost::mutex> lock(future_->mutex);
2371 boost::throw_exception(promise_already_satisfied());
2373 future_->mark_finished_with_result_internal(r, lock);
2376 void set_value(source_reference_type r)
2379 boost::unique_lock<boost::mutex> lock(future_->mutex);
2382 boost::throw_exception(promise_already_satisfied());
2384 future_->mark_finished_with_result_internal(r, lock);
2388 void set_value(rvalue_source_type r)
2391 boost::unique_lock<boost::mutex> lock(future_->mutex);
2394 boost::throw_exception(promise_already_satisfied());
2396 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2397 future_->mark_finished_with_result_internal(boost::move(r), lock);
2399 future_->mark_finished_with_result_internal(static_cast<rvalue_source_type>(r), lock);
2403 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2405 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type
2406 set_value_deferred(TR const & r)
2409 if (future_.get()==0)
2411 boost::throw_exception(promise_moved());
2413 future_->set_value_deferred(r);
2416 void set_value_deferred(source_reference_type r)
2419 if (future_.get()==0)
2421 boost::throw_exception(promise_moved());
2423 future_->set_value_deferred(r);
2427 void set_value_deferred(rvalue_source_type r)
2430 if (future_.get()==0)
2432 boost::throw_exception(promise_moved());
2434 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2435 future_->set_value_deferred(boost::move(r));
2437 future_->set_value_deferred(static_cast<rvalue_source_type>(r));
2441 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
2442 template <class ...Args>
2443 void emplace(BOOST_THREAD_FWD_REF(Args) ...args)
2446 boost::unique_lock<boost::mutex> lock(future_->mutex);
2449 boost::throw_exception(promise_already_satisfied());
2451 future_->mark_finished_with_result_internal(lock, boost::forward<Args>(args)...);
2456 void set_exception(boost::exception_ptr p)
2459 boost::unique_lock<boost::mutex> lock(future_->mutex);
2462 boost::throw_exception(promise_already_satisfied());
2464 future_->mark_exceptional_finish_internal(p, lock);
2466 template <typename E>
2467 void set_exception(E ex)
2469 set_exception(boost::copy_exception(ex));
2471 void set_exception_deferred(boost::exception_ptr p)
2474 if (future_.get()==0)
2476 boost::throw_exception(promise_moved());
2478 future_->set_exception_deferred(p);
2480 template <typename E>
2481 void set_exception_deferred(E ex)
2483 set_exception_deferred(boost::copy_exception(ex));
2486 // setting the result with deferred notification
2487 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2489 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)
2491 if (future_.get()==0)
2493 boost::throw_exception(promise_moved());
2495 future_->set_value_at_thread_exit(r);
2498 void set_value_at_thread_exit(source_reference_type r)
2500 if (future_.get()==0)
2502 boost::throw_exception(promise_moved());
2504 future_->set_value_at_thread_exit(r);
2507 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
2509 if (future_.get()==0)
2511 boost::throw_exception(promise_moved());
2513 future_->set_value_at_thread_exit(boost::move(r));
2515 void set_exception_at_thread_exit(exception_ptr e)
2517 if (future_.get()==0)
2519 boost::throw_exception(promise_moved());
2521 future_->set_exception_at_thread_exit(e);
2523 template <typename E>
2524 void set_exception_at_thread_exit(E ex)
2526 set_exception_at_thread_exit(boost::copy_exception(ex));
2529 template<typename F>
2530 void set_wait_callback(F f)
2533 future_->set_wait_callback(f,this);
2535 void notify_deferred()
2537 if (future_.get()==0)
2539 boost::throw_exception(promise_moved());
2541 future_->notify_deferred();
2546 template <typename R>
2549 typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr;
2552 bool future_obtained;
2556 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2557 #include <boost/thread/detail/atomic_undef_macros.hpp>
2558 if(!atomic_load(&future_))
2561 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
2563 #include <boost/thread/detail/atomic_redef_macros.hpp>
2568 BOOST_THREAD_MOVABLE_ONLY(promise)
2569 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2570 template <class Allocator>
2571 promise(boost::allocator_arg_t, Allocator a)
2573 typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2;
2575 typedef thread_detail::allocator_destructor<A2> D;
2577 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
2578 future_obtained = false;
2582 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2585 future_(new detail::shared_state<R&>()),
2587 future_obtained(false)
2594 boost::unique_lock<boost::mutex> lock(future_->mutex);
2596 if(!future_->done && !future_->is_constructed)
2598 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2604 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2605 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2607 BOOST_THREAD_RV(rhs).future_.reset();
2608 BOOST_THREAD_RV(rhs).future_obtained=false;
2610 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2612 future_=BOOST_THREAD_RV(rhs).future_;
2613 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2614 BOOST_THREAD_RV(rhs).future_.reset();
2615 BOOST_THREAD_RV(rhs).future_obtained=false;
2619 void swap(promise& other)
2621 future_.swap(other.future_);
2622 std::swap(future_obtained,other.future_obtained);
2626 BOOST_THREAD_FUTURE<R&> get_future()
2629 if (future_.get()==0)
2631 boost::throw_exception(promise_moved());
2633 if (future_obtained)
2635 boost::throw_exception(future_already_retrieved());
2637 future_obtained=true;
2638 return BOOST_THREAD_FUTURE<R&>(future_);
2641 void set_value(R& r)
2644 boost::unique_lock<boost::mutex> lock(future_->mutex);
2647 boost::throw_exception(promise_already_satisfied());
2649 future_->mark_finished_with_result_internal(r, lock);
2651 void set_value_deferred(R& r)
2654 if (future_.get()==0)
2656 boost::throw_exception(promise_already_satisfied());
2658 future_->set_value_deferred(r);
2660 void set_exception(boost::exception_ptr p)
2663 boost::unique_lock<boost::mutex> lock(future_->mutex);
2666 boost::throw_exception(promise_already_satisfied());
2668 future_->mark_exceptional_finish_internal(p, lock);
2670 template <typename E>
2671 void set_exception(E ex)
2673 set_exception(boost::copy_exception(ex));
2675 void set_exception_deferred(boost::exception_ptr p)
2678 if (future_.get()==0)
2680 boost::throw_exception(promise_moved());
2682 future_->set_exception_deferred(p);
2684 template <typename E>
2685 void set_exception_deferred(E ex)
2687 set_exception_deferred(boost::copy_exception(ex));
2689 // setting the result with deferred notification
2690 void set_value_at_thread_exit(R& r)
2692 if (future_.get()==0)
2694 boost::throw_exception(promise_moved());
2696 future_->set_value_at_thread_exit(r);
2699 void set_exception_at_thread_exit(exception_ptr e)
2701 if (future_.get()==0)
2703 boost::throw_exception(promise_moved());
2705 future_->set_exception_at_thread_exit(e);
2707 template <typename E>
2708 void set_exception_at_thread_exit(E ex)
2710 set_exception_at_thread_exit(boost::copy_exception(ex));
2713 template<typename F>
2714 void set_wait_callback(F f)
2717 future_->set_wait_callback(f,this);
2719 void notify_deferred()
2721 if (future_.get()==0)
2723 boost::throw_exception(promise_moved());
2725 future_->notify_deferred();
2732 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr;
2735 bool future_obtained;
2739 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2740 if(!atomic_load(&future_))
2743 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>));
2748 BOOST_THREAD_MOVABLE_ONLY(promise)
2750 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2751 template <class Allocator>
2752 promise(boost::allocator_arg_t, Allocator a)
2754 typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2;
2756 typedef thread_detail::allocator_destructor<A2> D;
2758 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
2759 future_obtained = false;
2763 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2766 future_(new detail::shared_state<void>),
2768 future_obtained(false)
2775 boost::unique_lock<boost::mutex> lock(future_->mutex);
2777 if(!future_->done && !future_->is_constructed)
2779 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2785 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2786 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2788 // we need to release the future as shared_ptr doesn't implements move semantics
2789 BOOST_THREAD_RV(rhs).future_.reset();
2790 BOOST_THREAD_RV(rhs).future_obtained=false;
2793 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2795 future_=BOOST_THREAD_RV(rhs).future_;
2796 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2797 BOOST_THREAD_RV(rhs).future_.reset();
2798 BOOST_THREAD_RV(rhs).future_obtained=false;
2802 void swap(promise& other)
2804 future_.swap(other.future_);
2805 std::swap(future_obtained,other.future_obtained);
2809 BOOST_THREAD_FUTURE<void> get_future()
2813 if (future_.get()==0)
2815 boost::throw_exception(promise_moved());
2819 boost::throw_exception(future_already_retrieved());
2821 future_obtained=true;
2822 //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<void>(future_));
2823 return BOOST_THREAD_FUTURE<void>(future_);
2829 boost::unique_lock<boost::mutex> lock(future_->mutex);
2832 boost::throw_exception(promise_already_satisfied());
2834 future_->mark_finished_with_result_internal(lock);
2836 void set_value_deferred()
2839 if (future_.get()==0)
2841 boost::throw_exception(promise_moved());
2843 future_->set_value_deferred();
2846 void set_exception(boost::exception_ptr p)
2849 boost::unique_lock<boost::mutex> lock(future_->mutex);
2852 boost::throw_exception(promise_already_satisfied());
2854 future_->mark_exceptional_finish_internal(p,lock);
2856 template <typename E>
2857 void set_exception(E ex)
2859 set_exception(boost::copy_exception(ex));
2861 void set_exception_deferred(boost::exception_ptr p)
2864 if (future_.get()==0)
2866 boost::throw_exception(promise_moved());
2868 future_->set_exception_deferred(p);
2870 template <typename E>
2871 void set_exception_deferred(E ex)
2873 set_exception_deferred(boost::copy_exception(ex));
2875 // setting the result with deferred notification
2876 void set_value_at_thread_exit()
2878 if (future_.get()==0)
2880 boost::throw_exception(promise_moved());
2882 future_->set_value_at_thread_exit();
2885 void set_exception_at_thread_exit(exception_ptr e)
2887 if (future_.get()==0)
2889 boost::throw_exception(promise_moved());
2891 future_->set_exception_at_thread_exit(e);
2893 template <typename E>
2894 void set_exception_at_thread_exit(E ex)
2896 set_exception_at_thread_exit(boost::copy_exception(ex));
2899 template<typename F>
2900 void set_wait_callback(F f)
2903 future_->set_wait_callback(f,this);
2905 void notify_deferred()
2907 if (future_.get()==0)
2909 boost::throw_exception(promise_moved());
2911 future_->notify_deferred();
2915 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2916 namespace boost { namespace container {
2917 template <class R, class Alloc>
2918 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
2922 #if ! defined BOOST_NO_CXX11_ALLOCATOR
2924 template <class R, class Alloc>
2925 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
2935 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
2939 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2940 template<typename R>
2941 struct task_base_shared_state;
2942 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2943 template<typename R, typename ...ArgTypes>
2944 struct task_base_shared_state<R(ArgTypes...)>:
2946 template<typename R>
2947 struct task_base_shared_state<R()>:
2950 template<typename R>
2951 struct task_base_shared_state:
2953 detail::shared_state<R>
2957 task_base_shared_state():
2963 // todo The packaged_task::reset must be as if an assignemnt froma new packaged_task with the same function
2964 // the reset function is an optimization that avoids reallocating a new task.
2968 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2969 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2970 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2972 virtual void do_run()=0;
2977 boost::lock_guard<boost::mutex> lk(this->mutex);
2980 boost::throw_exception(task_already_started());
2984 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2985 do_run(boost::move(args)...);
2991 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2992 virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2993 void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2995 virtual void do_apply()=0;
3000 boost::lock_guard<boost::mutex> lk(this->mutex);
3003 boost::throw_exception(task_already_started());
3007 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3008 do_apply(boost::move(args)...);
3014 void owner_destroyed()
3016 boost::unique_lock<boost::mutex> lk(this->mutex);
3020 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
3025 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3026 template<typename F, typename R>
3027 struct task_shared_state;
3028 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3029 template<typename F, typename R, typename ...ArgTypes>
3030 struct task_shared_state<F, R(ArgTypes...)>:
3031 task_base_shared_state<R(ArgTypes...)>
3033 template<typename F, typename R>
3034 struct task_shared_state<F, R()>:
3035 task_base_shared_state<R()>
3038 template<typename F, typename R>
3039 struct task_shared_state:
3040 task_base_shared_state<R>
3044 task_shared_state(task_shared_state&);
3047 task_shared_state(F const& f_):
3050 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
3056 return boost::move(f);
3059 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3060 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3064 this->set_value_at_thread_exit(f(boost::move(args)...));
3071 this->set_value_at_thread_exit(f());
3076 this->set_exception_at_thread_exit(current_exception());
3080 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3081 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3085 this->mark_finished_with_result(f(boost::move(args)...));
3092 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3094 this->mark_finished_with_result(boost::move(res));
3096 this->mark_finished_with_result(f());
3102 this->mark_exceptional_finish();
3107 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3108 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3109 template<typename F, typename R, typename ...ArgTypes>
3110 struct task_shared_state<F, R&(ArgTypes...)>:
3111 task_base_shared_state<R&(ArgTypes...)>
3113 template<typename F, typename R>
3114 struct task_shared_state<F, R&()>:
3115 task_base_shared_state<R&()>
3118 template<typename F, typename R>
3119 struct task_shared_state<F,R&>:
3120 task_base_shared_state<R&>
3124 task_shared_state(task_shared_state&);
3127 task_shared_state(F const& f_):
3130 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
3139 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3140 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3144 this->set_value_at_thread_exit(f(boost::move(args)...));
3151 this->set_value_at_thread_exit(f());
3156 this->set_exception_at_thread_exit(current_exception());
3160 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3161 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3165 this->mark_finished_with_result(f(boost::move(args)...));
3173 this->mark_finished_with_result(res);
3178 this->mark_exceptional_finish();
3183 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
3185 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3186 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3187 template<typename R, typename ...ArgTypes>
3188 struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>:
3189 task_base_shared_state<R(ArgTypes...)>
3191 template<typename R>
3192 struct task_shared_state<R (*)(), R()>:
3193 task_base_shared_state<R()>
3196 template<typename R>
3197 struct task_shared_state<R (*)(), R> :
3198 task_base_shared_state<R>
3202 task_shared_state(task_shared_state&);
3203 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3204 typedef R (*CallableType)(ArgTypes ... );
3206 typedef R (*CallableType)();
3210 task_shared_state(CallableType f_):
3214 CallableType callable()
3219 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3220 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3224 this->set_value_at_thread_exit(f(boost::move(args)...));
3232 this->set_value_at_thread_exit(boost::move(r));
3237 this->set_exception_at_thread_exit(current_exception());
3242 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3243 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3247 this->mark_finished_with_result(f(boost::move(args)...));
3255 this->mark_finished_with_result(boost::move(res));
3260 this->mark_exceptional_finish();
3264 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3265 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3266 template<typename R, typename ...ArgTypes>
3267 struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>:
3268 task_base_shared_state<R&(ArgTypes...)>
3270 template<typename R>
3271 struct task_shared_state<R& (*)(), R&()>:
3272 task_base_shared_state<R&()>
3275 template<typename R>
3276 struct task_shared_state<R& (*)(), R&> :
3277 task_base_shared_state<R&>
3281 task_shared_state(task_shared_state&);
3283 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3284 typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... );
3286 typedef R& (*CallableType)();
3289 task_shared_state(CallableType f_):
3293 CallableType callable()
3295 return boost::move(f);
3298 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3299 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3303 this->set_value_at_thread_exit(f(boost::move(args)...));
3310 this->set_value_at_thread_exit(f());
3315 this->set_exception_at_thread_exit(current_exception());
3320 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3321 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3325 this->mark_finished_with_result(f(boost::move(args)...));
3332 this->mark_finished_with_result(f());
3337 this->mark_exceptional_finish();
3342 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3343 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3344 template<typename F, typename ...ArgTypes>
3345 struct task_shared_state<F, void(ArgTypes...)>:
3346 task_base_shared_state<void(ArgTypes...)>
3348 template<typename F>
3349 struct task_shared_state<F, void()>:
3350 task_base_shared_state<void()>
3353 template<typename F>
3354 struct task_shared_state<F,void>:
3355 task_base_shared_state<void>
3359 task_shared_state(task_shared_state&);
3361 typedef F CallableType;
3363 task_shared_state(F const& f_):
3366 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
3371 return boost::move(f);
3373 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3374 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3378 f(boost::move(args)...);
3386 this->set_value_at_thread_exit();
3390 this->set_exception_at_thread_exit(current_exception());
3394 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3395 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3399 f(boost::move(args)...);
3407 this->mark_finished_with_result();
3411 this->mark_exceptional_finish();
3416 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3417 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3418 template<typename ...ArgTypes>
3419 struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>:
3420 task_base_shared_state<void(ArgTypes...)>
3423 struct task_shared_state<void (*)(), void()>:
3424 task_base_shared_state<void()>
3428 struct task_shared_state<void (*)(),void>:
3429 task_base_shared_state<void>
3433 task_shared_state(task_shared_state&);
3434 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3435 typedef void (*CallableType)(ArgTypes...);
3437 typedef void (*CallableType)();
3441 task_shared_state(CallableType f_):
3444 CallableType callable()
3448 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3449 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3453 f(boost::move(args)...);
3461 this->set_value_at_thread_exit();
3465 this->set_exception_at_thread_exit(current_exception());
3469 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3470 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3474 f(boost::move(args)...);
3482 this->mark_finished_with_result();
3486 this->mark_exceptional_finish();
3492 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3493 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3494 template<typename R, typename ...ArgTypes>
3495 class packaged_task<R(ArgTypes...)>
3497 typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr;
3498 boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task;
3500 template<typename R>
3501 class packaged_task<R()>
3503 typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr;
3504 boost::shared_ptr<detail::task_base_shared_state<R()> > task;
3507 template<typename R>
3510 typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr;
3511 boost::shared_ptr<detail::task_base_shared_state<R> > task;
3513 bool future_obtained;
3517 typedef R result_type;
3518 BOOST_THREAD_MOVABLE_ONLY(packaged_task)
3521 future_obtained(false)
3524 // construction and destruction
3525 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
3527 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3528 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3529 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
3531 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3532 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3533 task= task_ptr(new task_shared_state_type(f, boost::move(args)...));
3534 future_obtained=false;
3537 explicit packaged_task(R(*f)())
3540 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3541 task= task_ptr(new task_shared_state_type(f));
3542 future_obtained=false;
3546 explicit packaged_task(R(*f)())
3549 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3550 task= task_ptr(new task_shared_state_type(f));
3551 future_obtained=false;
3555 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
3557 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
3558 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3561 typedef typename decay<F>::type FR;
3562 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3563 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3564 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3566 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3569 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3571 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
3572 future_obtained = false;
3578 explicit packaged_task(F const& f
3579 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3582 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3583 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3584 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3586 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3589 typedef detail::task_shared_state<F,R> task_shared_state_type;
3591 task = task_ptr(new task_shared_state_type(f));
3592 future_obtained=false;
3595 explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
3597 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3598 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3599 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3600 task = task_ptr(new task_shared_state_type(boost::move(f)));
3602 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3603 task = task_ptr(new task_shared_state_type(boost::move(f)));
3606 typedef detail::task_shared_state<F,R> task_shared_state_type;
3607 task = task_ptr(new task_shared_state_type(boost::move(f)));
3609 future_obtained=false;
3614 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3615 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
3616 template <class Allocator>
3617 packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
3620 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3621 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3622 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3624 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3627 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3629 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3631 typedef thread_detail::allocator_destructor<A2> D;
3633 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3634 future_obtained = false;
3636 #endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
3638 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3639 template <class F, class Allocator>
3640 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
3642 typedef typename decay<F>::type FR;
3644 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3645 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3646 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3648 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3651 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3653 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3655 typedef thread_detail::allocator_destructor<A2> D;
3657 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
3658 future_obtained = false;
3660 #else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3661 template <class F, class Allocator>
3662 packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
3664 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3665 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3666 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3668 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3671 typedef detail::task_shared_state<F,R> task_shared_state_type;
3673 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3675 typedef thread_detail::allocator_destructor<A2> D;
3677 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3678 future_obtained = false;
3680 template <class F, class Allocator>
3681 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
3683 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3684 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3685 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3687 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3690 typedef detail::task_shared_state<F,R> task_shared_state_type;
3692 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3694 typedef thread_detail::allocator_destructor<A2> D;
3696 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) );
3697 future_obtained = false;
3700 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
3701 #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3705 task->owner_destroyed();
3710 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
3711 : future_obtained(BOOST_THREAD_RV(other).future_obtained) {
3712 task.swap(BOOST_THREAD_RV(other).task);
3713 BOOST_THREAD_RV(other).future_obtained=false;
3715 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT {
3717 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3718 packaged_task temp(boost::move(other));
3720 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
3726 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
3727 void set_executor(executor_ptr_type aex)
3730 boost::throw_exception(task_moved());
3731 boost::lock_guard<boost::mutex> lk(task->mutex);
3732 task->set_executor_policy(aex, lk);
3737 boost::throw_exception(future_error(system::make_error_code(future_errc::no_state)));
3739 // As if *this = packaged_task(task->callable());
3742 future_obtained=false;
3745 void swap(packaged_task& other) BOOST_NOEXCEPT {
3746 task.swap(other.task);
3747 std::swap(future_obtained,other.future_obtained);
3749 bool valid() const BOOST_NOEXCEPT {
3750 return task.get()!=0;
3754 BOOST_THREAD_FUTURE<R> get_future() {
3756 boost::throw_exception(task_moved());
3757 } else if(!future_obtained) {
3758 future_obtained=true;
3759 return BOOST_THREAD_FUTURE<R>(task);
3761 boost::throw_exception(future_already_retrieved());
3766 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3767 void operator()(ArgTypes... args) {
3769 boost::throw_exception(task_moved());
3771 task->run(boost::move(args)...);
3773 void make_ready_at_thread_exit(ArgTypes... args) {
3775 boost::throw_exception(task_moved());
3777 if (task->has_value()) {
3778 boost::throw_exception(promise_already_satisfied());
3780 task->apply(boost::move(args)...);
3785 boost::throw_exception(task_moved());
3789 void make_ready_at_thread_exit() {
3791 boost::throw_exception(task_moved());
3793 if (task->has_value()) boost::throw_exception(promise_already_satisfied());
3797 template<typename F>
3798 void set_wait_callback(F f) {
3799 task->set_wait_callback(f,this);
3803 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3804 namespace boost { namespace container {
3805 template <class R, class Alloc>
3806 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
3809 #if ! defined BOOST_NO_CXX11_ALLOCATOR
3811 template <class R, class Alloc>
3812 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
3820 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
3824 ////////////////////////////////
3825 // make_future_deferred_shared_state
3826 ////////////////////////////////
3827 template <class Rp, class Fp>
3828 BOOST_THREAD_FUTURE<Rp>
3829 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
3830 shared_ptr<future_deferred_shared_state<Rp, Fp> >
3831 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
3832 return BOOST_THREAD_FUTURE<Rp>(h);
3835 ////////////////////////////////
3836 // make_future_async_shared_state
3837 ////////////////////////////////
3838 template <class Rp, class Fp>
3839 BOOST_THREAD_FUTURE<Rp>
3840 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
3841 shared_ptr<future_async_shared_state<Rp, Fp> >
3842 h(new future_async_shared_state<Rp, Fp>());
3843 h->init(boost::forward<Fp>(f));
3844 return BOOST_THREAD_FUTURE<Rp>(h);
3848 ////////////////////////////////
3849 // template <class F, class... ArgTypes>
3850 // future<R> async(launch policy, F&&, ArgTypes&&...);
3851 ////////////////////////////////
3853 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
3855 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3856 template <class R, class... ArgTypes>
3857 BOOST_THREAD_FUTURE<R>
3858 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3859 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3860 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3861 typedef typename BF::result_type Rp;
3863 if (underlying_cast<int>(policy) & int(launch::async)) {
3864 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3867 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3870 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3871 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3874 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3879 //BOOST_THREAD_FUTURE<R> ret;
3880 //return ::boost::move(ret);
3884 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3887 BOOST_THREAD_FUTURE<R>
3888 async(launch policy, R(*f)()) {
3889 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3890 typedef packaged_task<R()> packaged_task_type;
3892 typedef packaged_task<R> packaged_task_type;
3895 if (underlying_cast<int>(policy) & int(launch::async)) {
3896 packaged_task_type pt( f );
3897 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
3899 boost::thread( boost::move(pt) ).detach();
3900 return ::boost::move(ret);
3901 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3903 //BOOST_THREAD_FUTURE<R> ret;
3904 //return ::boost::move(ret);
3907 //BOOST_THREAD_FUTURE<R> ret;
3908 //return ::boost::move(ret);
3912 #endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
3914 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3916 template <class F, class ...ArgTypes>
3917 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3918 typename decay<ArgTypes>::type...
3920 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3921 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3922 typedef typename BF::result_type Rp;
3924 if (underlying_cast<int>(policy) & int(launch::async)) {
3925 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3927 thread_detail::decay_copy(boost::forward<F>(f))
3928 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3931 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3932 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3934 thread_detail::decay_copy(boost::forward<F>(f))
3935 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3940 //BOOST_THREAD_FUTURE<R> ret;
3941 //return ::boost::move(ret);
3945 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3948 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3949 async(launch policy, BOOST_THREAD_FWD_REF(F) f) {
3950 typedef typename boost::result_of<typename decay<F>::type()>::type R;
3951 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3952 typedef packaged_task<R()> packaged_task_type;
3953 #else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3954 typedef packaged_task<R> packaged_task_type;
3955 #endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3957 if (underlying_cast<int>(policy) & int(launch::async)) {
3958 packaged_task_type pt( boost::forward<F>(f) );
3959 BOOST_THREAD_FUTURE<R> ret = pt.get_future();
3961 boost::thread( boost::move(pt) ).detach();
3962 return ::boost::move(ret);
3963 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3965 //BOOST_THREAD_FUTURE<R> ret;
3966 //return ::boost::move(ret);
3967 // return boost::detail::make_future_deferred_shared_state<Rp>(
3969 // thread_detail::decay_copy(boost::forward<F>(f))
3974 //BOOST_THREAD_FUTURE<R> ret;
3975 //return ::boost::move(ret);
3978 #endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3980 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
3983 /////////////////////////
3984 /// shared_state_nullary_task
3985 /////////////////////////
3986 template<typename Rp, typename Fp>
3987 struct shared_state_nullary_task
3990 typedef shared_ptr<shared_state_base > storage_type;
3995 shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f)
3996 : that(st), f_(boost::move(f))
3999 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
4000 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
4001 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
4002 : that(x.that), f_(x.f_)
4004 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
4013 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
4014 : that(x.that), f_(boost::move(x.f_))
4018 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
4022 f_=boost::move(x.f_);
4029 shared_ptr<shared_state<Rp> > that_ = static_pointer_cast<shared_state<Rp> >(that);
4031 that_->mark_finished_with_result(f_());
4033 that_->mark_exceptional_finish();
4036 ~shared_state_nullary_task()
4041 template<typename Fp>
4042 struct shared_state_nullary_task<void, Fp>
4044 typedef shared_ptr<shared_state_base > storage_type;
4048 shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f)
4049 : that(st), f_(boost::move(f))
4052 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
4053 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
4054 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
4055 : that(x.that), f_(x.f_)
4057 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
4066 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT
4067 : that(x.that), f_(boost::move(x.f_))
4071 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
4074 f_=boost::move(x.f_);
4081 shared_ptr<shared_state<void> > that_ = static_pointer_cast<shared_state<void> >(that);
4084 that_->mark_finished_with_result();
4086 that_->mark_exceptional_finish();
4092 BOOST_THREAD_DCL_MOVABLE_BEG2(R,F) detail::shared_state_nullary_task<R,F> BOOST_THREAD_DCL_MOVABLE_END
4095 /////////////////////////
4096 /// future_executor_shared_state_base
4097 /////////////////////////
4098 template<typename Rp>
4099 struct future_executor_shared_state: shared_state<Rp>
4101 typedef shared_state<Rp> base_type;
4104 future_executor_shared_state() {
4107 template <class Fp, class Executor>
4108 void init(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f)
4110 typedef typename decay<Fp>::type Cont;
4111 this->set_executor_policy(executor_ptr_type(new executor_ref<Executor>(ex)));
4112 shared_state_nullary_task<Rp,Cont> t(this->shared_from_this(), boost::forward<Fp>(f));
4113 ex.submit(boost::move(t));
4116 ~future_executor_shared_state() {}
4119 ////////////////////////////////
4120 // make_future_executor_shared_state
4121 ////////////////////////////////
4122 template <class Rp, class Fp, class Executor>
4123 BOOST_THREAD_FUTURE<Rp>
4124 make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) {
4125 shared_ptr<future_executor_shared_state<Rp> >
4126 h(new future_executor_shared_state<Rp>());
4127 h->init(ex, boost::forward<Fp>(f));
4128 return BOOST_THREAD_FUTURE<Rp>(h);
4133 ////////////////////////////////
4134 // template <class Executor, class F, class... ArgTypes>
4135 // future<R> async(Executor& ex, F&&, ArgTypes&&...);
4136 ////////////////////////////////
4138 //#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4139 #if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
4141 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4143 template <class Executor, class R, class... ArgTypes>
4144 BOOST_THREAD_FUTURE<R>
4145 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4146 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
4147 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
4148 typedef typename BF::result_type Rp;
4150 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4153 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
4157 #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4159 template <class Executor, class F, class ...ArgTypes>
4160 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4161 typename decay<ArgTypes>::type...
4163 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4164 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
4165 typedef typename BF::result_type Rp;
4167 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4169 thread_detail::decay_copy(boost::forward<F>(f))
4170 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
4175 #else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4176 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4178 template <class Executor, class R>
4179 BOOST_THREAD_FUTURE<R>
4180 async(Executor& ex, R(*f)()) {
4182 typedef detail::invoker<F> BF;
4183 typedef typename BF::result_type Rp;
4185 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4192 template <class Executor, class R, class A1>
4193 BOOST_THREAD_FUTURE<R>
4194 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) {
4195 typedef R(*F)(BOOST_THREAD_FWD_REF(A1));
4196 typedef detail::invoker<F, typename decay<A1>::type> BF;
4197 typedef typename BF::result_type Rp;
4199 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4202 , thread_detail::decay_copy(boost::forward<A1>(a1))
4206 #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4208 template <class Executor, class F>
4209 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
4210 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) {
4211 typedef detail::invoker<typename decay<F>::type> BF;
4212 typedef typename BF::result_type Rp;
4214 return boost::detail::make_future_executor_shared_state<Rp>(ex,
4216 thread_detail::decay_copy(boost::forward<F>(f))
4221 template <class Executor, class F, class A1>
4222 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4223 typename decay<A1>::type
4225 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) {
4226 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type> BF;
4227 typedef typename BF::result_type Rp;
4229 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4231 thread_detail::decay_copy(boost::forward<F>(f))
4232 , thread_detail::decay_copy(boost::forward<A1>(a1))
4237 template <class Executor, class F, class A1, class A2>
4238 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4239 typename decay<A1>::type, typename decay<A2>::type
4241 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) {
4242 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type, typename decay<A2>::type> BF;
4243 typedef typename BF::result_type Rp;
4245 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4247 thread_detail::decay_copy(boost::forward<F>(f))
4248 , thread_detail::decay_copy(boost::forward<A1>(a1))
4249 , thread_detail::decay_copy(boost::forward<A2>(a2))
4254 #endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4257 ////////////////////////////////
4258 // template <class F, class... ArgTypes>
4259 // future<R> async(F&&, ArgTypes&&...);
4260 ////////////////////////////////
4262 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
4263 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
4264 template <class R, class... ArgTypes>
4265 BOOST_THREAD_FUTURE<R>
4266 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4267 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
4271 BOOST_THREAD_FUTURE<R>
4273 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
4278 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
4279 template <class F, class ...ArgTypes>
4280 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4281 typename decay<ArgTypes>::type...
4283 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4284 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
4288 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
4289 async(BOOST_THREAD_FWD_REF(F) f) {
4290 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
4294 ////////////////////////////////
4295 // make_future deprecated
4296 ////////////////////////////////
4297 template <typename T>
4298 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) {
4299 typedef typename decay<T>::type future_value_type;
4300 promise<future_value_type> p;
4301 p.set_value(boost::forward<future_value_type>(value));
4302 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4305 #if defined BOOST_THREAD_USES_MOVE
4306 inline BOOST_THREAD_FUTURE<void> make_future() {
4309 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4313 ////////////////////////////////
4314 // make_ready_future
4315 ////////////////////////////////
4318 struct deduced_type_impl
4324 struct deduced_type_impl<reference_wrapper<T> const>
4329 struct deduced_type_impl<reference_wrapper<T> >
4333 #if __cplusplus > 201103L
4335 struct deduced_type_impl<std::reference_wrapper<T> >
4343 typedef typename detail::deduced_type_impl<typename decay<T>::type>::type type;
4349 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4350 template <int = 0, int..., class T>
4354 BOOST_THREAD_FUTURE<typename detail::deduced_type<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) {
4355 typedef typename detail::deduced_type<T>::type future_value_type;
4356 promise<future_value_type> p;
4357 p.set_value(boost::forward<T>(value));
4358 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4361 // explicit overloads
4363 BOOST_THREAD_FUTURE<T> make_ready_future(typename remove_reference<T>::type & x)
4367 return p.get_future();
4371 BOOST_THREAD_FUTURE<T> make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference<T>::type) x)
4374 p.set_value(forward<typename remove_reference<T>::type>(x));
4375 return p.get_future();
4378 // variadic overload
4379 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4380 template <class T, class ...Args>
4381 BOOST_THREAD_FUTURE<T> make_ready_future(Args&&... args)
4384 p.emplace(forward<Args>(args)...);
4385 return p.get_future();
4390 template <typename T, typename T1>
4391 BOOST_THREAD_FUTURE<T> make_ready_no_decay_future(T1 value) {
4392 typedef T future_value_type;
4393 promise<future_value_type> p;
4395 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4398 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined BOOST_THREAD_USES_MOVE
4399 inline BOOST_THREAD_FUTURE<void> make_ready_future() {
4402 return p.get_future();
4407 template <typename T>
4408 BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) {
4410 p.set_exception(ex);
4411 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4414 template <typename T, typename E>
4415 BOOST_THREAD_FUTURE<T> make_exceptional_future(E ex) {
4417 p.set_exception(boost::copy_exception(ex));
4418 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4421 template <typename T>
4422 BOOST_THREAD_FUTURE<T> make_exceptional_future() {
4424 p.set_exception(boost::current_exception());
4425 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4427 template <typename T>
4428 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) {
4429 return make_exceptional_future<T>(ex);
4433 template<typename CLOSURE>
4434 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
4435 typedef decltype(closure()) T;
4438 p.set_value(closure());
4440 p.set_exception(std::current_exception());
4442 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4446 ////////////////////////////////
4447 // make_shared_future deprecated
4448 ////////////////////////////////
4449 template <typename T>
4450 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) {
4451 typedef typename decay<T>::type future_type;
4452 promise<future_type> p;
4453 p.set_value(boost::forward<T>(value));
4454 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
4457 inline shared_future<void> make_shared_future() {
4459 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
4462 ////////////////////////////////
4463 // detail::future_async_continuation_shared_state
4464 ////////////////////////////////
4465 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
4469 //////////////////////
4470 // detail::continuation_shared_state
4471 //////////////////////
4472 template<typename F, typename Rp, typename Fp, class ShSt=shared_state<Rp> >
4473 struct continuation_shared_state: ShSt
4479 continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4480 : parent(boost::move(f)),
4481 continuation(boost::move(c))
4485 void init(boost::unique_lock<boost::mutex> &lock)
4487 parent.future_->set_continuation_ptr(this->shared_from_this(), lock);
4492 this->mark_finished_with_result(this->continuation(boost::move(this->parent)));
4494 this->mark_exceptional_finish();
4496 // make sure parent is really cleared to prevent memory "leaks"
4500 void call(boost::unique_lock<boost::mutex>& lck) {
4502 relocker relock(lck);
4504 // neither continuation nor parent are protected by the lock - call() must only
4505 // be called once, and no one else must modify it.
4506 Rp res = this->continuation(boost::move(this->parent));
4508 // make sure parent is really cleared to prevent memory "leaks"
4513 this->mark_finished_with_result_internal(boost::move(res), lck);
4515 this->mark_exceptional_finish_internal(current_exception(), lck);
4517 // make sure parent is really cleared to prevent memory "leaks"
4518 relocker relock(lck);
4523 static void run(shared_ptr<boost::detail::shared_state_base> that_)
4525 continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get());
4529 ~continuation_shared_state() {}
4532 template<typename F, typename Fp, class ShSt>
4533 struct continuation_shared_state<F, void, Fp, ShSt>: ShSt
4539 continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4540 : parent(boost::move(f)),
4541 continuation(boost::move(c))
4545 void init(boost::unique_lock<boost::mutex> &lock)
4547 parent.future_->set_continuation_ptr(this->shared_from_this(), lock);
4553 this->continuation(boost::move(this->parent));
4554 this->mark_finished_with_result();
4556 this->mark_exceptional_finish();
4558 // make sure parent is really cleared to prevent memory "leaks"
4562 void call(boost::unique_lock<boost::mutex>& lck) {
4565 relocker relock(lck);
4566 // neither continuation nor parent are protected by the lock - call() must only
4567 // be called once, and no one else must modify it.
4568 this->continuation(boost::move(this->parent));
4570 // make sure parent is really cleared to prevent memory "leaks"
4573 this->mark_finished_with_result_internal(lck);
4575 this->mark_exceptional_finish_internal(current_exception(), lck);
4577 // make sure parent is really cleared to prevent memory "leaks"
4578 relocker relock(lck);
4583 static void run(shared_ptr<boost::detail::shared_state_base> that_)
4585 continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get());
4589 ~continuation_shared_state() {}
4591 /////////////////////////
4592 /// future_async_continuation_shared_state
4593 /////////////////////////
4595 template<typename F, typename Rp, typename Fp>
4596 struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
4598 typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
4600 future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4601 : base_type(boost::move(f), boost::forward<Fp>(c))
4604 void launch_continuation() {
4605 #if defined BOOST_THREAD_FUTURE_BLOCKING
4606 boost::lock_guard<boost::mutex> lk(this->mutex);
4607 this->thr_ = boost::thread(&future_async_continuation_shared_state::run, static_shared_from_this(this));
4609 boost::thread(&base_type::run, static_shared_from_this(this)).detach();
4614 /////////////////////////
4615 /// future_sync_continuation_shared_state
4616 /////////////////////////
4618 template<typename F, typename Rp, typename Fp>
4619 struct future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
4621 typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
4623 future_sync_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4624 : base_type(boost::move(f), boost::forward<Fp>(c))
4627 void launch_continuation() {
4633 /////////////////////////
4634 /// future_executor_continuation_shared_state
4635 /////////////////////////
4636 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4638 template <typename FutureExecutorContinuationSharedState>
4640 shared_ptr<FutureExecutorContinuationSharedState> that_;
4642 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
4643 BOOST_THREAD_COPYABLE_AND_MOVABLE(run_it)
4644 run_it(run_it const& x) //BOOST_NOEXCEPT
4647 run_it& operator=(BOOST_THREAD_COPY_ASSIGN_REF(run_it) x) //BOOST_NOEXCEPT
4655 run_it(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT
4660 run_it& operator=(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT {
4668 run_it(shared_ptr<FutureExecutorContinuationSharedState> that) : that_ (that) {}
4677 BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::run_it<F> BOOST_THREAD_DCL_MOVABLE_END
4681 template<typename F, typename Rp, typename Fp>
4682 struct future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4684 typedef continuation_shared_state<F,Rp,Fp> base_type;
4687 future_executor_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4688 : base_type(boost::move(f), boost::forward<Fp>(c))
4693 void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
4695 this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
4696 this->base_type::init(lk);
4699 void launch_continuation() {
4700 run_it<base_type> fct(static_shared_from_this(this));
4701 this->get_executor()->submit(boost::move(fct));
4704 ~future_executor_continuation_shared_state() {}
4708 /////////////////////////
4709 /// shared_future_async_continuation_shared_state
4710 /////////////////////////
4712 template<typename F, typename Rp, typename Fp>
4713 struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
4715 typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
4718 shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4719 : base_type(boost::move(f), boost::forward<Fp>(c))
4723 void launch_continuation() {
4724 #if defined BOOST_THREAD_FUTURE_BLOCKING
4725 boost::lock_guard<boost::mutex> lk(this->mutex);
4726 this->thr_ = boost::thread(&base_type::run, static_shared_from_this(this));
4728 boost::thread(&base_type::run, static_shared_from_this(this)).detach();
4733 /////////////////////////
4734 /// shared_future_async_continuation_shared_state
4735 /////////////////////////
4737 template<typename F, typename Rp, typename Fp>
4738 struct shared_future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
4740 typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
4743 shared_future_sync_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4744 : base_type(boost::move(f), boost::forward<Fp>(c))
4748 void launch_continuation() {
4754 /////////////////////////
4755 /// shared_future_executor_continuation_shared_state
4756 /////////////////////////
4757 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4759 template<typename F, typename Rp, typename Fp>
4760 struct shared_future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4762 typedef continuation_shared_state<F,Rp,Fp> base_type;
4766 shared_future_executor_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4767 : base_type(boost::move(f), boost::forward<Fp>(c))
4772 void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
4774 this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
4775 this->base_type::init(lk);
4778 void launch_continuation() {
4779 run_it<base_type> fct(static_shared_from_this(this));
4780 this->get_executor()->submit(boost::move(fct));
4783 ~shared_future_executor_continuation_shared_state() {}
4787 //////////////////////////
4788 /// future_deferred_continuation_shared_state
4789 //////////////////////////
4790 template<typename F, typename Rp, typename Fp>
4791 struct future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4793 typedef continuation_shared_state<F,Rp,Fp> base_type;
4795 future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4796 : base_type(boost::move(f), boost::forward<Fp>(c))
4798 this->set_deferred();
4801 virtual void execute(boost::unique_lock<boost::mutex>& lk) {
4802 this->parent.wait();
4806 virtual void launch_continuation() { }
4809 //////////////////////////
4810 /// shared_future_deferred_continuation_shared_state
4811 //////////////////////////
4812 template<typename F, typename Rp, typename Fp>
4813 struct shared_future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4815 typedef continuation_shared_state<F,Rp,Fp> base_type;
4818 shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4819 : base_type(boost::move(f), boost::forward<Fp>(c))
4821 this->set_deferred();
4824 virtual void execute(boost::unique_lock<boost::mutex>& lk) {
4825 this->parent.wait();
4829 virtual void launch_continuation() { }
4832 ////////////////////////////////
4833 // make_future_deferred_continuation_shared_state
4834 ////////////////////////////////
4835 template<typename F, typename Rp, typename Fp>
4836 BOOST_THREAD_FUTURE<Rp>
4837 make_future_deferred_continuation_shared_state(
4838 boost::unique_lock<boost::mutex> &lock,
4839 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) {
4840 typedef typename decay<Fp>::type Cont;
4841 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Cont> >
4842 h(new future_deferred_continuation_shared_state<F, Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4844 return BOOST_THREAD_FUTURE<Rp>(h);
4847 ////////////////////////////////
4848 // make_future_async_continuation_shared_state
4849 ////////////////////////////////
4850 template<typename F, typename Rp, typename Fp>
4851 BOOST_THREAD_FUTURE<Rp>
4852 make_future_async_continuation_shared_state(
4853 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4854 BOOST_THREAD_FWD_REF(Fp) c) {
4855 typedef typename decay<Fp>::type Cont;
4856 shared_ptr<future_async_continuation_shared_state<F,Rp, Cont> >
4857 h(new future_async_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4860 return BOOST_THREAD_FUTURE<Rp>(h);
4862 ////////////////////////////////
4863 // make_future_sync_continuation_shared_state
4864 ////////////////////////////////
4865 template<typename F, typename Rp, typename Fp>
4866 BOOST_THREAD_FUTURE<Rp>
4867 make_future_sync_continuation_shared_state(
4868 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4869 BOOST_THREAD_FWD_REF(Fp) c) {
4870 typedef typename decay<Fp>::type Cont;
4871 shared_ptr<future_sync_continuation_shared_state<F,Rp, Cont> >
4872 h(new future_sync_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4875 return BOOST_THREAD_FUTURE<Rp>(h);
4878 ////////////////////////////////
4879 // make_future_executor_continuation_shared_state
4880 ////////////////////////////////
4881 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4883 template<typename Ex, typename F, typename Rp, typename Fp>
4884 BOOST_THREAD_FUTURE<Rp>
4885 make_future_executor_continuation_shared_state(Ex& ex,
4886 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4887 BOOST_THREAD_FWD_REF(Fp) c) {
4888 typedef typename decay<Fp>::type Cont;
4889 shared_ptr<future_executor_continuation_shared_state<F,Rp, Cont> >
4890 h(new future_executor_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4893 return BOOST_THREAD_FUTURE<Rp>(h);
4897 ////////////////////////////////
4898 // make_shared_future_deferred_continuation_shared_state
4899 ////////////////////////////////
4900 template<typename F, typename Rp, typename Fp>
4901 BOOST_THREAD_FUTURE<Rp>
4902 make_shared_future_deferred_continuation_shared_state(
4903 boost::unique_lock<boost::mutex> &lock,
4904 F f, BOOST_THREAD_FWD_REF(Fp) c) {
4905 typedef typename decay<Fp>::type Cont;
4906 shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Cont> >
4907 h(new shared_future_deferred_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c)));
4910 return BOOST_THREAD_FUTURE<Rp>(h);
4912 ////////////////////////////////
4913 // make_shared_future_async_continuation_shared_state
4914 ////////////////////////////////
4915 template<typename F, typename Rp, typename Fp>
4916 BOOST_THREAD_FUTURE<Rp>
4917 make_shared_future_async_continuation_shared_state(
4918 boost::unique_lock<boost::mutex> &lock, F f,
4919 BOOST_THREAD_FWD_REF(Fp) c) {
4920 typedef typename decay<Fp>::type Cont;
4921 shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Cont> >
4922 h(new shared_future_async_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
4925 return BOOST_THREAD_FUTURE<Rp>(h);
4927 ////////////////////////////////
4928 // make_shared_future_sync_continuation_shared_state
4929 ////////////////////////////////
4930 template<typename F, typename Rp, typename Fp>
4931 BOOST_THREAD_FUTURE<Rp>
4932 make_shared_future_sync_continuation_shared_state(
4933 boost::unique_lock<boost::mutex> &lock, F f,
4934 BOOST_THREAD_FWD_REF(Fp) c) {
4935 typedef typename decay<Fp>::type Cont;
4936 shared_ptr<shared_future_sync_continuation_shared_state<F,Rp, Cont> >
4937 h(new shared_future_sync_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
4940 return BOOST_THREAD_FUTURE<Rp>(h);
4942 ////////////////////////////////
4943 // make_shared_future_executor_continuation_shared_state
4944 ////////////////////////////////
4945 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4946 template<typename Ex, typename F, typename Rp, typename Fp>
4947 BOOST_THREAD_FUTURE<Rp>
4948 make_shared_future_executor_continuation_shared_state(Ex& ex,
4949 boost::unique_lock<boost::mutex> &lock, F f,
4950 BOOST_THREAD_FWD_REF(Fp) c) {
4951 typedef typename decay<Fp>::type Cont;
4952 shared_ptr<shared_future_executor_continuation_shared_state<F, Rp, Cont> >
4953 h(new shared_future_executor_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c)));
4956 return BOOST_THREAD_FUTURE<Rp>(h);
4961 ////////////////////////////////
4962 // template<typename F>
4963 // auto future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4964 ////////////////////////////////
4965 template <typename R>
4966 template <typename F>
4967 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
4968 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
4969 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4970 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
4972 // keep state alive as we move ourself but hold the lock
4973 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4974 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4976 if (underlying_cast<int>(policy) & int(launch::async)) {
4977 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4978 lock, boost::move(*this), boost::forward<F>(func)
4980 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
4981 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4982 lock, boost::move(*this), boost::forward<F>(func)
4984 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
4985 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4986 lock, boost::move(*this), boost::forward<F>(func)
4988 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4989 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
4990 assert(this->future_->get_executor());
4991 typedef executor Ex;
4992 Ex& ex = *(this->future_->get_executor());
4993 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4994 lock, boost::move(*this), boost::forward<F>(func)
4997 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
4999 launch policy_ = this->launch_policy(lock);
5000 if (underlying_cast<int>(policy_) & int(launch::async)) {
5001 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5002 lock, boost::move(*this), boost::forward<F>(func)
5004 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
5005 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5006 lock, boost::move(*this), boost::forward<F>(func)
5008 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
5009 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5010 lock, boost::move(*this), boost::forward<F>(func)
5012 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5013 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
5014 assert(this->future_->get_executor());
5015 typedef executor Ex;
5016 Ex& ex = *(this->future_->get_executor());
5017 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5018 lock, boost::move(*this), boost::forward<F>(func)
5022 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5023 lock, boost::move(*this), boost::forward<F>(func)
5027 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5028 lock, boost::move(*this), boost::forward<F>(func)
5032 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5033 ////////////////////////////////
5034 // template<typename Ex, typename F>
5035 // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5036 ////////////////////////////////
5037 template <typename R>
5038 template <typename Ex, typename F>
5039 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
5040 BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
5041 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5042 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5044 // keep state alive as we move ourself but hold the lock
5045 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5046 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5048 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5049 lock, boost::move(*this), boost::forward<F>(func)
5053 ////////////////////////////////
5054 // template<typename F>
5055 // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5056 ////////////////////////////////
5057 template <typename R>
5058 template <typename F>
5059 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
5060 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) {
5062 #ifndef BOOST_THREAD_CONTINUATION_SYNC
5063 return this->then(this->launch_policy(), boost::forward<F>(func));
5065 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5066 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5068 // keep state alive as we move ourself but hold the lock
5069 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5070 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5072 launch policy = this->launch_policy(lock);
5073 if (underlying_cast<int>(policy) & int(launch::deferred)) {
5074 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5075 lock, boost::move(*this), boost::forward<F>(func)
5078 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5079 lock, boost::move(*this), boost::forward<F>(func)
5086 ////////////////////////////////
5087 // template<typename F>
5088 // auto future<future<R2> >::then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5089 ////////////////////////////////
5090 template <typename R2>
5091 template <typename F>
5092 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
5093 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
5094 typedef BOOST_THREAD_FUTURE<R2> R;
5095 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5096 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5098 // keep state alive as we move ourself but hold the lock
5099 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5100 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5102 if (underlying_cast<int>(policy) & int(launch::async)) {
5103 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5104 lock, boost::move(*this), boost::forward<F>(func)
5106 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
5107 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5108 lock, boost::move(*this), boost::forward<F>(func)
5110 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
5111 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5112 lock, boost::move(*this), boost::forward<F>(func)
5114 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5115 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
5116 assert(this->future_->get_executor());
5117 typedef executor Ex;
5118 Ex& ex = *(this->future_->get_executor());
5119 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5120 lock, boost::move(*this), boost::forward<F>(func)
5123 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
5124 launch policy_ = this->launch_policy(lock);
5126 if (underlying_cast<int>(policy_) & int(launch::async)) {
5127 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5128 lock, boost::move(*this), boost::forward<F>(func)
5130 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
5131 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5132 lock, boost::move(*this), boost::forward<F>(func)
5134 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
5135 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5136 lock, boost::move(*this), boost::forward<F>(func)
5138 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5139 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
5140 assert(this->future_->get_executor());
5141 typedef executor Ex;
5142 Ex& ex = *(this->future_->get_executor());
5143 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5144 lock, boost::move(*this), boost::forward<F>(func)
5148 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5149 lock, boost::move(*this), boost::forward<F>(func)
5153 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5154 lock, boost::move(*this), boost::forward<F>(func)
5159 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5160 ////////////////////////////////
5161 // template<typename Ex, typename F>
5162 // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5163 ////////////////////////////////
5164 template <typename R2>
5165 template <typename Ex, typename F>
5166 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
5167 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
5168 typedef BOOST_THREAD_FUTURE<R2> R;
5169 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5170 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5172 // keep state alive as we move ourself but hold the lock
5173 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5174 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5176 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
5177 lock, boost::move(*this), boost::forward<F>(func)
5182 ////////////////////////////////
5183 // template<typename F>
5184 // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5185 ////////////////////////////////
5186 template <typename R2>
5187 template <typename F>
5188 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
5189 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) {
5191 #ifndef BOOST_THREAD_CONTINUATION_SYNC
5192 return this->then(this->launch_policy(), boost::forward<F>(func));
5194 typedef BOOST_THREAD_FUTURE<R2> R;
5195 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
5196 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5198 // keep state alive as we move ourself but hold the lock
5199 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5200 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5202 launch policy = this->launch_policy(lock);
5204 if (underlying_cast<int>(policy) & int(launch::deferred)) {
5205 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5206 lock, boost::move(*this), boost::forward<F>(func)
5209 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
5210 lock, boost::move(*this), boost::forward<F>(func)
5216 ////////////////////////////////
5217 // template<typename F>
5218 // auto shared_future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5219 ////////////////////////////////
5220 template <typename R>
5221 template <typename F>
5222 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5223 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const
5225 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5226 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5228 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5229 if (underlying_cast<int>(policy) & int(launch::async)) {
5230 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5231 lock, *this, boost::forward<F>(func)
5233 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
5234 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5235 lock, *this, boost::forward<F>(func)
5237 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
5238 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5239 lock, *this, boost::forward<F>(func)
5241 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5242 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
5243 typedef executor Ex;
5244 Ex& ex = *(this->future_->get_executor());
5245 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5246 lock, *this, boost::forward<F>(func)
5249 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
5251 launch policy_ = this->launch_policy(lock);
5252 if (underlying_cast<int>(policy_) & int(launch::async)) {
5253 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5254 lock, *this, boost::forward<F>(func)
5256 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
5257 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5258 lock, *this, boost::forward<F>(func)
5260 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
5261 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5262 lock, *this, boost::forward<F>(func)
5264 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5265 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
5266 typedef executor Ex;
5267 Ex& ex = *(this->future_->get_executor());
5268 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5269 lock, *this, boost::forward<F>(func)
5273 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5274 lock, *this, boost::forward<F>(func)
5279 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5280 lock, *this, boost::forward<F>(func)
5284 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5285 ////////////////////////////////
5286 // template<typename Ex, typename F>
5287 // auto shared_future<R>::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5288 ////////////////////////////////
5289 template <typename R>
5290 template <typename Ex, typename F>
5291 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5292 shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const
5294 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5295 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5297 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5298 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5299 lock, *this, boost::forward<F>(func)
5304 ////////////////////////////////
5305 // template<typename F>
5306 // auto shared_future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5307 ////////////////////////////////
5308 template <typename R>
5309 template <typename F>
5310 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5311 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const {
5312 #ifndef BOOST_THREAD_CONTINUATION_SYNC
5313 return this->then(this->launch_policy(), boost::forward<F>(func));
5315 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5316 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5318 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5319 launch policy = this->launch_policy(lock);
5320 if (underlying_cast<int>(policy) & int(launch::deferred)) {
5321 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5322 lock, *this, boost::forward<F>(func)
5325 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5326 lock, *this, boost::forward<F>(func)
5334 template <typename T>
5335 struct mfallbacker_to
5338 typedef T result_type;
5339 mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
5340 : value_(boost::move(v))
5343 T operator()(BOOST_THREAD_FUTURE<T> fut) {
5344 return fut.get_or(boost::move(value_));
5347 template <typename T>
5348 struct cfallbacker_to
5351 typedef T result_type;
5352 cfallbacker_to(T const& v)
5356 T operator()(BOOST_THREAD_FUTURE<T> fut) const {
5357 return fut.get_or(value_);
5362 ////////////////////////////////
5363 // future<R> future<R>::fallback_to(R&& v);
5364 ////////////////////////////////
5366 template <typename R>
5367 template <typename R2>
5368 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
5369 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) {
5370 return then(detail::mfallbacker_to<R>(boost::move(v)));
5373 template <typename R>
5374 template <typename R2>
5375 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
5376 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) {
5377 return then(detail::cfallbacker_to<R>(v));
5382 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
5385 /////////////////////////
5386 /// future_unwrap_shared_state
5387 /////////////////////////
5389 template<typename F, typename Rp>
5390 struct future_unwrap_shared_state: shared_state<Rp>
5393 typename F::value_type unwrapped;
5395 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
5396 : wrapped(boost::move(f)) {
5399 void launch_continuation()
5401 boost::unique_lock<boost::mutex> lk(this->mutex);
5402 // assert(wrapped.is_ready());
5403 if (! unwrapped.valid() )
5405 if (wrapped.has_exception()) {
5406 this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk);
5408 unwrapped = wrapped.get();
5409 if (unwrapped.valid())
5412 boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex);
5413 unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2);
5415 this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk);
5419 // assert(unwrapped.is_ready());
5420 if (unwrapped.has_exception()) {
5421 this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk);
5423 this->mark_finished_with_result_internal(unwrapped.get(), lk);
5429 template<typename F>
5430 struct future_unwrap_shared_state<F,void>: shared_state<void>
5433 typename F::value_type unwrapped;
5435 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
5436 : wrapped(boost::move(f)) {
5439 void launch_continuation()
5441 boost::unique_lock<boost::mutex> lk(this->mutex);
5442 // assert(wrapped.is_ready());
5443 if (! unwrapped.valid() )
5445 if (wrapped.has_exception()) {
5446 this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk);
5448 unwrapped = wrapped.get();
5449 if (unwrapped.valid())
5452 boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex);
5453 unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2);
5455 this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk);
5459 // assert(unwrapped.is_ready());
5460 if (unwrapped.has_exception()) {
5461 this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk);
5463 this->mark_finished_with_result_internal(lk);
5469 template <class F, class Rp>
5470 BOOST_THREAD_FUTURE<Rp>
5471 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) {
5472 shared_ptr<future_unwrap_shared_state<F, Rp> >
5473 h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
5474 h->wrapped.future_->set_continuation_ptr(h, lock);
5476 return BOOST_THREAD_FUTURE<Rp>(h);
5480 template <typename R>
5481 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other)
5482 : base_type(other.unwrap()) {}
5484 template <typename R2>
5485 BOOST_THREAD_FUTURE<R2>
5486 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
5488 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5490 // keep state alive as we move ourself but hold the lock
5491 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5492 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5494 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
5498 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
5501 struct input_iterator_tag {};
5502 struct vector_tag {};
5503 struct values_tag {};
5504 template <typename T>
5505 struct alias_t { typedef T type; };
5507 BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {};
5508 BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {};
5509 BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {};
5510 ////////////////////////////////
5511 // detail::future_async_when_all_shared_state
5512 ////////////////////////////////
5513 template<typename F>
5514 struct future_when_all_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
5516 typedef csbl::vector<F> vector_type;
5517 typedef typename F::value_type value_type;
5520 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
5521 future_when_all_vector_shared_state* that = static_cast<future_when_all_vector_shared_state*>(that_.get());
5523 boost::wait_for_all(that->vec_.begin(), that->vec_.end());
5524 that->mark_finished_with_result(boost::move(that->vec_));
5526 that->mark_exceptional_finish();
5529 bool run_deferred() {
5532 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
5533 if (! it->run_if_is_deferred())
5541 if (! run_deferred())
5543 future_when_all_vector_shared_state::run(this->shared_from_this());
5546 #ifdef BOOST_THREAD_FUTURE_BLOCKING
5547 this->thr_ = boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this());
5549 boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this()).detach();
5554 template< typename InputIterator>
5555 future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
5556 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
5560 future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
5561 : vec_(boost::move(v))
5565 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5566 template< typename T0, typename ...T>
5567 future_when_all_vector_shared_state(values_tag, BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5568 vec_.push_back(boost::forward<T0>(f));
5569 typename alias_t<char[]>::type{
5570 ( //first part of magic unpacker
5571 vec_.push_back(boost::forward<T>(futures)),'0'
5573 }; //second part of magic unpacker
5577 ~future_when_all_vector_shared_state() {}
5580 ////////////////////////////////
5581 // detail::future_async_when_any_shared_state
5582 ////////////////////////////////
5583 template<typename F>
5584 struct future_when_any_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
5586 typedef csbl::vector<F> vector_type;
5587 typedef typename F::value_type value_type;
5590 static void run(shared_ptr<boost::detail::shared_state_base> that_)
5592 future_when_any_vector_shared_state* that = static_cast<future_when_any_vector_shared_state*>(that_.get());
5594 boost::wait_for_any(that->vec_.begin(), that->vec_.end());
5595 that->mark_finished_with_result(boost::move(that->vec_));
5597 that->mark_exceptional_finish();
5600 bool run_deferred() {
5602 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
5603 if (it->run_if_is_deferred_or_ready())
5613 future_when_any_vector_shared_state::run(this->shared_from_this());
5617 #ifdef BOOST_THREAD_FUTURE_BLOCKING
5618 this->thr_ = boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this());
5620 boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this()).detach();
5625 template< typename InputIterator>
5626 future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
5627 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
5631 future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
5632 : vec_(boost::move(v))
5636 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5637 template< typename T0, typename ...T>
5638 future_when_any_vector_shared_state(values_tag,
5639 BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures
5641 vec_.push_back(boost::forward<T0>(f));
5642 typename alias_t<char[]>::type{
5643 ( //first part of magic unpacker
5644 vec_.push_back(boost::forward<T>(futures))
5648 }; //second part of magic unpacker
5652 ~future_when_any_vector_shared_state() {}
5655 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5656 struct wait_for_all_fctr {
5657 template <class ...T>
5658 void operator()(T&&... v) {
5659 boost::wait_for_all(boost::forward<T>(v)...);
5663 struct wait_for_any_fctr {
5664 template <class ...T>
5665 void operator()(T&&... v) {
5666 boost::wait_for_any(boost::forward<T>(v)...);
5671 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
5672 struct accumulate_run_if_is_deferred {
5673 bool operator ()(Tuple& t)
5675 return (! csbl::get<i-1>(t).run_if_is_deferred()) || accumulate_run_if_is_deferred<Tuple,i-1>()(t);
5678 template <class Tuple>
5679 struct accumulate_run_if_is_deferred<Tuple, 0> {
5680 bool operator ()(Tuple& )
5687 template< typename Tuple, typename T0, typename ...T>
5688 struct future_when_all_tuple_shared_state: future_async_shared_state_base<Tuple>
5691 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
5693 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
5694 future_when_all_tuple_shared_state* that = static_cast<future_when_all_tuple_shared_state*>(that_.get());
5696 // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor());
5697 that->wait_for_all(Index());
5699 that->mark_finished_with_result(boost::move(that->tup_));
5701 that->mark_exceptional_finish();
5705 template <size_t ...Indices>
5706 void wait_for_all(tuple_indices<Indices...>) {
5707 #if defined BOOST_THREAD_PROVIDES_INVOKE
5708 return invoke<void>(wait_for_all_fctr(), csbl::get<Indices>(tup_)...);
5710 return wait_for_all_fctr()(csbl::get<Indices>(tup_)...);
5714 bool run_deferred() {
5716 return accumulate_run_if_is_deferred<Tuple>()(tup_);
5719 if (! run_deferred())
5721 future_when_all_tuple_shared_state::run(this->shared_from_this());
5724 #ifdef BOOST_THREAD_FUTURE_BLOCKING
5725 this->thr_ = boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this());
5727 boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()).detach();
5732 template< typename F, typename ...Fs>
5733 future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) :
5734 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
5738 ~future_when_all_tuple_shared_state() {}
5743 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
5744 struct apply_any_run_if_is_deferred_or_ready {
5745 bool operator ()(Tuple& t)
5747 if (csbl::get<i-1>(t).run_if_is_deferred_or_ready()) return true;
5748 return apply_any_run_if_is_deferred_or_ready<Tuple,i-1>()(t);
5751 template <class Tuple>
5752 struct apply_any_run_if_is_deferred_or_ready<Tuple, 0> {
5753 bool operator ()(Tuple& )
5759 template< typename Tuple, typename T0, typename ...T >
5760 struct future_when_any_tuple_shared_state: future_async_shared_state_base<Tuple>
5763 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
5765 static void run(shared_ptr<boost::detail::shared_state_base> that_)
5767 future_when_any_tuple_shared_state* that = static_cast<future_when_any_tuple_shared_state*>(that_.get());
5769 // TODO make use of apply(that->tup_, wait_for_any_fctr);
5770 that->wait_for_any(Index());
5772 that->mark_finished_with_result(boost::move(that->tup_));
5774 that->mark_exceptional_finish();
5777 template <size_t ...Indices>
5778 void wait_for_any(tuple_indices<Indices...>) {
5779 #if defined BOOST_THREAD_PROVIDES_INVOKE
5780 return invoke<void>(wait_for_any_fctr(), csbl::get<Indices>(tup_)...);
5782 return wait_for_any_fctr()(csbl::get<Indices>(tup_)...);
5785 bool run_deferred() {
5786 return apply_any_run_if_is_deferred_or_ready<Tuple>()(tup_);
5791 future_when_any_tuple_shared_state::run(this->shared_from_this());
5795 #ifdef BOOST_THREAD_FUTURE_BLOCKING
5796 this->thr_ = boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this());
5798 boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()).detach();
5803 template< typename F, typename ...Fs>
5804 future_when_any_tuple_shared_state(values_tag,
5805 BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures
5807 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
5811 ~future_when_any_tuple_shared_state() {}
5817 template< typename InputIterator>
5818 typename boost::disable_if<is_future_type<InputIterator>,
5819 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
5821 when_all(InputIterator first, InputIterator last) {
5822 typedef typename InputIterator::value_type value_type;
5823 typedef csbl::vector<value_type> container_type;
5824 typedef detail::future_when_all_vector_shared_state<value_type> factory_type;
5826 if (first==last) return make_ready_future(container_type());
5827 shared_ptr<factory_type >
5828 h(new factory_type(detail::input_iterator_tag_value, first,last));
5830 return BOOST_THREAD_FUTURE<container_type>(h);
5833 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all() {
5834 return make_ready_future(csbl::tuple<>());
5837 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5838 template< typename T0, typename ...T>
5839 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
5840 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5841 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
5842 typedef detail::future_when_all_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
5844 shared_ptr<factory_type>
5845 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
5847 return BOOST_THREAD_FUTURE<container_type>(h);
5851 template< typename InputIterator>
5852 typename boost::disable_if<is_future_type<InputIterator>,
5853 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
5855 when_any(InputIterator first, InputIterator last) {
5856 typedef typename InputIterator::value_type value_type;
5857 typedef csbl::vector<value_type> container_type;
5858 typedef detail::future_when_any_vector_shared_state<value_type> factory_type;
5860 if (first==last) return make_ready_future(container_type());
5861 shared_ptr<factory_type >
5862 h(new factory_type(detail::input_iterator_tag_value, first,last));
5864 return BOOST_THREAD_FUTURE<container_type>(h);
5867 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any() {
5868 return make_ready_future(csbl::tuple<>());
5871 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5872 template< typename T0, typename ...T>
5873 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
5874 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5875 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
5876 typedef detail::future_when_any_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
5878 shared_ptr<factory_type>
5879 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
5881 return BOOST_THREAD_FUTURE<container_type>(h);
5884 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
5887 #endif // BOOST_NO_EXCEPTIONS