1// (C) Copyright 2008-10 Anthony Williams
2// (C) Copyright 2011-2015 Vicente J. Botet Escriba
3//
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)
7
8#ifndef BOOST_THREAD_FUTURE_HPP
9#define BOOST_THREAD_FUTURE_HPP
10
11#include <boost/thread/detail/config.hpp>
12
13// boost::thread::future requires exception handling
14// due to boost::exception::exception_ptr dependency
15
16//#define BOOST_THREAD_CONTINUATION_SYNC
17
18#ifndef BOOST_NO_EXCEPTIONS
19
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>
40
41#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
42#include <boost/optional.hpp>
43#else
44#include <boost/thread/csbl/memory/unique_ptr.hpp>
45#endif
46
47#include <boost/assert.hpp>
48#include <boost/bind.hpp>
49#ifdef BOOST_THREAD_USES_CHRONO
50#include <boost/chrono/system_clocks.hpp>
51#endif
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>
68
69
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
74#include <memory>
75#endif
76#endif
77
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>
81#endif
82
83#include <algorithm>
84#include <list>
85#include <vector>
86#include <utility>
87
88#if defined BOOST_THREAD_PROVIDES_FUTURE
89#define BOOST_THREAD_FUTURE future
90#else
91#define BOOST_THREAD_FUTURE unique_future
92#endif
93
94namespace boost
95{
96 template <class T>
97 shared_ptr<T> static_shared_from_this(T* that)
98 {
99 return static_pointer_cast<T>(that->shared_from_this());
100 }
101 template <class T>
102 shared_ptr<T const> static_shared_from_this(T const* that)
103 {
104 return static_pointer_cast<T const>(that->shared_from_this());
105 }
106
107#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
108#else
109 namespace executors {
110 class executor;
111 }
112#endif
113 typedef shared_ptr<executor> executor_ptr_type;
114
115 namespace detail
116 {
117
118 struct relocker
119 {
120 boost::unique_lock<boost::mutex>& lock_;
121
122 relocker(boost::unique_lock<boost::mutex>& lk):
123 lock_(lk)
124 {
125 lock_.unlock();
126 }
127 ~relocker()
128 {
129 if (! lock_.owns_lock()) {
130 lock_.lock();
131 }
132 }
133 void lock() {
134 if (! lock_.owns_lock()) {
135 lock_.lock();
136 }
137 }
138 private:
139 relocker& operator=(relocker const&);
140 };
141
142 struct shared_state_base : enable_shared_from_this<shared_state_base>
143 {
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;
149
150 boost::exception_ptr exception;
151 bool done;
152 bool is_valid_;
153 bool is_deferred_;
154 bool is_constructed;
155 launch policy_;
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;
163
164 // This declaration should be only included conditionally, but is included to maintain the same layout.
165 virtual void launch_continuation()
166 {
167 }
168
169 shared_state_base():
170 done(false),
171 is_valid_(true),
172 is_deferred_(false),
173 is_constructed(false),
174 policy_(launch::none),
175 continuations(),
176 ex()
177 {}
178
179 shared_state_base(exceptional_ptr const& ex_):
180 exception(ex_.ptr_),
181 done(true),
182 is_valid_(true),
183 is_deferred_(false),
184 is_constructed(false),
185 policy_(launch::none),
186 continuations(),
187 ex()
188 {}
189
190
191 virtual ~shared_state_base()
192 {
193 }
194 executor_ptr_type get_executor()
195 {
196 return ex;
197 }
198
199 void set_executor_policy(executor_ptr_type aex)
200 {
201 set_executor();
202 ex = aex;
203 }
204 void set_executor_policy(executor_ptr_type aex, boost::lock_guard<boost::mutex>&)
205 {
206 set_executor();
207 ex = aex;
208 }
209 void set_executor_policy(executor_ptr_type aex, boost::unique_lock<boost::mutex>&)
210 {
211 set_executor();
212 ex = aex;
213 }
214
215 bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; }
216 bool valid() {
217 boost::unique_lock<boost::mutex> lk(this->mutex);
218 return valid(lk);
219 }
220 void invalidate(boost::unique_lock<boost::mutex>&) { is_valid_ = false; }
221 void invalidate() {
222 boost::unique_lock<boost::mutex> lk(this->mutex);
223 invalidate(lk);
224 }
225 void validate(boost::unique_lock<boost::mutex>&) { is_valid_ = true; }
226 void validate() {
227 boost::unique_lock<boost::mutex> lk(this->mutex);
228 validate(lk);
229 }
230
231 void set_deferred()
232 {
233 is_deferred_ = true;
234 policy_ = launch::deferred;
235 }
236 void set_async()
237 {
238 is_deferred_ = false;
239 policy_ = launch::async;
240 }
241#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
242 void set_executor()
243 {
244 is_deferred_ = false;
245 policy_ = launch::executor;
246 }
247#else
248 void set_executor()
249 {
250 }
251#endif
252 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
253 {
254 boost::unique_lock<boost::mutex> lock(this->mutex);
255 do_callback(lock);
256 return external_waiters.insert(external_waiters.end(),&cv);
257 }
258
259 void unnotify_when_ready(notify_when_ready_handle it)
260 {
261 boost::lock_guard<boost::mutex> lock(this->mutex);
262 external_waiters.erase(it);
263 }
264
265#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
266 void do_continuation(boost::unique_lock<boost::mutex>& lock)
267 {
268 if (! continuations.empty()) {
269 continuations_type the_continuations = continuations;
270 continuations.clear();
271 relocker rlk(lock);
272 for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) {
273 (*it)->launch_continuation();
274 }
275 }
276 }
277#else
278 void do_continuation(boost::unique_lock<boost::mutex>&)
279 {
280 }
281#endif
282#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
283 virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
284 {
285 continuations.push_back(continuation);
286 if (done) {
287 do_continuation(lock);
288 }
289 }
290#endif
291 void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
292 {
293 done=true;
294 waiters.notify_all();
295 for(waiter_list::const_iterator it=external_waiters.begin(),
296 end=external_waiters.end();it!=end;++it)
297 {
298 (*it)->notify_all();
299 }
300 do_continuation(lock);
301 }
302 void make_ready()
303 {
304 boost::unique_lock<boost::mutex> lock(this->mutex);
305 mark_finished_internal(lock);
306 }
307
308 void do_callback(boost::unique_lock<boost::mutex>& lock)
309 {
310 if(callback && !done)
311 {
312 boost::function<void()> local_callback=callback;
313 relocker relock(lock);
314 local_callback();
315 }
316 }
317
318 virtual bool run_if_is_deferred()
319 {
320 boost::unique_lock<boost::mutex> lk(this->mutex);
321 if (is_deferred_)
322 {
323 is_deferred_=false;
324 execute(lk);
325 return true;
326 }
327 else
328 return false;
329 }
330 virtual bool run_if_is_deferred_or_ready()
331 {
332 boost::unique_lock<boost::mutex> lk(this->mutex);
333 if (is_deferred_)
334 {
335 is_deferred_=false;
336 execute(lk);
337
338 return true;
339 }
340 else
341 return done;
342 }
343 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true)
344 {
345 do_callback(lk);
346 if (is_deferred_)
347 {
348 is_deferred_=false;
349 execute(lk);
350 }
351 while(!done)
352 {
353 waiters.wait(lk);
354 }
355 if(rethrow && exception)
356 {
357 boost::rethrow_exception(exception);
358 }
359 }
360
361 virtual void wait(boost::unique_lock<boost::mutex>& lock, bool rethrow=true)
362 {
363 wait_internal(lock, rethrow);
364 }
365
366 void wait(bool rethrow=true)
367 {
368 boost::unique_lock<boost::mutex> lock(this->mutex);
369 wait(lock, rethrow);
370 }
371
372#if defined BOOST_THREAD_USES_DATETIME
373 bool timed_wait_until(boost::system_time const& target_time)
374 {
375 boost::unique_lock<boost::mutex> lock(this->mutex);
376 if (is_deferred_)
377 return false;
378
379 do_callback(lock);
380 while(!done)
381 {
382 bool const success=waiters.timed_wait(lock,target_time);
383 if(!success && !done)
384 {
385 return false;
386 }
387 }
388 return true;
389 }
390#endif
391#ifdef BOOST_THREAD_USES_CHRONO
392
393 template <class Clock, class Duration>
394 future_status
395 wait_until(const chrono::time_point<Clock, Duration>& abs_time)
396 {
397 boost::unique_lock<boost::mutex> lock(this->mutex);
398 if (is_deferred_)
399 return future_status::deferred;
400 do_callback(lock);
401 while(!done)
402 {
403 cv_status const st=waiters.wait_until(lock,abs_time);
404 if(st==cv_status::timeout && !done)
405 {
406 return future_status::timeout;
407 }
408 }
409 return future_status::ready;
410 }
411#endif
412 void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
413 {
414 exception=e;
415 mark_finished_internal(lock);
416 }
417
418 void mark_exceptional_finish()
419 {
420 boost::unique_lock<boost::mutex> lock(this->mutex);
421 mark_exceptional_finish_internal(boost::current_exception(), lock);
422 }
423
424 void set_exception_at_thread_exit(exception_ptr e)
425 {
426 unique_lock<boost::mutex> lk(this->mutex);
427 if (has_value(lk))
428 {
429 throw_exception(promise_already_satisfied());
430 }
431 exception=e;
432 this->is_constructed = true;
433 detail::make_ready_at_thread_exit(shared_from_this());
434 }
435
436 bool has_value() const
437 {
438 boost::lock_guard<boost::mutex> lock(this->mutex);
439 return done && ! exception;
440 }
441
442 bool has_value(unique_lock<boost::mutex>& ) const
443 {
444 return done && ! exception;
445 }
446
447 bool has_exception() const
448 {
449 boost::lock_guard<boost::mutex> lock(this->mutex);
450 return done && exception;
451 }
452
453 launch launch_policy(boost::unique_lock<boost::mutex>&) const
454 {
455 return policy_;
456 }
457
458 future_state::state get_state(boost::unique_lock<boost::mutex>&) const
459 {
460 if(!done)
461 {
462 return future_state::waiting;
463 }
464 else
465 {
466 return future_state::ready;
467 }
468 }
469 future_state::state get_state() const
470 {
471 boost::lock_guard<boost::mutex> guard(this->mutex);
472 if(!done)
473 {
474 return future_state::waiting;
475 }
476 else
477 {
478 return future_state::ready;
479 }
480 }
481
482 exception_ptr get_exception_ptr()
483 {
484 boost::unique_lock<boost::mutex> lock(this->mutex);
485 wait_internal(lock, false);
486 return exception;
487 }
488
489 template<typename F,typename U>
490 void set_wait_callback(F f,U* u)
491 {
492 boost::lock_guard<boost::mutex> lock(this->mutex);
493 callback=boost::bind(f,boost::ref(*u));
494 }
495
496 virtual void execute(boost::unique_lock<boost::mutex>&) {}
497
498 private:
499 shared_state_base(shared_state_base const&);
500 shared_state_base& operator=(shared_state_base const&);
501 };
502
503 // Used to create stand-alone futures
504 template<typename T>
505 struct shared_state:
506 detail::shared_state_base
507 {
508#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
509 typedef boost::optional<T> storage_type;
510#else
511 typedef boost::csbl::unique_ptr<T> storage_type;
512#endif
513#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
514 typedef T const& source_reference_type;
515 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
516 typedef T move_dest_type;
517#elif defined BOOST_THREAD_USES_MOVE
518 typedef typename conditional<boost::is_fundamental<T>::value,T,T const&>::type source_reference_type;
519 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
520 typedef T move_dest_type;
521#else
522 typedef T& source_reference_type;
523 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;
524 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;
525#endif
526
527 typedef const T& shared_future_get_result_type;
528
529 storage_type result;
530
531 shared_state():
532 result()
533 {}
534 shared_state(exceptional_ptr const& ex):
535 detail::shared_state_base(ex), result()
536 {}
537
538
539 ~shared_state()
540 {
541 }
542
543 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
544 {
545#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
546 result = result_;
547#else
548 result.reset(new T(result_));
549#endif
550 this->mark_finished_internal(lock);
551 }
552
553 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
554 {
555#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
556 result = boost::move(result_);
557#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
558 result.reset(new T(boost::move(result_)));
559#else
560 result.reset(new T(static_cast<rvalue_source_type>(result_)));
561#endif
562 this->mark_finished_internal(lock);
563 }
564
565
566#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
567 template <class ...Args>
568 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock, BOOST_THREAD_FWD_REF(Args)... args)
569 {
570#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
571 result.emplace(boost::forward<Args>(args)...);
572#else
573 result.reset(new T(boost::forward<Args>(args)...));
574#endif
575 this->mark_finished_internal(lock);
576 }
577#endif
578
579 void mark_finished_with_result(source_reference_type result_)
580 {
581 boost::unique_lock<boost::mutex> lock(this->mutex);
582 this->mark_finished_with_result_internal(result_, lock);
583 }
584
585 void mark_finished_with_result(rvalue_source_type result_)
586 {
587 boost::unique_lock<boost::mutex> lock(this->mutex);
588
589#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
590 mark_finished_with_result_internal(boost::move(result_), lock);
591#else
592 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
593#endif
594 }
595
596 storage_type& get_storage(boost::unique_lock<boost::mutex>& lk)
597 {
598 wait_internal(lk);
599 return result;
600 }
601 virtual move_dest_type get(boost::unique_lock<boost::mutex>& lk)
602 {
603 return boost::move(*get_storage(lk));
604 }
605 move_dest_type get()
606 {
607 boost::unique_lock<boost::mutex> lk(this->mutex);
608 return this->get(lk);
609 }
610
611 virtual shared_future_get_result_type get_sh(boost::unique_lock<boost::mutex>& lk)
612 {
613 return *get_storage(lk);
614 }
615 shared_future_get_result_type get_sh()
616 {
617 boost::unique_lock<boost::mutex> lk(this->mutex);
618 return this->get_sh(lk);
619 }
620
621 void set_value_at_thread_exit(source_reference_type result_)
622 {
623 unique_lock<boost::mutex> lk(this->mutex);
624 if (this->has_value(lk))
625 {
626 throw_exception(promise_already_satisfied());
627 }
628#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
629 result = result_;
630#else
631 result.reset(new T(result_));
632#endif
633
634 this->is_constructed = true;
635 detail::make_ready_at_thread_exit(shared_from_this());
636 }
637 void set_value_at_thread_exit(rvalue_source_type result_)
638 {
639 unique_lock<boost::mutex> lk(this->mutex);
640 if (this->has_value(lk))
641 throw_exception(promise_already_satisfied());
642
643#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
644#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
645 result = boost::move(result_);
646#else
647 result.reset(new T(boost::move(result_)));
648#endif
649#else
650#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
651 result = boost::move(result_);
652#else
653 result.reset(new T(static_cast<rvalue_source_type>(result_)));
654#endif
655#endif
656 this->is_constructed = true;
657 detail::make_ready_at_thread_exit(shared_from_this());
658 }
659
660 private:
661 shared_state(shared_state const&);
662 shared_state& operator=(shared_state const&);
663 };
664
665 template<typename T>
666 struct shared_state<T&>:
667 detail::shared_state_base
668 {
669 typedef T* storage_type;
670 typedef T& source_reference_type;
671 typedef T& move_dest_type;
672 typedef T& shared_future_get_result_type;
673
674 T* result;
675
676 shared_state():
677 result(0)
678 {}
679
680 shared_state(exceptional_ptr const& ex):
681 detail::shared_state_base(ex), result(0)
682 {}
683
684 ~shared_state()
685 {
686 }
687
688 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
689 {
690 result= &result_;
691 mark_finished_internal(lock);
692 }
693
694 void mark_finished_with_result(source_reference_type result_)
695 {
696 boost::unique_lock<boost::mutex> lock(this->mutex);
697 mark_finished_with_result_internal(result_, lock);
698 }
699
700 virtual T& get(boost::unique_lock<boost::mutex>& lock)
701 {
702 wait_internal(lock);
703 return *result;
704 }
705 T& get()
706 {
707 boost::unique_lock<boost::mutex> lk(this->mutex);
708 return get(lk);
709 }
710
711 virtual T& get_sh(boost::unique_lock<boost::mutex>& lock)
712 {
713 wait_internal(lock);
714 return *result;
715 }
716 T& get_sh()
717 {
718 boost::unique_lock<boost::mutex> lock(this->mutex);
719 return get_sh(lock);
720 }
721
722 void set_value_at_thread_exit(T& result_)
723 {
724 unique_lock<boost::mutex> lk(this->mutex);
725 if (this->has_value(lk))
726 throw_exception(promise_already_satisfied());
727 result= &result_;
728 this->is_constructed = true;
729 detail::make_ready_at_thread_exit(shared_from_this());
730 }
731
732 private:
733 shared_state(shared_state const&);
734 shared_state& operator=(shared_state const&);
735 };
736
737 template<>
738 struct shared_state<void>:
739 detail::shared_state_base
740 {
741 typedef void shared_future_get_result_type;
742 typedef void move_dest_type;
743
744 shared_state()
745 {}
746
747 shared_state(exceptional_ptr const& ex):
748 detail::shared_state_base(ex)
749 {}
750
751 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
752 {
753 mark_finished_internal(lock);
754 }
755
756 void mark_finished_with_result()
757 {
758 boost::unique_lock<boost::mutex> lock(this->mutex);
759 mark_finished_with_result_internal(lock);
760 }
761
762 virtual void get(boost::unique_lock<boost::mutex>& lock)
763 {
764 this->wait_internal(lock);
765 }
766 void get()
767 {
768 boost::unique_lock<boost::mutex> lock(this->mutex);
769 this->get(lock);
770 }
771
772 virtual void get_sh(boost::unique_lock<boost::mutex>& lock)
773 {
774 this->wait_internal(lock);
775 }
776 void get_sh()
777 {
778 boost::unique_lock<boost::mutex> lock(this->mutex);
779 this->get_sh(lock);
780 }
781
782 void set_value_at_thread_exit()
783 {
784 unique_lock<boost::mutex> lk(this->mutex);
785 if (this->has_value(lk))
786 {
787 throw_exception(promise_already_satisfied());
788 }
789 this->is_constructed = true;
790 detail::make_ready_at_thread_exit(shared_from_this());
791 }
792 private:
793 shared_state(shared_state const&);
794 shared_state& operator=(shared_state const&);
795 };
796
797 /////////////////////////
798 /// future_async_shared_state_base
799 /////////////////////////
800 template<typename Rp>
801 struct future_async_shared_state_base: shared_state<Rp>
802 {
803 typedef shared_state<Rp> base_type;
804 protected:
805#ifdef BOOST_THREAD_FUTURE_BLOCKING
806 boost::thread thr_;
807 void join()
808 {
809 if (this_thread::get_id() == thr_.get_id())
810 {
811 thr_.detach();
812 return;
813 }
814 if (thr_.joinable()) thr_.join();
815 }
816#endif
817 public:
818 future_async_shared_state_base()
819 {
820 this->set_async();
821 }
822
823 ~future_async_shared_state_base()
824 {
825#ifdef BOOST_THREAD_FUTURE_BLOCKING
826 join();
827#elif defined BOOST_THREAD_ASYNC_FUTURE_WAITS
828 unique_lock<boost::mutex> lk(this->mutex);
829 while(!this->done)
830 {
831 this->waiters.wait(lk);
832 }
833#endif
834 }
835
836 virtual void wait(boost::unique_lock<boost::mutex>& lk, bool rethrow)
837 {
838#ifdef BOOST_THREAD_FUTURE_BLOCKING
839 {
840 relocker rlk(lk);
841 join();
842 }
843#endif
844 this->base_type::wait(lk, rethrow);
845 }
846 };
847
848 /////////////////////////
849 /// future_async_shared_state
850 /////////////////////////
851 template<typename Rp, typename Fp>
852 struct future_async_shared_state: future_async_shared_state_base<Rp>
853 {
854 future_async_shared_state()
855 {
856 }
857
858 void init(BOOST_THREAD_FWD_REF(Fp) f)
859 {
860#ifdef BOOST_THREAD_FUTURE_BLOCKING
861 this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f));
862#else
863 boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f)).detach();
864#endif
865 }
866
867 static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f)
868 {
869 try
870 {
871 that->mark_finished_with_result(f());
872 }
873 catch(...)
874 {
875 that->mark_exceptional_finish();
876 }
877 }
878 };
879
880 template<typename Fp>
881 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void>
882 {
883 void init(BOOST_THREAD_FWD_REF(Fp) f)
884 {
885#ifdef BOOST_THREAD_FUTURE_BLOCKING
886 this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
887#else
888 boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
889#endif
890 }
891
892 static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f)
893 {
894 try
895 {
896 f();
897 that->mark_finished_with_result();
898 }
899 catch(...)
900 {
901 that->mark_exceptional_finish();
902 }
903 }
904 };
905
906 template<typename Rp, typename Fp>
907 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&>
908 {
909 void init(BOOST_THREAD_FWD_REF(Fp) f)
910 {
911#ifdef BOOST_THREAD_FUTURE_BLOCKING
912 this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
913#else
914 boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
915#endif
916 }
917
918 static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f)
919 {
920 try
921 {
922 that->mark_finished_with_result(f());
923 }
924 catch(...)
925 {
926 that->mark_exceptional_finish();
927 }
928 }
929 };
930
931 //////////////////////////
932 /// future_deferred_shared_state
933 //////////////////////////
934 template<typename Rp, typename Fp>
935 struct future_deferred_shared_state: shared_state<Rp>
936 {
937 typedef shared_state<Rp> base_type;
938 Fp func_;
939
940 public:
941 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
942 : func_(boost::move(f))
943 {
944 this->set_deferred();
945 }
946
947 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
948 try
949 {
950 Fp local_fuct=boost::move(func_);
951 relocker relock(lck);
952 Rp res = local_fuct();
953 relock.lock();
954 this->mark_finished_with_result_internal(boost::move(res), lck);
955 }
956 catch (...)
957 {
958 this->mark_exceptional_finish_internal(current_exception(), lck);
959 }
960 }
961 };
962 template<typename Rp, typename Fp>
963 struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
964 {
965 typedef shared_state<Rp&> base_type;
966 Fp func_;
967
968 public:
969 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
970 : func_(boost::move(f))
971 {
972 this->set_deferred();
973 }
974
975 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
976 try
977 {
978 this->mark_finished_with_result_internal(func_(), lck);
979 }
980 catch (...)
981 {
982 this->mark_exceptional_finish_internal(current_exception(), lck);
983 }
984 }
985 };
986
987 template<typename Fp>
988 struct future_deferred_shared_state<void,Fp>: shared_state<void>
989 {
990 typedef shared_state<void> base_type;
991 Fp func_;
992
993 public:
994 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
995 : func_(boost::move(f))
996 {
997 this->set_deferred();
998 }
999
1000 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1001 try
1002 {
1003 Fp local_fuct=boost::move(func_);
1004 relocker relock(lck);
1005 local_fuct();
1006 relock.lock();
1007 this->mark_finished_with_result_internal(lck);
1008 }
1009 catch (...)
1010 {
1011 this->mark_exceptional_finish_internal(current_exception(), lck);
1012 }
1013 }
1014 };
1015
1016 class future_waiter
1017 {
1018 public:
1019 typedef std::vector<int>::size_type count_type;
1020 private:
1021 struct registered_waiter;
1022 struct registered_waiter
1023 {
1024 boost::shared_ptr<detail::shared_state_base> future_;
1025 detail::shared_state_base::notify_when_ready_handle handle;
1026 count_type index;
1027
1028 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future,
1029 detail::shared_state_base::notify_when_ready_handle handle_,
1030 count_type index_):
1031 future_(a_future),handle(handle_),index(index_)
1032 {}
1033 };
1034
1035 struct all_futures_lock
1036 {
1037#ifdef _MANAGED
1038 typedef std::ptrdiff_t count_type_portable;
1039#else
1040 typedef count_type count_type_portable;
1041#endif
1042 count_type_portable count;
1043 boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
1044
1045 all_futures_lock(std::vector<registered_waiter>& futures):
1046 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
1047 {
1048 for(count_type_portable i=0;i<count;++i)
1049 {
1050 locks[i]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(futures[i].future_->mutex));
1051 }
1052 }
1053
1054 void lock()
1055 {
1056 boost::lock(locks.get(),locks.get()+count);
1057 }
1058
1059 void unlock()
1060 {
1061 for(count_type_portable i=0;i<count;++i)
1062 {
1063 locks[i].unlock();
1064 }
1065 }
1066 };
1067
1068 boost::condition_variable_any cv;
1069 std::vector<registered_waiter> futures_;
1070 count_type future_count;
1071
1072 public:
1073 future_waiter():
1074 future_count(0)
1075 {}
1076
1077 template<typename F>
1078 void add(F& f)
1079 {
1080 if(f.future_)
1081 {
1082 registered_waiter waiter(f.future_,f.future_->notify_when_ready(cv),future_count);
1083 try {
1084 futures_.push_back(waiter);
1085 } catch(...) {
1086 f.future_->unnotify_when_ready(waiter.handle);
1087 throw;
1088 }
1089 }
1090 ++future_count;
1091 }
1092
1093#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
1094 template<typename F1, typename... Fs>
1095 void add(F1& f1, Fs&... fs)
1096 {
1097 add(f1); add(fs...);
1098 }
1099#endif
1100
1101 count_type wait()
1102 {
1103 all_futures_lock lk(futures_);
1104 for(;;)
1105 {
1106 for(count_type i=0;i<futures_.size();++i)
1107 {
1108 if(futures_[i].future_->done)
1109 {
1110 return futures_[i].index;
1111 }
1112 }
1113 cv.wait(lk);
1114 }
1115 }
1116
1117 ~future_waiter()
1118 {
1119 for(count_type i=0;i<futures_.size();++i)
1120 {
1121 futures_[i].future_->unnotify_when_ready(futures_[i].handle);
1122 }
1123 }
1124 };
1125
1126 }
1127
1128 template <typename R>
1129 class BOOST_THREAD_FUTURE;
1130
1131 template <typename R>
1132 class shared_future;
1133
1134 template<typename T>
1135 struct is_future_type<BOOST_THREAD_FUTURE<T> > : true_type
1136 {
1137 };
1138
1139 template<typename T>
1140 struct is_future_type<shared_future<T> > : true_type
1141 {
1142 };
1143
1144// template<typename Iterator>
1145// typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
1146// {
1147// if(begin==end)
1148// return end;
1149//
1150// detail::future_waiter waiter;
1151// for(Iterator current=begin;current!=end;++current)
1152// {
1153// waiter.add(*current);
1154// }
1155// return boost::next(begin,waiter.wait());
1156// }
1157
1158#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
1159 template<typename F1,typename F2>
1160 typename boost::enable_if<is_future_type<F1>,typename detail::future_waiter::count_type>::type wait_for_any(F1& f1,F2& f2)
1161 {
1162 detail::future_waiter waiter;
1163 waiter.add(f1);
1164 waiter.add(f2);
1165 return waiter.wait();
1166 }
1167
1168 template<typename F1,typename F2,typename F3>
1169 typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3)
1170 {
1171 detail::future_waiter waiter;
1172 waiter.add(f1);
1173 waiter.add(f2);
1174 waiter.add(f3);
1175 return waiter.wait();
1176 }
1177
1178 template<typename F1,typename F2,typename F3,typename F4>
1179 typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
1180 {
1181 detail::future_waiter waiter;
1182 waiter.add(f1);
1183 waiter.add(f2);
1184 waiter.add(f3);
1185 waiter.add(f4);
1186 return waiter.wait();
1187 }
1188
1189 template<typename F1,typename F2,typename F3,typename F4,typename F5>
1190 typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
1191 {
1192 detail::future_waiter waiter;
1193 waiter.add(f1);
1194 waiter.add(f2);
1195 waiter.add(f3);
1196 waiter.add(f4);
1197 waiter.add(f5);
1198 return waiter.wait();
1199 }
1200#else
1201 template<typename F1, typename... Fs>
1202 typename boost::enable_if<is_future_type<F1>, typename detail::future_waiter::count_type>::type
1203 wait_for_any(F1& f1, Fs&... fs)
1204 {
1205 detail::future_waiter waiter;
1206 waiter.add(f1, fs...);
1207 return waiter.wait();
1208 }
1209#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1210
1211 template <typename R>
1212 class promise;
1213
1214 template <typename R>
1215 class packaged_task;
1216
1217 namespace detail
1218 {
1219 /// Common implementation for all the futures independently of the return type
1220 class base_future
1221 {
1222 public:
1223 };
1224 /// Common implementation for future and shared_future.
1225 template <typename R>
1226 class basic_future : public base_future
1227 {
1228 protected:
1229 public:
1230
1231 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
1232 typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
1233
1234 static //BOOST_CONSTEXPR
1235 future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) {
1236 return future_ptr(new detail::shared_state<R>(ex));
1237 }
1238
1239 future_ptr future_;
1240
1241 basic_future(future_ptr a_future):
1242 future_(a_future)
1243 {
1244 }
1245
1246 public:
1247 typedef future_state::state state;
1248
1249 BOOST_THREAD_MOVABLE_ONLY(basic_future)
1250 basic_future(): future_() {}
1251
1252
1253 //BOOST_CONSTEXPR
1254 basic_future(exceptional_ptr const& ex)
1255 : future_(make_exceptional_future_ptr(ex))
1256 {
1257 }
1258
1259 ~basic_future() {
1260 }
1261
1262 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
1263 future_(BOOST_THREAD_RV(other).future_)
1264 {
1265 BOOST_THREAD_RV(other).future_.reset();
1266 }
1267 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
1268 {
1269 future_=BOOST_THREAD_RV(other).future_;
1270 BOOST_THREAD_RV(other).future_.reset();
1271 return *this;
1272 }
1273 void swap(basic_future& that) BOOST_NOEXCEPT
1274 {
1275 future_.swap(that.future_);
1276 }
1277 // functions to check state, and wait for ready
1278 state get_state(boost::unique_lock<boost::mutex>& lk) const
1279 {
1280 if(!future_)
1281 {
1282 return future_state::uninitialized;
1283 }
1284 return future_->get_state(lk);
1285 }
1286 state get_state() const
1287 {
1288 if(!future_)
1289 {
1290 return future_state::uninitialized;
1291 }
1292 return future_->get_state();
1293 }
1294
1295 bool is_ready() const
1296 {
1297 return get_state()==future_state::ready;
1298 }
1299
1300 bool is_ready(boost::unique_lock<boost::mutex>& lk) const
1301 {
1302 return get_state(lk)==future_state::ready;
1303 }
1304 bool has_exception() const
1305 {
1306 return future_ && future_->has_exception();
1307 }
1308
1309 bool has_value() const
1310 {
1311 return future_ && future_->has_value();
1312 }
1313
1314 launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
1315 {
1316 if ( future_ ) return future_->launch_policy(lk);
1317 else return launch(launch::none);
1318 }
1319
1320 launch launch_policy() const
1321 {
1322 if ( future_ ) {
1323 boost::unique_lock<boost::mutex> lk(this->future_->mutex);
1324 return future_->launch_policy(lk);
1325 }
1326 else return launch(launch::none);
1327 }
1328
1329 exception_ptr get_exception_ptr()
1330 {
1331 return future_
1332 ? future_->get_exception_ptr()
1333 : exception_ptr();
1334 }
1335
1336 bool valid() const BOOST_NOEXCEPT
1337 {
1338 return future_.get() != 0 && future_->valid();
1339 }
1340
1341 void wait() const
1342 {
1343 if(!future_)
1344 {
1345 boost::throw_exception(future_uninitialized());
1346 }
1347 future_->wait(false);
1348 }
1349
1350 typedef detail::shared_state_base::notify_when_ready_handle notify_when_ready_handle;
1351
1352 boost::mutex& mutex() {
1353 if(!future_)
1354 {
1355 boost::throw_exception(future_uninitialized());
1356 }
1357 return future_->mutex;
1358 }
1359
1360 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
1361 {
1362 if(!future_)
1363 {
1364 boost::throw_exception(future_uninitialized());
1365 }
1366 return future_->notify_when_ready(cv);
1367 }
1368
1369 void unnotify_when_ready(notify_when_ready_handle h)
1370 {
1371 if(!future_)
1372 {
1373 boost::throw_exception(future_uninitialized());
1374 }
1375 return future_->unnotify_when_ready(h);
1376 }
1377
1378#if defined BOOST_THREAD_USES_DATETIME
1379 template<typename Duration>
1380 bool timed_wait(Duration const& rel_time) const
1381 {
1382 return timed_wait_until(boost::get_system_time()+rel_time);
1383 }
1384
1385 bool timed_wait_until(boost::system_time const& abs_time) const
1386 {
1387 if(!future_)
1388 {
1389 boost::throw_exception(future_uninitialized());
1390 }
1391 return future_->timed_wait_until(abs_time);
1392 }
1393#endif
1394#ifdef BOOST_THREAD_USES_CHRONO
1395 template <class Rep, class Period>
1396 future_status
1397 wait_for(const chrono::duration<Rep, Period>& rel_time) const
1398 {
1399 return wait_until(chrono::steady_clock::now() + rel_time);
1400
1401 }
1402 template <class Clock, class Duration>
1403 future_status
1404 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
1405 {
1406 if(!future_)
1407 {
1408 boost::throw_exception(future_uninitialized());
1409 }
1410 return future_->wait_until(abs_time);
1411 }
1412#endif
1413
1414 };
1415
1416 } // detail
1417 BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
1418
1419 namespace detail
1420 {
1421#if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
1422 template <class Rp, class Fp>
1423 BOOST_THREAD_FUTURE<Rp>
1424 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1425
1426 template <class Rp, class Fp>
1427 BOOST_THREAD_FUTURE<Rp>
1428 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1429#endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
1430#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1431 template<typename F, typename Rp, typename Fp>
1432 struct future_deferred_continuation_shared_state;
1433 template<typename F, typename Rp, typename Fp>
1434 struct future_async_continuation_shared_state;
1435
1436 template <class F, class Rp, class Fp>
1437 BOOST_THREAD_FUTURE<Rp>
1438 make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1439
1440 template <class F, class Rp, class Fp>
1441 BOOST_THREAD_FUTURE<Rp>
1442 make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1443
1444 template <class F, class Rp, class Fp>
1445 BOOST_THREAD_FUTURE<Rp>
1446 make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1447
1448 template<typename F, typename Rp, typename Fp>
1449 BOOST_THREAD_FUTURE<Rp>
1450 make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1451
1452 template<typename F, typename Rp, typename Fp>
1453 BOOST_THREAD_FUTURE<Rp>
1454 make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1455
1456 template<typename F, typename Rp, typename Fp>
1457 BOOST_THREAD_FUTURE<Rp>
1458 make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1459
1460
1461 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1462 template<typename Ex, typename F, typename Rp, typename Fp>
1463 BOOST_THREAD_FUTURE<Rp>
1464 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);
1465
1466 template<typename Ex, typename F, typename Rp, typename Fp>
1467 BOOST_THREAD_FUTURE<Rp>
1468 make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1469
1470 template <class Rp, class Fp, class Executor>
1471 BOOST_THREAD_FUTURE<Rp>
1472 make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1473 #endif
1474#endif
1475#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1476 template<typename F, typename Rp>
1477 struct future_unwrap_shared_state;
1478 template <class F, class Rp>
1479 inline BOOST_THREAD_FUTURE<Rp>
1480 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1481#endif
1482 }
1483#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1484 template< typename InputIterator>
1485 typename boost::disable_if<is_future_type<InputIterator>,
1486 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1487 >::type
1488 when_all(InputIterator first, InputIterator last);
1489
1490 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1491
1492 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1493 template< typename T0, typename ...T>
1494 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1495 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1496 #endif
1497
1498 template< typename InputIterator>
1499 typename boost::disable_if<is_future_type<InputIterator>,
1500 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1501 >::type
1502 when_any(InputIterator first, InputIterator last);
1503
1504 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1505
1506 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1507 template< typename T0, typename ...T>
1508 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1509 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1510 #endif
1511#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1512
1513
1514 template <typename R>
1515 class BOOST_THREAD_FUTURE : public detail::basic_future<R>
1516 {
1517 private:
1518 typedef detail::basic_future<R> base_type;
1519 typedef typename base_type::future_ptr future_ptr;
1520
1521 friend class shared_future<R>;
1522 friend class promise<R>;
1523#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1524 template <typename, typename, typename>
1525 friend struct detail::future_async_continuation_shared_state;
1526 template <typename, typename, typename>
1527 friend struct detail::future_deferred_continuation_shared_state;
1528
1529 template <class F, class Rp, class Fp>
1530 friend BOOST_THREAD_FUTURE<Rp>
1531 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);
1532
1533 template <class F, class Rp, class Fp>
1534 friend BOOST_THREAD_FUTURE<Rp>
1535 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);
1536
1537 template <class F, class Rp, class Fp>
1538 friend BOOST_THREAD_FUTURE<Rp>
1539 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);
1540
1541 template<typename F, typename Rp, typename Fp>
1542 friend BOOST_THREAD_FUTURE<Rp>
1543 detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1544
1545 template<typename F, typename Rp, typename Fp>
1546 friend BOOST_THREAD_FUTURE<Rp>
1547 detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1548
1549 template<typename F, typename Rp, typename Fp>
1550 friend BOOST_THREAD_FUTURE<Rp>
1551 detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1552
1553 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1554 template<typename Ex, typename F, typename Rp, typename Fp>
1555 friend BOOST_THREAD_FUTURE<Rp>
1556 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);
1557
1558 template<typename Ex, typename F, typename Rp, typename Fp>
1559 friend BOOST_THREAD_FUTURE<Rp>
1560 detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1561
1562 template <class Rp, class Fp, class Executor>
1563 friend BOOST_THREAD_FUTURE<Rp>
1564 detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1565 #endif
1566#endif
1567#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1568 template<typename F, typename Rp>
1569 friend struct detail::future_unwrap_shared_state;
1570 template <class F, class Rp>
1571 friend BOOST_THREAD_FUTURE<Rp>
1572 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1573#endif
1574#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1575 template< typename InputIterator>
1576 friend typename boost::disable_if<is_future_type<InputIterator>,
1577 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1578 >::type
1579 when_all(InputIterator first, InputIterator last);
1580
1581 //friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1582
1583 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1584 template< typename T0, typename ...T>
1585 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1586 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1587 #endif
1588
1589 template< typename InputIterator>
1590 friend typename boost::disable_if<is_future_type<InputIterator>,
1591 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1592 >::type
1593 when_any(InputIterator first, InputIterator last);
1594
1595 //friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1596
1597 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1598 template< typename T0, typename ...T>
1599 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1600 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1601 #endif
1602#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1603#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1604 template <class> friend class packaged_task; // todo check if this works in windows
1605#else
1606 friend class packaged_task<R>;
1607#endif
1608 friend class detail::future_waiter;
1609
1610 template <class Rp, class Fp>
1611 friend BOOST_THREAD_FUTURE<Rp>
1612 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1613
1614 template <class Rp, class Fp>
1615 friend BOOST_THREAD_FUTURE<Rp>
1616 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1617
1618 typedef typename base_type::move_dest_type move_dest_type;
1619
1620 BOOST_THREAD_FUTURE(future_ptr a_future):
1621 base_type(a_future)
1622 {
1623 }
1624
1625 public:
1626 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1627 typedef future_state::state state;
1628 typedef R value_type; // EXTENSION
1629
1630 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
1631 //BOOST_CONSTEXPR
1632 BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
1633 base_type(ex) {}
1634
1635 ~BOOST_THREAD_FUTURE() {
1636 }
1637
1638 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
1639 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1640 {
1641 }
1642#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1643 inline explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
1644#endif
1645
1646 explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) :
1647 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1648 {}
1649
1650 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1651 {
1652 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1653 return *this;
1654 }
1655
1656 shared_future<R> share()
1657 {
1658 return shared_future<R>(::boost::move(*this));
1659 }
1660
1661 void swap(BOOST_THREAD_FUTURE& other)
1662 {
1663 static_cast<base_type*>(this)->swap(other);
1664 }
1665
1666 // todo this function must be private and friendship provided to the internal users.
1667 void set_async()
1668 {
1669 this->future_->set_async();
1670 }
1671 // todo this function must be private and friendship provided to the internal users.
1672 void set_deferred()
1673 {
1674 this->future_->set_deferred();
1675 }
1676 bool run_if_is_deferred() {
1677 return this->future_->run_if_is_deferred();
1678 }
1679 bool run_if_is_deferred_or_ready() {
1680 return this->future_->run_if_is_deferred_or_ready();
1681 }
1682 // retrieving the value
1683 move_dest_type get()
1684 {
1685 if (this->future_.get() == 0)
1686 {
1687 boost::throw_exception(future_uninitialized());
1688 }
1689 unique_lock<boost::mutex> lk(this->future_->mutex);
1690 if (! this->future_->valid(lk))
1691 {
1692 boost::throw_exception(future_uninitialized());
1693 }
1694#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1695 this->future_->invalidate(lk);
1696#endif
1697 return this->future_->get(lk);
1698 }
1699
1700 template <typename R2>
1701 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1702 get_or(BOOST_THREAD_RV_REF(R2) v)
1703 {
1704
1705 if (this->future_.get() == 0)
1706 {
1707 boost::throw_exception(future_uninitialized());
1708 }
1709 unique_lock<boost::mutex> lk(this->future_->mutex);
1710 if (! this->future_->valid(lk))
1711 {
1712 boost::throw_exception(future_uninitialized());
1713 }
1714 this->future_->wait(lk, false);
1715#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1716 this->future_->invalidate(lk);
1717#endif
1718
1719 if (this->future_->has_value(lk)) {
1720 return this->future_->get(lk);
1721 }
1722 else {
1723 return boost::move(v);
1724 }
1725 }
1726
1727 template <typename R2>
1728 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1729 get_or(R2 const& v) // EXTENSION
1730 {
1731 if (this->future_.get() == 0)
1732 {
1733 boost::throw_exception(future_uninitialized());
1734 }
1735 unique_lock<boost::mutex> lk(this->future_->mutex);
1736 if (! this->future_->valid(lk))
1737 {
1738 boost::throw_exception(future_uninitialized());
1739 }
1740 this->future_->wait(lk, false);
1741#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1742 this->future_->invalidate(lk);
1743#endif
1744 if (this->future_->has_value(lk)) {
1745 return this->future_->get(lk);
1746 }
1747 else {
1748 return v;
1749 }
1750 }
1751
1752#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1753 template<typename F>
1754 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1755 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1756 template<typename F>
1757 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1758 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1759 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1760 template<typename Ex, typename F>
1761 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1762 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1763 #endif
1764
1765 template <typename R2>
1766 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1767 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION
1768 template <typename R2>
1769 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1770 fallback_to(R2 const& v); // EXTENSION
1771
1772#endif
1773
1774 };
1775
1776 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
1777
1778 template <typename R2>
1779 class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
1780 {
1781 typedef BOOST_THREAD_FUTURE<R2> R;
1782
1783 private:
1784 typedef detail::basic_future<R> base_type;
1785 typedef typename base_type::future_ptr future_ptr;
1786
1787 friend class shared_future<R>;
1788 friend class promise<R>;
1789#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1790 template <typename, typename, typename>
1791 friend struct detail::future_async_continuation_shared_state;
1792 template <typename, typename, typename>
1793 friend struct detail::future_deferred_continuation_shared_state;
1794
1795 template <class F, class Rp, class Fp>
1796 friend BOOST_THREAD_FUTURE<Rp>
1797 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);
1798
1799 template <class F, class Rp, class Fp>
1800 friend BOOST_THREAD_FUTURE<Rp>
1801 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);
1802
1803 template <class F, class Rp, class Fp>
1804 friend BOOST_THREAD_FUTURE<Rp>
1805 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);
1806
1807 template<typename F, typename Rp, typename Fp>
1808 friend BOOST_THREAD_FUTURE<Rp>
1809 detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1810
1811 template<typename F, typename Rp, typename Fp>
1812 friend BOOST_THREAD_FUTURE<Rp>
1813 detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1814
1815 template<typename F, typename Rp, typename Fp>
1816 friend BOOST_THREAD_FUTURE<Rp>
1817 detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1818
1819 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1820 template<typename Ex, typename F, typename Rp, typename Fp>
1821 friend BOOST_THREAD_FUTURE<Rp>
1822 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);
1823
1824 template<typename Ex, typename F, typename Rp, typename Fp>
1825 friend BOOST_THREAD_FUTURE<Rp>
1826 detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1827
1828 template <class Rp, class Fp, class Executor>
1829 friend BOOST_THREAD_FUTURE<Rp>
1830 detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1831 #endif
1832
1833#endif
1834#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1835 template<typename F, typename Rp>
1836 friend struct detail::future_unwrap_shared_state;
1837 template <class F, class Rp>
1838 friend BOOST_THREAD_FUTURE<Rp>
1839 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1840#endif
1841#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1842 template< typename InputIterator>
1843 friend typename boost::disable_if<is_future_type<InputIterator>,
1844 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1845 >::type
1846 when_all(InputIterator first, InputIterator last);
1847
1848 friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1849
1850 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1851 template< typename T0, typename ...T>
1852 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1853 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1854 #endif
1855
1856 template< typename InputIterator>
1857 friend typename boost::disable_if<is_future_type<InputIterator>,
1858 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1859 >::type
1860 when_any(InputIterator first, InputIterator last);
1861
1862 friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1863
1864 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1865 template< typename T0, typename ...T>
1866 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1867 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1868 #endif
1869#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1870
1871 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1872 template <class> friend class packaged_task; // todo check if this works in windows
1873 #else
1874 friend class packaged_task<R>;
1875 #endif
1876 friend class detail::future_waiter;
1877
1878 template <class Rp, class Fp>
1879 friend BOOST_THREAD_FUTURE<Rp>
1880 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1881
1882 template <class Rp, class Fp>
1883 friend BOOST_THREAD_FUTURE<Rp>
1884 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1885
1886 typedef typename base_type::move_dest_type move_dest_type;
1887
1888 BOOST_THREAD_FUTURE(future_ptr a_future):
1889 base_type(a_future)
1890 {
1891 }
1892 public:
1893
1894 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1895 typedef future_state::state state;
1896 typedef R value_type; // EXTENSION
1897
1898 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
1899 //BOOST_CONSTEXPR
1900 BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
1901 base_type(ex) {}
1902
1903 ~BOOST_THREAD_FUTURE() {
1904 }
1905
1906 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
1907 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1908 {
1909 }
1910
1911 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1912 {
1913 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1914 return *this;
1915 }
1916
1917 shared_future<R> share()
1918 {
1919 return shared_future<R>(::boost::move(*this));
1920 }
1921
1922 void swap(BOOST_THREAD_FUTURE& other)
1923 {
1924 static_cast<base_type*>(this)->swap(other);
1925 }
1926
1927 // todo this function must be private and friendship provided to the internal users.
1928 void set_async()
1929 {
1930 this->future_->set_async();
1931 }
1932 // todo this function must be private and friendship provided to the internal users.
1933 void set_deferred()
1934 {
1935 this->future_->set_deferred();
1936 }
1937 bool run_if_is_deferred() {
1938 return this->future_->run_if_is_deferred();
1939 }
1940 bool run_if_is_deferred_or_ready() {
1941 return this->future_->run_if_is_deferred_or_ready();
1942 }
1943 // retrieving the value
1944 move_dest_type get()
1945 {
1946 if (this->future_.get() == 0)
1947 {
1948 boost::throw_exception(future_uninitialized());
1949 }
1950 unique_lock<boost::mutex> lk(this->future_->mutex);
1951 if (! this->future_->valid(lk))
1952 {
1953 boost::throw_exception(future_uninitialized());
1954 }
1955 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1956 this->future_->invalidate(lk);
1957 #endif
1958 return this->future_->get(lk);
1959 }
1960 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
1961 {
1962 if (this->future_.get() == 0)
1963 {
1964 boost::throw_exception(future_uninitialized());
1965 }
1966 unique_lock<boost::mutex> lk(this->future_->mutex);
1967 if (! this->future_->valid(lk))
1968 {
1969 boost::throw_exception(future_uninitialized());
1970 }
1971 this->future_->wait(lk, false);
1972 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1973 this->future_->invalidate(lk);
1974 #endif
1975 if (this->future_->has_value(lk)) return this->future_->get(lk);
1976 else return boost::move(v);
1977 }
1978
1979 move_dest_type get_or(R const& v) // EXTENSION
1980 {
1981 if (this->future_.get() == 0)
1982 {
1983 boost::throw_exception(future_uninitialized());
1984 }
1985 unique_lock<boost::mutex> lk(this->future_->mutex);
1986 if (! this->future_->valid(lk))
1987 {
1988 boost::throw_exception(future_uninitialized());
1989 }
1990 this->future_->wait(lk, false);
1991 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1992 this->future_->invalidate(lk);
1993 #endif
1994 if (this->future_->has_value(lk)) return this->future_->get(lk);
1995 else return v;
1996 }
1997
1998
1999 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2000 template<typename F>
2001 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2002 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2003 template<typename F>
2004 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2005 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2006 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2007 template<typename Ex, typename F>
2008 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2009 then(Ex &ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2010 #endif
2011 #endif
2012
2013 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
2014 inline
2015 BOOST_THREAD_FUTURE<R2>
2016 unwrap(); // EXTENSION
2017 #endif
2018
2019 };
2020
2021 template <typename R>
2022 class shared_future : public detail::basic_future<R>
2023 {
2024 typedef detail::basic_future<R> base_type;
2025 typedef typename base_type::future_ptr future_ptr;
2026
2027 friend class detail::future_waiter;
2028 friend class promise<R>;
2029
2030#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2031 template <typename, typename, typename>
2032 friend struct detail::future_async_continuation_shared_state;
2033 template <typename, typename, typename>
2034 friend struct detail::future_deferred_continuation_shared_state;
2035
2036 template <class F, class Rp, class Fp>
2037 friend BOOST_THREAD_FUTURE<Rp>
2038 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);
2039
2040 template <class F, class Rp, class Fp>
2041 friend BOOST_THREAD_FUTURE<Rp>
2042 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);
2043
2044 template <class F, class Rp, class Fp>
2045 friend BOOST_THREAD_FUTURE<Rp>
2046 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);
2047#endif
2048#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2049 template <class> friend class packaged_task;// todo check if this works in windows
2050#else
2051 friend class packaged_task<R>;
2052#endif
2053 shared_future(future_ptr a_future):
2054 base_type(a_future)
2055 {}
2056
2057 public:
2058 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future)
2059 typedef R value_type; // EXTENSION
2060
2061 shared_future(shared_future const& other):
2062 base_type(other.future_)
2063 {}
2064
2065 typedef future_state::state state;
2066
2067 BOOST_CONSTEXPR shared_future()
2068 {}
2069 //BOOST_CONSTEXPR
2070 shared_future(exceptional_ptr const& ex):
2071 base_type(ex) {}
2072 ~shared_future()
2073 {}
2074
2075 shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other)
2076 {
2077 this->future_ = other.future_;
2078 return *this;
2079 }
2080
2081 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
2082 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2083 {
2084 }
2085 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
2086 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2087 {
2088 }
2089
2090 shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
2091 {
2092 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2093 return *this;
2094 }
2095 shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
2096 {
2097 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2098 return *this;
2099 }
2100
2101 void swap(shared_future& other) BOOST_NOEXCEPT
2102 {
2103 static_cast<base_type*>(this)->swap(other);
2104 }
2105 bool run_if_is_deferred() {
2106 return this->future_->run_if_is_deferred();
2107 }
2108 bool run_if_is_deferred_or_ready() {
2109 return this->future_->run_if_is_deferred_or_ready();
2110 }
2111 // retrieving the value
2112 typename detail::shared_state<R>::shared_future_get_result_type get() const
2113 {
2114 if(!this->future_)
2115 {
2116 boost::throw_exception(future_uninitialized());
2117 }
2118 return this->future_->get_sh();
2119 }
2120
2121 template <typename R2>
2122 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
2123 get_or(BOOST_THREAD_RV_REF(R2) v) const // EXTENSION
2124 {
2125 if(!this->future_)
2126 {
2127 boost::throw_exception(future_uninitialized());
2128 }
2129 this->future_->wait();
2130 if (this->future_->has_value()) return this->future_->get_sh();
2131 else return boost::move(v);
2132 }
2133
2134#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2135 template<typename F>
2136 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2137 then(BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2138 template<typename F>
2139 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2140 then(launch policy, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2141 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2142 template<typename Ex, typename F>
2143 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2144 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2145 #endif
2146#endif
2147
2148 };
2149
2150 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
2151
2152 template <typename R>
2153 class promise
2154 {
2155 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
2156
2157 typedef typename detail::shared_state<R>::source_reference_type source_reference_type;
2158 typedef typename detail::shared_state<R>::rvalue_source_type rvalue_source_type;
2159 typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
2160 typedef typename detail::shared_state<R>::shared_future_get_result_type shared_future_get_result_type;
2161
2162 future_ptr future_;
2163 bool future_obtained;
2164
2165 void lazy_init()
2166 {
2167#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2168#include <boost/detail/atomic_undef_macros.hpp>
2169 if(!atomic_load(&future_))
2170 {
2171 future_ptr blank;
2172 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
2173 }
2174#include <boost/detail/atomic_redef_macros.hpp>
2175#endif
2176 }
2177
2178 public:
2179 BOOST_THREAD_MOVABLE_ONLY(promise)
2180#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2181 template <class Allocator>
2182 promise(boost::allocator_arg_t, Allocator a)
2183 {
2184 typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2;
2185 A2 a2(a);
2186 typedef thread_detail::allocator_destructor<A2> D;
2187
2188 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) );
2189 future_obtained = false;
2190 }
2191#endif
2192 promise():
2193#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2194 future_(),
2195#else
2196 future_(new detail::shared_state<R>()),
2197#endif
2198 future_obtained(false)
2199 {}
2200
2201 ~promise()
2202 {
2203 if(future_)
2204 {
2205 boost::unique_lock<boost::mutex> lock(future_->mutex);
2206
2207 if(!future_->done && !future_->is_constructed)
2208 {
2209 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2210 }
2211 }
2212 }
2213
2214 // Assignment
2215 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2216 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2217 {
2218 BOOST_THREAD_RV(rhs).future_.reset();
2219 BOOST_THREAD_RV(rhs).future_obtained=false;
2220 }
2221 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2222 {
2223 future_=BOOST_THREAD_RV(rhs).future_;
2224 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2225 BOOST_THREAD_RV(rhs).future_.reset();
2226 BOOST_THREAD_RV(rhs).future_obtained=false;
2227 return *this;
2228 }
2229
2230 void swap(promise& other)
2231 {
2232 future_.swap(other.future_);
2233 std::swap(future_obtained,other.future_obtained);
2234 }
2235
2236#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2237 void set_executor(executor_ptr_type aex)
2238 {
2239 lazy_init();
2240 if (future_.get()==0)
2241 {
2242 boost::throw_exception(promise_moved());
2243 }
2244 boost::lock_guard<boost::mutex> lk(future_->mutex);
2245 future_->set_executor_policy(aex, lk);
2246 }
2247#endif
2248 // Result retrieval
2249 BOOST_THREAD_FUTURE<R> get_future()
2250 {
2251 lazy_init();
2252 if (future_.get()==0)
2253 {
2254 boost::throw_exception(promise_moved());
2255 }
2256 if (future_obtained)
2257 {
2258 boost::throw_exception(future_already_retrieved());
2259 }
2260 future_obtained=true;
2261 return BOOST_THREAD_FUTURE<R>(future_);
2262 }
2263
2264#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2265 template <class TR>
2266 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value(TR const & r)
2267 {
2268 lazy_init();
2269 boost::unique_lock<boost::mutex> lock(future_->mutex);
2270 if(future_->done)
2271 {
2272 boost::throw_exception(promise_already_satisfied());
2273 }
2274 future_->mark_finished_with_result_internal(r, lock);
2275 }
2276#else
2277 void set_value(source_reference_type r)
2278 {
2279 lazy_init();
2280 boost::unique_lock<boost::mutex> lock(future_->mutex);
2281 if(future_->done)
2282 {
2283 boost::throw_exception(promise_already_satisfied());
2284 }
2285 future_->mark_finished_with_result_internal(r, lock);
2286 }
2287#endif
2288
2289 void set_value(rvalue_source_type r)
2290 {
2291 lazy_init();
2292 boost::unique_lock<boost::mutex> lock(future_->mutex);
2293 if(future_->done)
2294 {
2295 boost::throw_exception(promise_already_satisfied());
2296 }
2297#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2298 future_->mark_finished_with_result_internal(boost::move(r), lock);
2299#else
2300 future_->mark_finished_with_result_internal(static_cast<rvalue_source_type>(r), lock);
2301#endif
2302 }
2303
2304#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
2305 template <class ...Args>
2306 void emplace(BOOST_THREAD_FWD_REF(Args) ...args)
2307 {
2308 lazy_init();
2309 boost::unique_lock<boost::mutex> lock(future_->mutex);
2310 if(future_->done)
2311 {
2312 boost::throw_exception(promise_already_satisfied());
2313 }
2314 future_->mark_finished_with_result_internal(lock, boost::forward<Args>(args)...);
2315 }
2316
2317#endif
2318
2319 void set_exception(boost::exception_ptr p)
2320 {
2321 lazy_init();
2322 boost::unique_lock<boost::mutex> lock(future_->mutex);
2323 if(future_->done)
2324 {
2325 boost::throw_exception(promise_already_satisfied());
2326 }
2327 future_->mark_exceptional_finish_internal(p, lock);
2328 }
2329 template <typename E>
2330 void set_exception(E ex)
2331 {
2332 set_exception(boost::copy_exception(ex));
2333 }
2334 // setting the result with deferred notification
2335#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2336 template <class TR>
2337 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)
2338 {
2339 if (future_.get()==0)
2340 {
2341 boost::throw_exception(promise_moved());
2342 }
2343 future_->set_value_at_thread_exit(r);
2344 }
2345#else
2346 void set_value_at_thread_exit(source_reference_type r)
2347 {
2348 if (future_.get()==0)
2349 {
2350 boost::throw_exception(promise_moved());
2351 }
2352 future_->set_value_at_thread_exit(r);
2353 }
2354#endif
2355 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
2356 {
2357 if (future_.get()==0)
2358 {
2359 boost::throw_exception(promise_moved());
2360 }
2361 future_->set_value_at_thread_exit(boost::move(r));
2362 }
2363 void set_exception_at_thread_exit(exception_ptr e)
2364 {
2365 if (future_.get()==0)
2366 {
2367 boost::throw_exception(promise_moved());
2368 }
2369 future_->set_exception_at_thread_exit(e);
2370 }
2371 template <typename E>
2372 void set_exception_at_thread_exit(E ex)
2373 {
2374 set_exception_at_thread_exit(boost::copy_exception(ex));
2375 }
2376
2377 template<typename F>
2378 void set_wait_callback(F f)
2379 {
2380 lazy_init();
2381 future_->set_wait_callback(f,this);
2382 }
2383
2384 };
2385
2386 template <typename R>
2387 class promise<R&>
2388 {
2389 typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr;
2390
2391 future_ptr future_;
2392 bool future_obtained;
2393
2394 void lazy_init()
2395 {
2396#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2397#include <boost/detail/atomic_undef_macros.hpp>
2398 if(!atomic_load(&future_))
2399 {
2400 future_ptr blank;
2401 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
2402 }
2403#include <boost/detail/atomic_redef_macros.hpp>
2404#endif
2405 }
2406
2407 public:
2408 BOOST_THREAD_MOVABLE_ONLY(promise)
2409#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2410 template <class Allocator>
2411 promise(boost::allocator_arg_t, Allocator a)
2412 {
2413 typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2;
2414 A2 a2(a);
2415 typedef thread_detail::allocator_destructor<A2> D;
2416
2417 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
2418 future_obtained = false;
2419 }
2420#endif
2421 promise():
2422#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2423 future_(),
2424#else
2425 future_(new detail::shared_state<R&>()),
2426#endif
2427 future_obtained(false)
2428 {}
2429
2430 ~promise()
2431 {
2432 if(future_)
2433 {
2434 boost::unique_lock<boost::mutex> lock(future_->mutex);
2435
2436 if(!future_->done && !future_->is_constructed)
2437 {
2438 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2439 }
2440 }
2441 }
2442
2443 // Assignment
2444 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2445 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2446 {
2447 BOOST_THREAD_RV(rhs).future_.reset();
2448 BOOST_THREAD_RV(rhs).future_obtained=false;
2449 }
2450 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2451 {
2452 future_=BOOST_THREAD_RV(rhs).future_;
2453 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2454 BOOST_THREAD_RV(rhs).future_.reset();
2455 BOOST_THREAD_RV(rhs).future_obtained=false;
2456 return *this;
2457 }
2458
2459 void swap(promise& other)
2460 {
2461 future_.swap(other.future_);
2462 std::swap(future_obtained,other.future_obtained);
2463 }
2464
2465 // Result retrieval
2466 BOOST_THREAD_FUTURE<R&> get_future()
2467 {
2468 lazy_init();
2469 if (future_.get()==0)
2470 {
2471 boost::throw_exception(promise_moved());
2472 }
2473 if (future_obtained)
2474 {
2475 boost::throw_exception(future_already_retrieved());
2476 }
2477 future_obtained=true;
2478 return BOOST_THREAD_FUTURE<R&>(future_);
2479 }
2480
2481 void set_value(R& r)
2482 {
2483 lazy_init();
2484 boost::unique_lock<boost::mutex> lock(future_->mutex);
2485 if(future_->done)
2486 {
2487 boost::throw_exception(promise_already_satisfied());
2488 }
2489 future_->mark_finished_with_result_internal(r, lock);
2490 }
2491
2492 void set_exception(boost::exception_ptr p)
2493 {
2494 lazy_init();
2495 boost::unique_lock<boost::mutex> lock(future_->mutex);
2496 if(future_->done)
2497 {
2498 boost::throw_exception(promise_already_satisfied());
2499 }
2500 future_->mark_exceptional_finish_internal(p, lock);
2501 }
2502 template <typename E>
2503 void set_exception(E ex)
2504 {
2505 set_exception(boost::copy_exception(ex));
2506 }
2507
2508 // setting the result with deferred notification
2509 void set_value_at_thread_exit(R& r)
2510 {
2511 if (future_.get()==0)
2512 {
2513 boost::throw_exception(promise_moved());
2514 }
2515 future_->set_value_at_thread_exit(r);
2516 }
2517
2518 void set_exception_at_thread_exit(exception_ptr e)
2519 {
2520 if (future_.get()==0)
2521 {
2522 boost::throw_exception(promise_moved());
2523 }
2524 future_->set_exception_at_thread_exit(e);
2525 }
2526 template <typename E>
2527 void set_exception_at_thread_exit(E ex)
2528 {
2529 set_exception_at_thread_exit(boost::copy_exception(ex));
2530 }
2531
2532 template<typename F>
2533 void set_wait_callback(F f)
2534 {
2535 lazy_init();
2536 future_->set_wait_callback(f,this);
2537 }
2538 };
2539
2540 template <>
2541 class promise<void>
2542 {
2543 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr;
2544
2545 future_ptr future_;
2546 bool future_obtained;
2547
2548 void lazy_init()
2549 {
2550#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2551 if(!atomic_load(&future_))
2552 {
2553 future_ptr blank;
2554 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>));
2555 }
2556#endif
2557 }
2558 public:
2559 BOOST_THREAD_MOVABLE_ONLY(promise)
2560
2561#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2562 template <class Allocator>
2563 promise(boost::allocator_arg_t, Allocator a)
2564 {
2565 typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2;
2566 A2 a2(a);
2567 typedef thread_detail::allocator_destructor<A2> D;
2568
2569 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
2570 future_obtained = false;
2571 }
2572#endif
2573 promise():
2574#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2575 future_(),
2576#else
2577 future_(new detail::shared_state<void>),
2578#endif
2579 future_obtained(false)
2580 {}
2581
2582 ~promise()
2583 {
2584 if(future_)
2585 {
2586 boost::unique_lock<boost::mutex> lock(future_->mutex);
2587
2588 if(!future_->done && !future_->is_constructed)
2589 {
2590 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2591 }
2592 }
2593 }
2594
2595 // Assignment
2596 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2597 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2598 {
2599 // we need to release the future as shared_ptr doesn't implements move semantics
2600 BOOST_THREAD_RV(rhs).future_.reset();
2601 BOOST_THREAD_RV(rhs).future_obtained=false;
2602 }
2603
2604 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2605 {
2606 future_=BOOST_THREAD_RV(rhs).future_;
2607 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2608 BOOST_THREAD_RV(rhs).future_.reset();
2609 BOOST_THREAD_RV(rhs).future_obtained=false;
2610 return *this;
2611 }
2612
2613 void swap(promise& other)
2614 {
2615 future_.swap(other.future_);
2616 std::swap(future_obtained,other.future_obtained);
2617 }
2618
2619 // Result retrieval
2620 BOOST_THREAD_FUTURE<void> get_future()
2621 {
2622 lazy_init();
2623
2624 if (future_.get()==0)
2625 {
2626 boost::throw_exception(promise_moved());
2627 }
2628 if(future_obtained)
2629 {
2630 boost::throw_exception(future_already_retrieved());
2631 }
2632 future_obtained=true;
2633 //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<void>(future_));
2634 return BOOST_THREAD_FUTURE<void>(future_);
2635 }
2636
2637 void set_value()
2638 {
2639 lazy_init();
2640 boost::unique_lock<boost::mutex> lock(future_->mutex);
2641 if(future_->done)
2642 {
2643 boost::throw_exception(promise_already_satisfied());
2644 }
2645 future_->mark_finished_with_result_internal(lock);
2646 }
2647
2648 void set_exception(boost::exception_ptr p)
2649 {
2650 lazy_init();
2651 boost::unique_lock<boost::mutex> lock(future_->mutex);
2652 if(future_->done)
2653 {
2654 boost::throw_exception(promise_already_satisfied());
2655 }
2656 future_->mark_exceptional_finish_internal(p,lock);
2657 }
2658 template <typename E>
2659 void set_exception(E ex)
2660 {
2661 set_exception(boost::copy_exception(ex));
2662 }
2663
2664 // setting the result with deferred notification
2665 void set_value_at_thread_exit()
2666 {
2667 if (future_.get()==0)
2668 {
2669 boost::throw_exception(promise_moved());
2670 }
2671 future_->set_value_at_thread_exit();
2672 }
2673
2674 void set_exception_at_thread_exit(exception_ptr e)
2675 {
2676 if (future_.get()==0)
2677 {
2678 boost::throw_exception(promise_moved());
2679 }
2680 future_->set_exception_at_thread_exit(e);
2681 }
2682 template <typename E>
2683 void set_exception_at_thread_exit(E ex)
2684 {
2685 set_exception_at_thread_exit(boost::copy_exception(ex));
2686 }
2687
2688 template<typename F>
2689 void set_wait_callback(F f)
2690 {
2691 lazy_init();
2692 future_->set_wait_callback(f,this);
2693 }
2694
2695 };
2696}
2697#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2698namespace boost { namespace container {
2699 template <class R, class Alloc>
2700 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
2701 {
2702 };
2703}}
2704#if ! defined BOOST_NO_CXX11_ALLOCATOR
2705namespace std {
2706 template <class R, class Alloc>
2707 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
2708 {
2709 };
2710}
2711#endif
2712#endif
2713
2714namespace boost
2715{
2716
2717 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
2718
2719 namespace detail
2720 {
2721#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2722 template<typename R>
2723 struct task_base_shared_state;
2724#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2725 template<typename R, typename ...ArgTypes>
2726 struct task_base_shared_state<R(ArgTypes...)>:
2727#else
2728 template<typename R>
2729 struct task_base_shared_state<R()>:
2730#endif
2731#else
2732 template<typename R>
2733 struct task_base_shared_state:
2734#endif
2735 detail::shared_state<R>
2736 {
2737 bool started;
2738
2739 task_base_shared_state():
2740 started(false)
2741 {}
2742
2743 void reset()
2744 {
2745 // todo The packaged_task::reset must be as if an assignemnt froma new packaged_task with the same function
2746 // the reset function is an optimization that avoids reallocating a new task.
2747 started=false;
2748 this->validate();
2749 }
2750#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2751 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2752 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2753#else
2754 virtual void do_run()=0;
2755 void run()
2756#endif
2757 {
2758 {
2759 boost::lock_guard<boost::mutex> lk(this->mutex);
2760 if(started)
2761 {
2762 boost::throw_exception(task_already_started());
2763 }
2764 started=true;
2765 }
2766#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2767 do_run(boost::move(args)...);
2768#else
2769 do_run();
2770#endif
2771 }
2772
2773#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2774 virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2775 void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2776#else
2777 virtual void do_apply()=0;
2778 void apply()
2779#endif
2780 {
2781 {
2782 boost::lock_guard<boost::mutex> lk(this->mutex);
2783 if(started)
2784 {
2785 boost::throw_exception(task_already_started());
2786 }
2787 started=true;
2788 }
2789#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2790 do_apply(boost::move(args)...);
2791#else
2792 do_apply();
2793#endif
2794 }
2795
2796 void owner_destroyed()
2797 {
2798 boost::unique_lock<boost::mutex> lk(this->mutex);
2799 if(!started)
2800 {
2801 started=true;
2802 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
2803 }
2804 }
2805 };
2806
2807#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2808 template<typename F, typename R>
2809 struct task_shared_state;
2810#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2811 template<typename F, typename R, typename ...ArgTypes>
2812 struct task_shared_state<F, R(ArgTypes...)>:
2813 task_base_shared_state<R(ArgTypes...)>
2814#else
2815 template<typename F, typename R>
2816 struct task_shared_state<F, R()>:
2817 task_base_shared_state<R()>
2818#endif
2819#else
2820 template<typename F, typename R>
2821 struct task_shared_state:
2822 task_base_shared_state<R>
2823#endif
2824 {
2825 private:
2826 task_shared_state(task_shared_state&);
2827 public:
2828 F f;
2829 task_shared_state(F const& f_):
2830 f(f_)
2831 {}
2832 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
2833 f(boost::move(f_))
2834 {}
2835
2836 F callable()
2837 {
2838 return boost::move(f);
2839 }
2840
2841#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2842 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2843 {
2844 try
2845 {
2846 this->set_value_at_thread_exit(f(boost::move(args)...));
2847 }
2848#else
2849 void do_apply()
2850 {
2851 try
2852 {
2853 this->set_value_at_thread_exit(f());
2854 }
2855#endif
2856 catch(...)
2857 {
2858 this->set_exception_at_thread_exit(current_exception());
2859 }
2860 }
2861
2862#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2863 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2864 {
2865 try
2866 {
2867 this->mark_finished_with_result(f(boost::move(args)...));
2868 }
2869#else
2870 void do_run()
2871 {
2872 try
2873 {
2874#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2875 R res((f()));
2876 this->mark_finished_with_result(boost::move(res));
2877#else
2878 this->mark_finished_with_result(f());
2879#endif
2880 }
2881#endif
2882 catch(...)
2883 {
2884 this->mark_exceptional_finish();
2885 }
2886 }
2887 };
2888
2889#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2890#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2891 template<typename F, typename R, typename ...ArgTypes>
2892 struct task_shared_state<F, R&(ArgTypes...)>:
2893 task_base_shared_state<R&(ArgTypes...)>
2894#else
2895 template<typename F, typename R>
2896 struct task_shared_state<F, R&()>:
2897 task_base_shared_state<R&()>
2898#endif
2899#else
2900 template<typename F, typename R>
2901 struct task_shared_state<F,R&>:
2902 task_base_shared_state<R&>
2903#endif
2904 {
2905 private:
2906 task_shared_state(task_shared_state&);
2907 public:
2908 F f;
2909 task_shared_state(F const& f_):
2910 f(f_)
2911 {}
2912 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
2913 f(boost::move(f_))
2914 {}
2915
2916 F callable()
2917 {
2918 return f;
2919 }
2920
2921#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2922 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2923 {
2924 try
2925 {
2926 this->set_value_at_thread_exit(f(boost::move(args)...));
2927 }
2928#else
2929 void do_apply()
2930 {
2931 try
2932 {
2933 this->set_value_at_thread_exit(f());
2934 }
2935#endif
2936 catch(...)
2937 {
2938 this->set_exception_at_thread_exit(current_exception());
2939 }
2940 }
2941
2942#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2943 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2944 {
2945 try
2946 {
2947 this->mark_finished_with_result(f(boost::move(args)...));
2948 }
2949#else
2950 void do_run()
2951 {
2952 try
2953 {
2954 R& res((f()));
2955 this->mark_finished_with_result(res);
2956 }
2957#endif
2958 catch(...)
2959 {
2960 this->mark_exceptional_finish();
2961 }
2962 }
2963 };
2964
2965#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
2966
2967#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2968#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2969 template<typename R, typename ...ArgTypes>
2970 struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>:
2971 task_base_shared_state<R(ArgTypes...)>
2972#else
2973 template<typename R>
2974 struct task_shared_state<R (*)(), R()>:
2975 task_base_shared_state<R()>
2976#endif
2977#else
2978 template<typename R>
2979 struct task_shared_state<R (*)(), R> :
2980 task_base_shared_state<R>
2981#endif
2982 {
2983 private:
2984 task_shared_state(task_shared_state&);
2985#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2986 typedef R (*CallableType)(ArgTypes ... );
2987#else
2988 typedef R (*CallableType)();
2989#endif
2990 public:
2991 CallableType f;
2992 task_shared_state(CallableType f_):
2993 f(f_)
2994 {}
2995
2996 CallableType callable()
2997 {
2998 return f;
2999 }
3000
3001#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3002 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3003 {
3004 try
3005 {
3006 this->set_value_at_thread_exit(f(boost::move(args)...));
3007 }
3008#else
3009 void do_apply()
3010 {
3011 try
3012 {
3013 R r((f()));
3014 this->set_value_at_thread_exit(boost::move(r));
3015 }
3016#endif
3017 catch(...)
3018 {
3019 this->set_exception_at_thread_exit(current_exception());
3020 }
3021 }
3022
3023
3024#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3025 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3026 {
3027 try
3028 {
3029 this->mark_finished_with_result(f(boost::move(args)...));
3030 }
3031#else
3032 void do_run()
3033 {
3034 try
3035 {
3036 R res((f()));
3037 this->mark_finished_with_result(boost::move(res));
3038 }
3039#endif
3040 catch(...)
3041 {
3042 this->mark_exceptional_finish();
3043 }
3044 }
3045 };
3046#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3047#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3048 template<typename R, typename ...ArgTypes>
3049 struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>:
3050 task_base_shared_state<R&(ArgTypes...)>
3051#else
3052 template<typename R>
3053 struct task_shared_state<R& (*)(), R&()>:
3054 task_base_shared_state<R&()>
3055#endif
3056#else
3057 template<typename R>
3058 struct task_shared_state<R& (*)(), R&> :
3059 task_base_shared_state<R&>
3060#endif
3061 {
3062 private:
3063 task_shared_state(task_shared_state&);
3064 public:
3065#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3066 typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... );
3067#else
3068 typedef R& (*CallableType)();
3069#endif
3070 CallableType f;
3071 task_shared_state(CallableType f_):
3072 f(f_)
3073 {}
3074
3075 CallableType callable()
3076 {
3077 return boost::move(f);
3078 }
3079
3080#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3081 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3082 {
3083 try
3084 {
3085 this->set_value_at_thread_exit(f(boost::move(args)...));
3086 }
3087#else
3088 void do_apply()
3089 {
3090 try
3091 {
3092 this->set_value_at_thread_exit(f());
3093 }
3094#endif
3095 catch(...)
3096 {
3097 this->set_exception_at_thread_exit(current_exception());
3098 }
3099 }
3100
3101
3102#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3103 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3104 {
3105 try
3106 {
3107 this->mark_finished_with_result(f(boost::move(args)...));
3108 }
3109#else
3110 void do_run()
3111 {
3112 try
3113 {
3114 this->mark_finished_with_result(f());
3115 }
3116#endif
3117 catch(...)
3118 {
3119 this->mark_exceptional_finish();
3120 }
3121 }
3122 };
3123#endif
3124#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3125#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3126 template<typename F, typename ...ArgTypes>
3127 struct task_shared_state<F, void(ArgTypes...)>:
3128 task_base_shared_state<void(ArgTypes...)>
3129#else
3130 template<typename F>
3131 struct task_shared_state<F, void()>:
3132 task_base_shared_state<void()>
3133#endif
3134#else
3135 template<typename F>
3136 struct task_shared_state<F,void>:
3137 task_base_shared_state<void>
3138#endif
3139 {
3140 private:
3141 task_shared_state(task_shared_state&);
3142 public:
3143 typedef F CallableType;
3144 F f;
3145 task_shared_state(F const& f_):
3146 f(f_)
3147 {}
3148 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
3149 f(boost::move(f_))
3150 {}
3151 F callable()
3152 {
3153 return boost::move(f);
3154 }
3155#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3156 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3157 {
3158 try
3159 {
3160 f(boost::move(args)...);
3161#else
3162 void do_apply()
3163 {
3164 try
3165 {
3166 f();
3167#endif
3168 this->set_value_at_thread_exit();
3169 }
3170 catch(...)
3171 {
3172 this->set_exception_at_thread_exit(current_exception());
3173 }
3174 }
3175
3176#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3177 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3178 {
3179 try
3180 {
3181 f(boost::move(args)...);
3182#else
3183 void do_run()
3184 {
3185 try
3186 {
3187 f();
3188#endif
3189 this->mark_finished_with_result();
3190 }
3191 catch(...)
3192 {
3193 this->mark_exceptional_finish();
3194 }
3195 }
3196 };
3197
3198#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3199#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3200 template<typename ...ArgTypes>
3201 struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>:
3202 task_base_shared_state<void(ArgTypes...)>
3203#else
3204 template<>
3205 struct task_shared_state<void (*)(), void()>:
3206 task_base_shared_state<void()>
3207#endif
3208#else
3209 template<>
3210 struct task_shared_state<void (*)(),void>:
3211 task_base_shared_state<void>
3212#endif
3213 {
3214 private:
3215 task_shared_state(task_shared_state&);
3216#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3217 typedef void (*CallableType)(ArgTypes...);
3218#else
3219 typedef void (*CallableType)();
3220#endif
3221 public:
3222 CallableType f;
3223 task_shared_state(CallableType f_):
3224 f(f_)
3225 {}
3226 CallableType callable()
3227 {
3228 return f;
3229 }
3230#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3231 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3232 {
3233 try
3234 {
3235 f(boost::move(args)...);
3236#else
3237 void do_apply()
3238 {
3239 try
3240 {
3241 f();
3242#endif
3243 this->set_value_at_thread_exit();
3244 }
3245 catch(...)
3246 {
3247 this->set_exception_at_thread_exit(current_exception());
3248 }
3249 }
3250
3251#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3252 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3253 {
3254 try
3255 {
3256 f(boost::move(args)...);
3257#else
3258 void do_run()
3259 {
3260 try
3261 {
3262 f();
3263#endif
3264 this->mark_finished_with_result();
3265 }
3266 catch(...)
3267 {
3268 this->mark_exceptional_finish();
3269 }
3270 }
3271 };
3272 }
3273
3274#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3275 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3276 template<typename R, typename ...ArgTypes>
3277 class packaged_task<R(ArgTypes...)>
3278 {
3279 typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr;
3280 boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task;
3281 #else
3282 template<typename R>
3283 class packaged_task<R()>
3284 {
3285 typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr;
3286 boost::shared_ptr<detail::task_base_shared_state<R()> > task;
3287 #endif
3288#else
3289 template<typename R>
3290 class packaged_task
3291 {
3292 typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr;
3293 boost::shared_ptr<detail::task_base_shared_state<R> > task;
3294#endif
3295 bool future_obtained;
3296 struct dummy;
3297
3298 public:
3299 typedef R result_type;
3300 BOOST_THREAD_MOVABLE_ONLY(packaged_task)
3301
3302 packaged_task():
3303 future_obtained(false)
3304 {}
3305
3306 // construction and destruction
3307#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3308
3309#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3310 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3311 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
3312 {
3313 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3314 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3315 task= task_ptr(new task_shared_state_type(f, boost::move(args)...));
3316 future_obtained=false;
3317 }
3318 #else
3319 explicit packaged_task(R(*f)())
3320 {
3321 typedef R(*FR)();
3322 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3323 task= task_ptr(new task_shared_state_type(f));
3324 future_obtained=false;
3325 }
3326 #endif
3327#else
3328 explicit packaged_task(R(*f)())
3329 {
3330 typedef R(*FR)();
3331 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3332 task= task_ptr(new task_shared_state_type(f));
3333 future_obtained=false;
3334 }
3335#endif
3336#endif
3337#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
3338 template <class F>
3339 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
3340 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3341 )
3342 {
3343 typedef typename decay<F>::type FR;
3344#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3345 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3346 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3347 #else
3348 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3349 #endif
3350#else
3351 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3352#endif
3353 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
3354 future_obtained = false;
3355
3356 }
3357
3358#else
3359 template <class F>
3360 explicit packaged_task(F const& f
3361 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3362 )
3363 {
3364#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3365 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3366 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3367 #else
3368 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3369 #endif
3370#else
3371 typedef detail::task_shared_state<F,R> task_shared_state_type;
3372#endif
3373 task = task_ptr(new task_shared_state_type(f));
3374 future_obtained=false;
3375 }
3376 template <class F>
3377 explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
3378 {
3379#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3380#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3381 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3382 task = task_ptr(new task_shared_state_type(boost::move(f)));
3383#else
3384 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3385 task = task_ptr(new task_shared_state_type(boost::move(f)));
3386#endif
3387#else
3388 typedef detail::task_shared_state<F,R> task_shared_state_type;
3389 task = task_ptr(new task_shared_state_type(boost::move(f)));
3390#endif
3391 future_obtained=false;
3392
3393 }
3394#endif
3395
3396#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3397#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3398 template <class Allocator>
3399 packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
3400 {
3401 typedef R(*FR)();
3402#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3403 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3404 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3405 #else
3406 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3407 #endif
3408#else
3409 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3410#endif
3411 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3412 A2 a2(a);
3413 typedef thread_detail::allocator_destructor<A2> D;
3414
3415 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3416 future_obtained = false;
3417 }
3418#endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3419
3420#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3421 template <class F, class Allocator>
3422 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
3423 {
3424 typedef typename decay<F>::type FR;
3425
3426#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3427 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3428 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3429 #else
3430 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3431 #endif
3432#else
3433 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3434#endif
3435 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3436 A2 a2(a);
3437 typedef thread_detail::allocator_destructor<A2> D;
3438
3439 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
3440 future_obtained = false;
3441 }
3442#else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3443 template <class F, class Allocator>
3444 packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
3445 {
3446#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3447 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3448 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3449 #else
3450 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3451 #endif
3452#else
3453 typedef detail::task_shared_state<F,R> task_shared_state_type;
3454#endif
3455 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3456 A2 a2(a);
3457 typedef thread_detail::allocator_destructor<A2> D;
3458
3459 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3460 future_obtained = false;
3461 }
3462 template <class F, class Allocator>
3463 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
3464 {
3465#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3466 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3467 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3468 #else
3469 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3470 #endif
3471#else
3472 typedef detail::task_shared_state<F,R> task_shared_state_type;
3473#endif
3474 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3475 A2 a2(a);
3476 typedef thread_detail::allocator_destructor<A2> D;
3477
3478 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) );
3479 future_obtained = false;
3480 }
3481
3482#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
3483#endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3484
3485 ~packaged_task() {
3486 if(task) {
3487 task->owner_destroyed();
3488 }
3489 }
3490
3491 // assignment
3492 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
3493 : future_obtained(BOOST_THREAD_RV(other).future_obtained) {
3494 task.swap(BOOST_THREAD_RV(other).task);
3495 BOOST_THREAD_RV(other).future_obtained=false;
3496 }
3497 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT {
3498
3499#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3500 packaged_task temp(boost::move(other));
3501#else
3502 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
3503#endif
3504 swap(temp);
3505 return *this;
3506 }
3507
3508#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
3509 void set_executor(executor_ptr_type aex)
3510 {
3511 if (!valid())
3512 boost::throw_exception(task_moved());
3513 boost::lock_guard<boost::mutex> lk(task->mutex);
3514 task->set_executor_policy(aex, lk);
3515 }
3516#endif
3517 void reset() {
3518 if (!valid())
3519 boost::throw_exception(future_error(system::make_error_code(future_errc::no_state)));
3520
3521 // As if *this = packaged_task(task->callable());
3522
3523 task->reset();
3524 future_obtained=false;
3525 }
3526
3527 void swap(packaged_task& other) BOOST_NOEXCEPT {
3528 task.swap(other.task);
3529 std::swap(future_obtained,other.future_obtained);
3530 }
3531 bool valid() const BOOST_NOEXCEPT {
3532 return task.get()!=0;
3533 }
3534
3535 // result retrieval
3536 BOOST_THREAD_FUTURE<R> get_future() {
3537 if(!task) {
3538 boost::throw_exception(task_moved());
3539 } else if(!future_obtained) {
3540 future_obtained=true;
3541 return BOOST_THREAD_FUTURE<R>(task);
3542 } else {
3543 boost::throw_exception(future_already_retrieved());
3544 }
3545 }
3546
3547 // execution
3548#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3549 void operator()(ArgTypes... args) {
3550 if(!task) {
3551 boost::throw_exception(task_moved());
3552 }
3553 task->run(boost::move(args)...);
3554 }
3555 void make_ready_at_thread_exit(ArgTypes... args) {
3556 if(!task) {
3557 boost::throw_exception(task_moved());
3558 }
3559 if (task->has_value()) {
3560 boost::throw_exception(promise_already_satisfied());
3561 }
3562 task->apply(boost::move(args)...);
3563 }
3564#else
3565 void operator()() {
3566 if(!task) {
3567 boost::throw_exception(task_moved());
3568 }
3569 task->run();
3570 }
3571 void make_ready_at_thread_exit() {
3572 if(!task) {
3573 boost::throw_exception(task_moved());
3574 }
3575 if (task->has_value()) boost::throw_exception(promise_already_satisfied());
3576 task->apply();
3577 }
3578#endif
3579 template<typename F>
3580 void set_wait_callback(F f) {
3581 task->set_wait_callback(f,this);
3582 }
3583 };
3584}
3585#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3586namespace boost { namespace container {
3587 template <class R, class Alloc>
3588 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
3589 {};
3590}}
3591#if ! defined BOOST_NO_CXX11_ALLOCATOR
3592namespace std {
3593 template <class R, class Alloc>
3594 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
3595 {};
3596}
3597#endif
3598#endif
3599
3600namespace boost
3601{
3602 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
3603
3604namespace detail
3605{
3606 ////////////////////////////////
3607 // make_future_deferred_shared_state
3608 ////////////////////////////////
3609 template <class Rp, class Fp>
3610 BOOST_THREAD_FUTURE<Rp>
3611 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
3612 shared_ptr<future_deferred_shared_state<Rp, Fp> >
3613 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
3614 return BOOST_THREAD_FUTURE<Rp>(h);
3615 }
3616
3617 ////////////////////////////////
3618 // make_future_async_shared_state
3619 ////////////////////////////////
3620 template <class Rp, class Fp>
3621 BOOST_THREAD_FUTURE<Rp>
3622 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
3623 shared_ptr<future_async_shared_state<Rp, Fp> >
3624 h(new future_async_shared_state<Rp, Fp>());
3625 h->init(boost::forward<Fp>(f));
3626 return BOOST_THREAD_FUTURE<Rp>(h);
3627 }
3628}
3629
3630 ////////////////////////////////
3631 // template <class F, class... ArgTypes>
3632 // future<R> async(launch policy, F&&, ArgTypes&&...);
3633 ////////////////////////////////
3634
3635#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3636
3637#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3638 template <class R, class... ArgTypes>
3639 BOOST_THREAD_FUTURE<R>
3640 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3641 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3642 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3643 typedef typename BF::result_type Rp;
3644
3645 if (underlying_cast<int>(policy) & int(launch::async)) {
3646 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3647 BF(
3648 f
3649 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3650 )
3651 ));
3652 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3653 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3654 BF(
3655 f
3656 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3657 )
3658 ));
3659 } else {
3660 std::terminate();
3661 //BOOST_THREAD_FUTURE<R> ret;
3662 //return ::boost::move(ret);
3663 }
3664 }
3665
3666#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3667
3668 template <class R>
3669 BOOST_THREAD_FUTURE<R>
3670 async(launch policy, R(*f)()) {
3671 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3672 typedef packaged_task<R()> packaged_task_type;
3673 #else
3674 typedef packaged_task<R> packaged_task_type;
3675 #endif
3676
3677 if (underlying_cast<int>(policy) & int(launch::async)) {
3678 packaged_task_type pt( f );
3679 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
3680 ret.set_async();
3681 boost::thread( boost::move(pt) ).detach();
3682 return ::boost::move(ret);
3683 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3684 std::terminate();
3685 //BOOST_THREAD_FUTURE<R> ret;
3686 //return ::boost::move(ret);
3687 } else {
3688 std::terminate();
3689 //BOOST_THREAD_FUTURE<R> ret;
3690 //return ::boost::move(ret);
3691 }
3692 }
3693#endif
3694#endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3695
3696#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3697
3698 template <class F, class ...ArgTypes>
3699 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3700 typename decay<ArgTypes>::type...
3701 )>::type>
3702 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3703 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3704 typedef typename BF::result_type Rp;
3705
3706 if (underlying_cast<int>(policy) & int(launch::async)) {
3707 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3708 BF(
3709 thread_detail::decay_copy(boost::forward<F>(f))
3710 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3711 )
3712 ));
3713 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3714 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3715 BF(
3716 thread_detail::decay_copy(boost::forward<F>(f))
3717 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3718 )
3719 ));
3720 } else {
3721 std::terminate();
3722 //BOOST_THREAD_FUTURE<R> ret;
3723 //return ::boost::move(ret);
3724 }
3725 }
3726
3727#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3728
3729 template <class F>
3730 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3731 async(launch policy, BOOST_THREAD_FWD_REF(F) f) {
3732 typedef typename boost::result_of<typename decay<F>::type()>::type R;
3733#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3734 typedef packaged_task<R()> packaged_task_type;
3735#else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3736 typedef packaged_task<R> packaged_task_type;
3737#endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3738
3739 if (underlying_cast<int>(policy) & int(launch::async)) {
3740 packaged_task_type pt( boost::forward<F>(f) );
3741 BOOST_THREAD_FUTURE<R> ret = pt.get_future();
3742 ret.set_async();
3743 boost::thread( boost::move(pt) ).detach();
3744 return ::boost::move(ret);
3745 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3746 std::terminate();
3747 //BOOST_THREAD_FUTURE<R> ret;
3748 //return ::boost::move(ret);
3749 // return boost::detail::make_future_deferred_shared_state<Rp>(
3750 // BF(
3751 // thread_detail::decay_copy(boost::forward<F>(f))
3752 // )
3753 // );
3754 } else {
3755 std::terminate();
3756 //BOOST_THREAD_FUTURE<R> ret;
3757 //return ::boost::move(ret);
3758 }
3759 }
3760#endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3761
3762#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
3763namespace detail {
3764
3765 /////////////////////////
3766 /// shared_state_nullary_task
3767 /////////////////////////
3768 template<typename Rp, typename Fp>
3769 struct shared_state_nullary_task
3770 {
3771
3772 typedef shared_ptr<shared_state_base > storage_type;
3773 storage_type that;
3774 Fp f_;
3775 public:
3776
3777 shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f)
3778 : that(st), f_(boost::move(f))
3779 {};
3780
3781#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
3782 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
3783 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
3784 : that(x.that), f_(x.f_)
3785 {}
3786 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
3787 {
3788 if (this != &x) {
3789 that=x.that;
3790 f_=x.f_;
3791 }
3792 return *this;
3793 }
3794 // move
3795 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
3796 : that(x.that), f_(boost::move(x.f_))
3797 {
3798 x.that.reset();
3799 }
3800 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
3801 {
3802 if (this != &x) {
3803 that=x.that;
3804 f_=boost::move(x.f_);
3805 x.that.reset();
3806 }
3807 return *this;
3808 }
3809#endif
3810 void operator()() {
3811 shared_ptr<shared_state<Rp> > that_ = static_pointer_cast<shared_state<Rp> >(that);
3812 try {
3813 that_->mark_finished_with_result(f_());
3814 } catch(...) {
3815 that_->mark_exceptional_finish();
3816 }
3817 }
3818 ~shared_state_nullary_task()
3819 {
3820 }
3821 };
3822
3823 template<typename Fp>
3824 struct shared_state_nullary_task<void, Fp>
3825 {
3826 typedef shared_ptr<shared_state_base > storage_type;
3827 storage_type that;
3828 Fp f_;
3829 public:
3830 shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f)
3831 : that(st), f_(boost::move(f))
3832 {};
3833
3834#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
3835 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
3836 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
3837 : that(x.that), f_(x.f_)
3838 {}
3839 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
3840 {
3841 if (this != &x) {
3842 that=x.that;
3843 f_=x.f_;
3844 }
3845 return *this;
3846 }
3847 // move
3848 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT
3849 : that(x.that), f_(boost::move(x.f_))
3850 {
3851 x.that.reset();
3852 }
3853 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
3854 if (this != &x) {
3855 that=x.that;
3856 f_=boost::move(x.f_);
3857 x.that.reset();
3858 }
3859 return *this;
3860 }
3861#endif
3862 void operator()() {
3863 shared_ptr<shared_state<void> > that_ = static_pointer_cast<shared_state<void> >(that);
3864 try {
3865 f_();
3866 that_->mark_finished_with_result();
3867 } catch(...) {
3868 that_->mark_exceptional_finish();
3869 }
3870 }
3871 };
3872
3873}
3874 BOOST_THREAD_DCL_MOVABLE_BEG2(R,F) detail::shared_state_nullary_task<R,F> BOOST_THREAD_DCL_MOVABLE_END
3875namespace detail {
3876
3877 /////////////////////////
3878 /// future_executor_shared_state_base
3879 /////////////////////////
3880 template<typename Rp>
3881 struct future_executor_shared_state: shared_state<Rp>
3882 {
3883 typedef shared_state<Rp> base_type;
3884 protected:
3885 public:
3886 future_executor_shared_state() {
3887 }
3888
3889 template <class Fp, class Executor>
3890 void init(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f)
3891 {
3892 typedef typename decay<Fp>::type Cont;
3893 this->set_executor_policy(executor_ptr_type(new executor_ref<Executor>(ex)));
3894 shared_state_nullary_task<Rp,Cont> t(this->shared_from_this(), boost::forward<Fp>(f));
3895 ex.submit(boost::move(t));
3896 }
3897
3898 ~future_executor_shared_state() {}
3899 };
3900
3901 ////////////////////////////////
3902 // make_future_executor_shared_state
3903 ////////////////////////////////
3904 template <class Rp, class Fp, class Executor>
3905 BOOST_THREAD_FUTURE<Rp>
3906 make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) {
3907 shared_ptr<future_executor_shared_state<Rp> >
3908 h(new future_executor_shared_state<Rp>());
3909 h->init(ex, boost::forward<Fp>(f));
3910 return BOOST_THREAD_FUTURE<Rp>(h);
3911 }
3912
3913} // detail
3914
3915 ////////////////////////////////
3916 // template <class Executor, class F, class... ArgTypes>
3917 // future<R> async(Executor& ex, F&&, ArgTypes&&...);
3918 ////////////////////////////////
3919
3920//#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
3921#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
3922
3923#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3924
3925 template <class Executor, class R, class... ArgTypes>
3926 BOOST_THREAD_FUTURE<R>
3927 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3928 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3929 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3930 typedef typename BF::result_type Rp;
3931
3932 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
3933 BF(
3934 f
3935 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3936 )
3937 ));
3938 }
3939#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3940
3941 template <class Executor, class F, class ...ArgTypes>
3942 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3943 typename decay<ArgTypes>::type...
3944 )>::type>
3945 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3946 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3947 typedef typename BF::result_type Rp;
3948
3949 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
3950 BF(
3951 thread_detail::decay_copy(boost::forward<F>(f))
3952 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3953 )
3954 ));
3955 }
3956
3957#else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
3958#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3959
3960 template <class Executor, class R>
3961 BOOST_THREAD_FUTURE<R>
3962 async(Executor& ex, R(*f)()) {
3963 typedef R(*F)();
3964 typedef detail::invoker<F> BF;
3965 typedef typename BF::result_type Rp;
3966
3967 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
3968 BF(
3969 f
3970 )
3971 ));
3972 }
3973
3974 template <class Executor, class R, class A1>
3975 BOOST_THREAD_FUTURE<R>
3976 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) {
3977 typedef R(*F)(BOOST_THREAD_FWD_REF(A1));
3978 typedef detail::invoker<F, typename decay<A1>::type> BF;
3979 typedef typename BF::result_type Rp;
3980
3981 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
3982 BF(
3983 f
3984 , thread_detail::decay_copy(boost::forward<A1>(a1))
3985 )
3986 ));
3987 }
3988#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3989
3990 template <class Executor, class F>
3991 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3992 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) {
3993 typedef detail::invoker<typename decay<F>::type> BF;
3994 typedef typename BF::result_type Rp;
3995
3996 return boost::detail::make_future_executor_shared_state<Rp>(ex,
3997 BF(
3998 thread_detail::decay_copy(boost::forward<F>(f))
3999 )
4000 );
4001 }
4002
4003 template <class Executor, class F, class A1>
4004 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4005 typename decay<A1>::type
4006 )>::type>
4007 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) {
4008 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type> BF;
4009 typedef typename BF::result_type Rp;
4010
4011 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4012 BF(
4013 thread_detail::decay_copy(boost::forward<F>(f))
4014 , thread_detail::decay_copy(boost::forward<A1>(a1))
4015 )
4016 ));
4017 }
4018
4019 template <class Executor, class F, class A1, class A2>
4020 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4021 typename decay<A1>::type, typename decay<A2>::type
4022 )>::type>
4023 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) {
4024 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type, typename decay<A2>::type> BF;
4025 typedef typename BF::result_type Rp;
4026
4027 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4028 BF(
4029 thread_detail::decay_copy(boost::forward<F>(f))
4030 , thread_detail::decay_copy(boost::forward<A1>(a1))
4031 , thread_detail::decay_copy(boost::forward<A2>(a2))
4032 )
4033 ));
4034 }
4035
4036#endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4037#endif
4038
4039 ////////////////////////////////
4040 // template <class F, class... ArgTypes>
4041 // future<R> async(F&&, ArgTypes&&...);
4042 ////////////////////////////////
4043
4044#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
4045 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
4046 template <class R, class... ArgTypes>
4047 BOOST_THREAD_FUTURE<R>
4048 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4049 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
4050 }
4051 #else
4052 template <class R>
4053 BOOST_THREAD_FUTURE<R>
4054 async(R(*f)()) {
4055 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
4056 }
4057 #endif
4058#endif
4059
4060#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
4061 template <class F, class ...ArgTypes>
4062 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4063 typename decay<ArgTypes>::type...
4064 )>::type>
4065 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4066 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
4067 }
4068#else
4069 template <class F>
4070 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
4071 async(BOOST_THREAD_FWD_REF(F) f) {
4072 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
4073 }
4074#endif
4075
4076 ////////////////////////////////
4077 // make_future deprecated
4078 ////////////////////////////////
4079 template <typename T>
4080 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) {
4081 typedef typename decay<T>::type future_value_type;
4082 promise<future_value_type> p;
4083 p.set_value(boost::forward<future_value_type>(value));
4084 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4085 }
4086
4087#if defined BOOST_THREAD_USES_MOVE
4088 inline BOOST_THREAD_FUTURE<void> make_future() {
4089 promise<void> p;
4090 p.set_value();
4091 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4092 }
4093#endif
4094
4095 ////////////////////////////////
4096 // make_ready_future
4097 ////////////////////////////////
4098 namespace detail {
4099 template <class T>
4100 struct deduced_type_impl
4101 {
4102 typedef T type;
4103 };
4104
4105 template <class T>
4106 struct deduced_type_impl<reference_wrapper<T> const>
4107 {
4108 typedef T& type;
4109 };
4110 template <class T>
4111 struct deduced_type_impl<reference_wrapper<T> >
4112 {
4113 typedef T& type;
4114 };
4115#if __cplusplus > 201103L
4116 template <class T>
4117 struct deduced_type_impl<std::reference_wrapper<T> >
4118 {
4119 typedef T& type;
4120 };
4121#endif
4122 template <class T>
4123 struct deduced_type
4124 {
4125 typedef typename detail::deduced_type_impl<typename decay<T>::type>::type type;
4126 };
4127
4128 }
4129
4130
4131#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4132 template <int = 0, int..., class T>
4133#else
4134 template <class T>
4135#endif
4136 BOOST_THREAD_FUTURE<typename detail::deduced_type<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) {
4137 typedef typename detail::deduced_type<T>::type future_value_type;
4138 promise<future_value_type> p;
4139 p.set_value(boost::forward<T>(value));
4140 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4141 }
4142
4143 // explicit overloads
4144 template <class T>
4145 BOOST_THREAD_FUTURE<T> make_ready_future(typename remove_reference<T>::type & x)
4146 {
4147 promise<T> p;
4148 p.set_value(x);
4149 return p.get_future();
4150 }
4151
4152 template <class T>
4153 BOOST_THREAD_FUTURE<T> make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference<T>::type) x)
4154 {
4155 promise<T> p;
4156 p.set_value(forward<typename remove_reference<T>::type>(x));
4157 return p.get_future();
4158 }
4159
4160 // variadic overload
4161#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4162 template <class T, class ...Args>
4163 BOOST_THREAD_FUTURE<T> make_ready_future(Args&&... args)
4164 {
4165 promise<T> p;
4166 p.emplace(forward<Args>(args)...);
4167 return p.get_future();
4168
4169 }
4170#endif
4171
4172 template <typename T, typename T1>
4173 BOOST_THREAD_FUTURE<T> make_ready_no_decay_future(T1 value) {
4174 typedef T future_value_type;
4175 promise<future_value_type> p;
4176 p.set_value(value);
4177 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4178 }
4179
4180#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined BOOST_THREAD_USES_MOVE
4181 inline BOOST_THREAD_FUTURE<void> make_ready_future() {
4182 promise<void> p;
4183 p.set_value();
4184 return p.get_future();
4185 }
4186#endif
4187
4188
4189 template <typename T>
4190 BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) {
4191 promise<T> p;
4192 p.set_exception(ex);
4193 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4194 }
4195
4196 template <typename T, typename E>
4197 BOOST_THREAD_FUTURE<T> make_exceptional_future(E ex) {
4198 promise<T> p;
4199 p.set_exception(boost::copy_exception(ex));
4200 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4201 }
4202
4203 template <typename T>
4204 BOOST_THREAD_FUTURE<T> make_exceptional_future() {
4205 promise<T> p;
4206 p.set_exception(boost::current_exception());
4207 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4208 }
4209 template <typename T>
4210 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) {
4211 return make_exceptional_future<T>(ex);
4212 }
4213
4214#if 0
4215 template<typename CLOSURE>
4216 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
4217 typedef decltype(closure()) T;
4218 promise<T> p;
4219 try {
4220 p.set_value(closure());
4221 } catch(...) {
4222 p.set_exception(std::current_exception());
4223 }
4224 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4225 }
4226#endif
4227
4228 ////////////////////////////////
4229 // make_shared_future deprecated
4230 ////////////////////////////////
4231 template <typename T>
4232 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) {
4233 typedef typename decay<T>::type future_type;
4234 promise<future_type> p;
4235 p.set_value(boost::forward<T>(value));
4236 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
4237 }
4238
4239 inline shared_future<void> make_shared_future() {
4240 promise<void> p;
4241 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
4242 }
4243
4244 ////////////////////////////////
4245 // detail::future_async_continuation_shared_state
4246 ////////////////////////////////
4247#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
4248
4249namespace detail
4250{
4251 //////////////////////
4252 // detail::continuation_shared_state
4253 //////////////////////
4254 template<typename F, typename Rp, typename Fp, class ShSt=shared_state<Rp> >
4255 struct continuation_shared_state: ShSt
4256 {
4257 F parent;
4258 Fp continuation;
4259
4260 public:
4261 continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4262 : parent(boost::move(f)),
4263 continuation(boost::move(c))
4264 {
4265 }
4266
4267 void init(boost::unique_lock<boost::mutex> &lock)
4268 {
4269 parent.future_->set_continuation_ptr(this->shared_from_this(), lock);
4270 }
4271
4272 void call() {
4273 try {
4274 this->mark_finished_with_result(this->continuation(boost::move(this->parent)));
4275 } catch(...) {
4276 this->mark_exceptional_finish();
4277 }
4278 // make sure parent is really cleared to prevent memory "leaks"
4279 this->parent = F();
4280 }
4281
4282 void call(boost::unique_lock<boost::mutex>& lck) {
4283 try {
4284 relocker relock(lck);
4285
4286 // neither continuation nor parent are protected by the lock - call() must only
4287 // be called once, and no one else must modify it.
4288 Rp res = this->continuation(boost::move(this->parent));
4289
4290 // make sure parent is really cleared to prevent memory "leaks"
4291 this->parent = F();
4292
4293 relock.lock();
4294
4295 this->mark_finished_with_result_internal(boost::move(res), lck);
4296 } catch (...) {
4297 this->mark_exceptional_finish_internal(current_exception(), lck);
4298
4299 // make sure parent is really cleared to prevent memory "leaks"
4300 relocker relock(lck);
4301 this->parent = F();
4302 }
4303 }
4304
4305 static void run(shared_ptr<boost::detail::shared_state_base> that_)
4306 {
4307 continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get());
4308 that->call();
4309 }
4310
4311 ~continuation_shared_state() {}
4312 };
4313
4314 template<typename F, typename Fp, class ShSt>
4315 struct continuation_shared_state<F, void, Fp, ShSt>: ShSt
4316 {
4317 F parent;
4318 Fp continuation;
4319
4320 public:
4321 continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4322 : parent(boost::move(f)),
4323 continuation(boost::move(c))
4324 {
4325 }
4326
4327 void init(boost::unique_lock<boost::mutex> &lock)
4328 {
4329 parent.future_->set_continuation_ptr(this->shared_from_this(), lock);
4330 }
4331
4332 void call()
4333 {
4334 try {
4335 this->continuation(boost::move(this->parent));
4336 this->mark_finished_with_result();
4337 } catch(...) {
4338 this->mark_exceptional_finish();
4339 }
4340 // make sure parent is really cleared to prevent memory "leaks"
4341 this->parent = F();
4342 }
4343
4344 void call(boost::unique_lock<boost::mutex>& lck) {
4345 try {
4346 {
4347 relocker relock(lck);
4348 // neither continuation nor parent are protected by the lock - call() must only
4349 // be called once, and no one else must modify it.
4350 this->continuation(boost::move(this->parent));
4351
4352 // make sure parent is really cleared to prevent memory "leaks"
4353 this->parent = F();
4354 }
4355 this->mark_finished_with_result_internal(lck);
4356 } catch (...) {
4357 this->mark_exceptional_finish_internal(current_exception(), lck);
4358
4359 // make sure parent is really cleared to prevent memory "leaks"
4360 relocker relock(lck);
4361 this->parent = F();
4362 }
4363 }
4364
4365 static void run(shared_ptr<boost::detail::shared_state_base> that_)
4366 {
4367 continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get());
4368 that->call();
4369 }
4370
4371 ~continuation_shared_state() {}
4372 };
4373 /////////////////////////
4374 /// future_async_continuation_shared_state
4375 /////////////////////////
4376
4377 template<typename F, typename Rp, typename Fp>
4378 struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
4379 {
4380 typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
4381 public:
4382 future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4383 : base_type(boost::move(f), boost::forward<Fp>(c))
4384 { }
4385
4386 void launch_continuation() {
4387#if defined BOOST_THREAD_FUTURE_BLOCKING
4388 boost::lock_guard<boost::mutex> lk(this->mutex);
4389 this->thr_ = boost::thread(&future_async_continuation_shared_state::run, static_shared_from_this(this));
4390#else
4391 boost::thread(&base_type::run, static_shared_from_this(this)).detach();
4392#endif
4393 }
4394 };
4395
4396 /////////////////////////
4397 /// future_sync_continuation_shared_state
4398 /////////////////////////
4399
4400 template<typename F, typename Rp, typename Fp>
4401 struct future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
4402 {
4403 typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
4404 public:
4405 future_sync_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4406 : base_type(boost::move(f), boost::forward<Fp>(c))
4407 { }
4408
4409 void launch_continuation() {
4410 this->call();
4411 }
4412 };
4413
4414
4415 /////////////////////////
4416 /// future_executor_continuation_shared_state
4417 /////////////////////////
4418#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4419
4420 template <typename FutureExecutorContinuationSharedState>
4421 struct run_it {
4422 shared_ptr<FutureExecutorContinuationSharedState> that_;
4423
4424#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
4425 BOOST_THREAD_COPYABLE_AND_MOVABLE(run_it)
4426 run_it(run_it const& x) //BOOST_NOEXCEPT
4427 : that_(x.that_)
4428 {}
4429 run_it& operator=(BOOST_THREAD_COPY_ASSIGN_REF(run_it) x) //BOOST_NOEXCEPT
4430 {
4431 if (this != &x) {
4432 that_=x.that_;
4433 }
4434 return *this;
4435 }
4436 // move
4437 run_it(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT
4438 : that_(x.that_)
4439 {
4440 x.that_.reset();
4441 }
4442 run_it& operator=(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT {
4443 if (this != &x) {
4444 that_=x.that;
4445 x.that_.reset();
4446 }
4447 return *this;
4448 }
4449#endif
4450 run_it(shared_ptr<FutureExecutorContinuationSharedState> that) : that_ (that) {}
4451
4452 void operator()()
4453 {
4454 that_->run(that_);
4455 }
4456 };
4457
4458}
4459 BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::run_it<F> BOOST_THREAD_DCL_MOVABLE_END
4460
4461namespace detail {
4462
4463 template<typename F, typename Rp, typename Fp>
4464 struct future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4465 {
4466 typedef continuation_shared_state<F,Rp,Fp> base_type;
4467
4468 public:
4469 future_executor_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4470 : base_type(boost::move(f), boost::forward<Fp>(c))
4471 {
4472 }
4473
4474 template <class Ex>
4475 void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
4476 {
4477 this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
4478 this->base_type::init(lk);
4479 }
4480
4481 void launch_continuation() {
4482 run_it<base_type> fct(static_shared_from_this(this));
4483 this->get_executor()->submit(boost::move(fct));
4484 }
4485
4486 ~future_executor_continuation_shared_state() {}
4487 };
4488#endif
4489
4490 /////////////////////////
4491 /// shared_future_async_continuation_shared_state
4492 /////////////////////////
4493
4494 template<typename F, typename Rp, typename Fp>
4495 struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
4496 {
4497 typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
4498
4499 public:
4500 shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4501 : base_type(boost::move(f), boost::forward<Fp>(c))
4502 {
4503 }
4504
4505 void launch_continuation() {
4506#if defined BOOST_THREAD_FUTURE_BLOCKING
4507 boost::lock_guard<boost::mutex> lk(this->mutex);
4508 this->thr_ = boost::thread(&base_type::run, static_shared_from_this(this));
4509#else
4510 boost::thread(&base_type::run, static_shared_from_this(this)).detach();
4511#endif
4512 }
4513 };
4514
4515 /////////////////////////
4516 /// shared_future_async_continuation_shared_state
4517 /////////////////////////
4518
4519 template<typename F, typename Rp, typename Fp>
4520 struct shared_future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
4521 {
4522 typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
4523
4524 public:
4525 shared_future_sync_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4526 : base_type(boost::move(f), boost::forward<Fp>(c))
4527 {
4528 }
4529
4530 void launch_continuation() {
4531 this->call();
4532 }
4533 };
4534
4535
4536 /////////////////////////
4537 /// shared_future_executor_continuation_shared_state
4538 /////////////////////////
4539#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4540
4541 template<typename F, typename Rp, typename Fp>
4542 struct shared_future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4543 {
4544 typedef continuation_shared_state<F,Rp,Fp> base_type;
4545
4546 public:
4547
4548 shared_future_executor_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4549 : base_type(boost::move(f), boost::forward<Fp>(c))
4550 {
4551 }
4552
4553 template <class Ex>
4554 void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
4555 {
4556 this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
4557 this->base_type::init(lk);
4558 }
4559
4560 void launch_continuation() {
4561 run_it<base_type> fct(static_shared_from_this(this));
4562 this->get_executor()->submit(boost::move(fct));
4563 }
4564
4565 ~shared_future_executor_continuation_shared_state() {}
4566 };
4567
4568#endif
4569 //////////////////////////
4570 /// future_deferred_continuation_shared_state
4571 //////////////////////////
4572 template<typename F, typename Rp, typename Fp>
4573 struct future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4574 {
4575 typedef continuation_shared_state<F,Rp,Fp> base_type;
4576 public:
4577 future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4578 : base_type(boost::move(f), boost::forward<Fp>(c))
4579 {
4580 this->set_deferred();
4581 }
4582
4583 virtual void execute(boost::unique_lock<boost::mutex>& lk) {
4584 this->parent.wait();
4585 this->call(lk);
4586 }
4587
4588 virtual void launch_continuation() { }
4589 };
4590
4591 //////////////////////////
4592 /// shared_future_deferred_continuation_shared_state
4593 //////////////////////////
4594 template<typename F, typename Rp, typename Fp>
4595 struct shared_future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4596 {
4597 typedef continuation_shared_state<F,Rp,Fp> base_type;
4598
4599 public:
4600 shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4601 : base_type(boost::move(f), boost::forward<Fp>(c))
4602 {
4603 this->set_deferred();
4604 }
4605
4606 virtual void execute(boost::unique_lock<boost::mutex>& lk) {
4607 this->parent.wait();
4608 this->call(lk);
4609 }
4610
4611 virtual void launch_continuation() { }
4612 };
4613
4614 ////////////////////////////////
4615 // make_future_deferred_continuation_shared_state
4616 ////////////////////////////////
4617 template<typename F, typename Rp, typename Fp>
4618 BOOST_THREAD_FUTURE<Rp>
4619 make_future_deferred_continuation_shared_state(
4620 boost::unique_lock<boost::mutex> &lock,
4621 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) {
4622 typedef typename decay<Fp>::type Cont;
4623 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Cont> >
4624 h(new future_deferred_continuation_shared_state<F, Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4625 h->init(lock);
4626 return BOOST_THREAD_FUTURE<Rp>(h);
4627 }
4628
4629 ////////////////////////////////
4630 // make_future_async_continuation_shared_state
4631 ////////////////////////////////
4632 template<typename F, typename Rp, typename Fp>
4633 BOOST_THREAD_FUTURE<Rp>
4634 make_future_async_continuation_shared_state(
4635 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4636 BOOST_THREAD_FWD_REF(Fp) c) {
4637 typedef typename decay<Fp>::type Cont;
4638 shared_ptr<future_async_continuation_shared_state<F,Rp, Cont> >
4639 h(new future_async_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4640 h->init(lock);
4641
4642 return BOOST_THREAD_FUTURE<Rp>(h);
4643 }
4644 ////////////////////////////////
4645 // make_future_sync_continuation_shared_state
4646 ////////////////////////////////
4647 template<typename F, typename Rp, typename Fp>
4648 BOOST_THREAD_FUTURE<Rp>
4649 make_future_sync_continuation_shared_state(
4650 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4651 BOOST_THREAD_FWD_REF(Fp) c) {
4652 typedef typename decay<Fp>::type Cont;
4653 shared_ptr<future_sync_continuation_shared_state<F,Rp, Cont> >
4654 h(new future_sync_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4655 h->init(lock);
4656
4657 return BOOST_THREAD_FUTURE<Rp>(h);
4658 }
4659
4660 ////////////////////////////////
4661 // make_future_executor_continuation_shared_state
4662 ////////////////////////////////
4663#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4664
4665 template<typename Ex, typename F, typename Rp, typename Fp>
4666 BOOST_THREAD_FUTURE<Rp>
4667 make_future_executor_continuation_shared_state(Ex& ex,
4668 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4669 BOOST_THREAD_FWD_REF(Fp) c) {
4670 typedef typename decay<Fp>::type Cont;
4671 shared_ptr<future_executor_continuation_shared_state<F,Rp, Cont> >
4672 h(new future_executor_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4673 h->init(lock, ex);
4674
4675 return BOOST_THREAD_FUTURE<Rp>(h);
4676 }
4677#endif
4678
4679 ////////////////////////////////
4680 // make_shared_future_deferred_continuation_shared_state
4681 ////////////////////////////////
4682 template<typename F, typename Rp, typename Fp>
4683 BOOST_THREAD_FUTURE<Rp>
4684 make_shared_future_deferred_continuation_shared_state(
4685 boost::unique_lock<boost::mutex> &lock,
4686 F f, BOOST_THREAD_FWD_REF(Fp) c) {
4687 typedef typename decay<Fp>::type Cont;
4688 shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Cont> >
4689 h(new shared_future_deferred_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c)));
4690 h->init(lock);
4691
4692 return BOOST_THREAD_FUTURE<Rp>(h);
4693 }
4694 ////////////////////////////////
4695 // make_shared_future_async_continuation_shared_state
4696 ////////////////////////////////
4697 template<typename F, typename Rp, typename Fp>
4698 BOOST_THREAD_FUTURE<Rp>
4699 make_shared_future_async_continuation_shared_state(
4700 boost::unique_lock<boost::mutex> &lock, F f,
4701 BOOST_THREAD_FWD_REF(Fp) c) {
4702 typedef typename decay<Fp>::type Cont;
4703 shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Cont> >
4704 h(new shared_future_async_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
4705 h->init(lock);
4706
4707 return BOOST_THREAD_FUTURE<Rp>(h);
4708 }
4709 ////////////////////////////////
4710 // make_shared_future_sync_continuation_shared_state
4711 ////////////////////////////////
4712 template<typename F, typename Rp, typename Fp>
4713 BOOST_THREAD_FUTURE<Rp>
4714 make_shared_future_sync_continuation_shared_state(
4715 boost::unique_lock<boost::mutex> &lock, F f,
4716 BOOST_THREAD_FWD_REF(Fp) c) {
4717 typedef typename decay<Fp>::type Cont;
4718 shared_ptr<shared_future_sync_continuation_shared_state<F,Rp, Cont> >
4719 h(new shared_future_sync_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
4720 h->init(lock);
4721
4722 return BOOST_THREAD_FUTURE<Rp>(h);
4723 }
4724 ////////////////////////////////
4725 // make_shared_future_executor_continuation_shared_state
4726 ////////////////////////////////
4727#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4728 template<typename Ex, typename F, typename Rp, typename Fp>
4729 BOOST_THREAD_FUTURE<Rp>
4730 make_shared_future_executor_continuation_shared_state(Ex& ex,
4731 boost::unique_lock<boost::mutex> &lock, F f,
4732 BOOST_THREAD_FWD_REF(Fp) c) {
4733 typedef typename decay<Fp>::type Cont;
4734 shared_ptr<shared_future_executor_continuation_shared_state<F, Rp, Cont> >
4735 h(new shared_future_executor_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c)));
4736 h->init(lock, ex);
4737
4738 return BOOST_THREAD_FUTURE<Rp>(h);
4739 }
4740#endif
4741}
4742
4743 ////////////////////////////////
4744 // template<typename F>
4745 // auto future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4746 ////////////////////////////////
4747 template <typename R>
4748 template <typename F>
4749 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
4750 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
4751 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4752 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
4753
4754 // keep state alive as we move ourself but hold the lock
4755 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4756 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4757
4758 if (underlying_cast<int>(policy) & int(launch::async)) {
4759 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4760 lock, boost::move(*this), boost::forward<F>(func)
4761 )));
4762 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
4763 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4764 lock, boost::move(*this), boost::forward<F>(func)
4765 )));
4766#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4767 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
4768 assert(this->future_->get_executor());
4769 typedef executor Ex;
4770 Ex& ex = *(this->future_->get_executor());
4771 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4772 lock, boost::move(*this), boost::forward<F>(func)
4773 )));
4774#endif
4775 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
4776
4777 launch policy_ = this->launch_policy(lock);
4778 if (underlying_cast<int>(policy_) & int(launch::async)) {
4779 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4780 lock, boost::move(*this), boost::forward<F>(func)
4781 )));
4782 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
4783 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4784 lock, boost::move(*this), boost::forward<F>(func)
4785 )));
4786#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4787 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
4788 assert(this->future_->get_executor());
4789 typedef executor Ex;
4790 Ex& ex = *(this->future_->get_executor());
4791 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4792 lock, boost::move(*this), boost::forward<F>(func)
4793 )));
4794#endif
4795 } else {
4796 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4797 lock, boost::move(*this), boost::forward<F>(func)
4798 )));
4799 }
4800 } else {
4801 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4802 lock, boost::move(*this), boost::forward<F>(func)
4803 )));
4804 }
4805 }
4806#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4807 ////////////////////////////////
4808 // template<typename Ex, typename F>
4809 // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4810 ////////////////////////////////
4811 template <typename R>
4812 template <typename Ex, typename F>
4813 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
4814 BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
4815 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4816 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
4817
4818 // keep state alive as we move ourself but hold the lock
4819 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4820 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4821
4822 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4823 lock, boost::move(*this), boost::forward<F>(func)
4824 )));
4825 }
4826#endif
4827 ////////////////////////////////
4828 // template<typename F>
4829 // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4830 ////////////////////////////////
4831 template <typename R>
4832 template <typename F>
4833 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
4834 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) {
4835
4836#ifndef BOOST_THREAD_CONTINUATION_SYNC
4837 return this->then(this->launch_policy(), boost::forward<F>(func));
4838#else
4839 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4840 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
4841
4842 // keep state alive as we move ourself but hold the lock
4843 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4844 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4845
4846 launch policy = this->launch_policy(lock);
4847 if (underlying_cast<int>(policy) & int(launch::deferred)) {
4848 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4849 lock, boost::move(*this), boost::forward<F>(func)
4850 )));
4851 } else {
4852 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4853 lock, boost::move(*this), boost::forward<F>(func)
4854 )));
4855 }
4856#endif
4857
4858 }
4859
4860 ////////////////////////////////
4861 // template<typename F>
4862 // auto future<future<R2> >::then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4863 ////////////////////////////////
4864 template <typename R2>
4865 template <typename F>
4866 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
4867 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
4868 typedef BOOST_THREAD_FUTURE<R2> R;
4869 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4870 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
4871
4872 // keep state alive as we move ourself but hold the lock
4873 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4874 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4875
4876 if (underlying_cast<int>(policy) & int(launch::async)) {
4877 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4878 lock, boost::move(*this), boost::forward<F>(func)
4879 )));
4880 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
4881 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4882 lock, boost::move(*this), boost::forward<F>(func)
4883 )));
4884 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
4885 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4886 lock, boost::move(*this), boost::forward<F>(func)
4887 )));
4888#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4889 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
4890 assert(this->future_->get_executor());
4891 typedef executor Ex;
4892 Ex& ex = *(this->future_->get_executor());
4893 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4894 lock, boost::move(*this), boost::forward<F>(func)
4895 )));
4896#endif
4897 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
4898 launch policy_ = this->launch_policy(lock);
4899
4900 if (underlying_cast<int>(policy_) & int(launch::async)) {
4901 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4902 lock, boost::move(*this), boost::forward<F>(func)
4903 )));
4904 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
4905 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4906 lock, boost::move(*this), boost::forward<F>(func)
4907 )));
4908 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
4909 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4910 lock, boost::move(*this), boost::forward<F>(func)
4911 )));
4912#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4913 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
4914 assert(this->future_->get_executor());
4915 typedef executor Ex;
4916 Ex& ex = *(this->future_->get_executor());
4917 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4918 lock, boost::move(*this), boost::forward<F>(func)
4919 )));
4920#endif
4921 } else {
4922 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4923 lock, boost::move(*this), boost::forward<F>(func)
4924 )));
4925 }
4926 } else {
4927 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4928 lock, boost::move(*this), boost::forward<F>(func)
4929 )));
4930 }
4931 }
4932
4933#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4934 ////////////////////////////////
4935 // template<typename Ex, typename F>
4936 // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4937 ////////////////////////////////
4938 template <typename R2>
4939 template <typename Ex, typename F>
4940 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
4941 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
4942 typedef BOOST_THREAD_FUTURE<R2> R;
4943 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4944 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
4945
4946 // keep state alive as we move ourself but hold the lock
4947 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4948 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4949
4950 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4951 lock, boost::move(*this), boost::forward<F>(func)
4952 )));
4953 }
4954#endif
4955
4956 ////////////////////////////////
4957 // template<typename F>
4958 // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4959 ////////////////////////////////
4960 template <typename R2>
4961 template <typename F>
4962 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
4963 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) {
4964
4965#ifndef BOOST_THREAD_CONTINUATION_SYNC
4966 return this->then(this->launch_policy(), boost::forward<F>(func));
4967#else
4968 typedef BOOST_THREAD_FUTURE<R2> R;
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());
4971
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);
4975
4976 launch policy = this->launch_policy(lock);
4977
4978 if (underlying_cast<int>(policy) & int(launch::deferred)) {
4979 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4980 lock, boost::move(*this), boost::forward<F>(func)
4981 )));
4982 } else {
4983 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4984 lock, boost::move(*this), boost::forward<F>(func)
4985 )));
4986 }
4987#endif
4988 }
4989
4990 ////////////////////////////////
4991 // template<typename F>
4992 // auto shared_future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4993 ////////////////////////////////
4994 template <typename R>
4995 template <typename F>
4996 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
4997 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const
4998 {
4999 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5000 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5001
5002 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5003 if (underlying_cast<int>(policy) & int(launch::async)) {
5004 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5005 lock, *this, boost::forward<F>(func)
5006 )));
5007 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
5008 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5009 lock, *this, boost::forward<F>(func)
5010 )));
5011 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
5012 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5013 lock, *this, boost::forward<F>(func)
5014 )));
5015#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5016 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
5017 typedef executor Ex;
5018 Ex& ex = *(this->future_->get_executor());
5019 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5020 lock, *this, boost::forward<F>(func)
5021 )));
5022#endif
5023 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
5024
5025 launch policy_ = this->launch_policy(lock);
5026 if (underlying_cast<int>(policy_) & int(launch::async)) {
5027 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5028 lock, *this, boost::forward<F>(func)
5029 )));
5030 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
5031 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5032 lock, *this, boost::forward<F>(func)
5033 )));
5034 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
5035 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5036 lock, *this, boost::forward<F>(func)
5037 )));
5038#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5039 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
5040 typedef executor Ex;
5041 Ex& ex = *(this->future_->get_executor());
5042 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5043 lock, *this, boost::forward<F>(func)
5044 )));
5045#endif
5046 } else {
5047 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5048 lock, *this, boost::forward<F>(func)
5049 )));
5050 }
5051
5052 } else {
5053 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5054 lock, *this, boost::forward<F>(func)
5055 )));
5056 }
5057 }
5058#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5059 ////////////////////////////////
5060 // template<typename Ex, typename F>
5061 // auto shared_future<R>::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5062 ////////////////////////////////
5063 template <typename R>
5064 template <typename Ex, typename F>
5065 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5066 shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const
5067 {
5068 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5069 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5070
5071 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5072 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5073 lock, *this, boost::forward<F>(func)
5074 )));
5075 }
5076#endif
5077
5078 ////////////////////////////////
5079 // template<typename F>
5080 // auto shared_future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5081 ////////////////////////////////
5082 template <typename R>
5083 template <typename F>
5084 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5085 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const {
5086#ifndef BOOST_THREAD_CONTINUATION_SYNC
5087 return this->then(this->launch_policy(), boost::forward<F>(func));
5088#else
5089 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5090 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5091
5092 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5093 launch policy = this->launch_policy(lock);
5094 if (underlying_cast<int>(policy) & int(launch::deferred)) {
5095 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5096 lock, *this, boost::forward<F>(func)
5097 )));
5098 } else {
5099 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5100 lock, *this, boost::forward<F>(func)
5101 )));
5102 }
5103#endif
5104 }
5105
5106namespace detail
5107{
5108 template <typename T>
5109 struct mfallbacker_to
5110 {
5111 T value_;
5112 typedef T result_type;
5113 mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
5114 : value_(boost::move(v))
5115 {}
5116
5117 T operator()(BOOST_THREAD_FUTURE<T> fut) {
5118 return fut.get_or(boost::move(value_));
5119 }
5120 };
5121 template <typename T>
5122 struct cfallbacker_to
5123 {
5124 T value_;
5125 typedef T result_type;
5126 cfallbacker_to(T const& v)
5127 : value_(v)
5128 {}
5129
5130 T operator()(BOOST_THREAD_FUTURE<T> fut) const {
5131 return fut.get_or(value_);
5132
5133 }
5134 };
5135}
5136 ////////////////////////////////
5137 // future<R> future<R>::fallback_to(R&& v);
5138 ////////////////////////////////
5139
5140 template <typename R>
5141 template <typename R2>
5142 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
5143 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) {
5144 return then(detail::mfallbacker_to<R>(boost::move(v)));
5145 }
5146
5147 template <typename R>
5148 template <typename R2>
5149 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
5150 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) {
5151 return then(detail::cfallbacker_to<R>(v));
5152 }
5153
5154#endif
5155
5156#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
5157namespace detail
5158{
5159 /////////////////////////
5160 /// future_unwrap_shared_state
5161 /////////////////////////
5162
5163 template<typename F, typename Rp>
5164 struct future_unwrap_shared_state: shared_state<Rp>
5165 {
5166 F wrapped;
5167 typename F::value_type unwrapped;
5168 public:
5169 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
5170 : wrapped(boost::move(f)) {
5171 }
5172
5173 void launch_continuation()
5174 {
5175 boost::unique_lock<boost::mutex> lk(this->mutex);
5176 // assert(wrapped.is_ready());
5177 if (! unwrapped.valid() )
5178 {
5179 if (wrapped.has_exception()) {
5180 this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk);
5181 } else {
5182 unwrapped = wrapped.get();
5183 if (unwrapped.valid())
5184 {
5185 lk.unlock();
5186 boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex);
5187 unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2);
5188 } else {
5189 this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk);
5190 }
5191 }
5192 } else {
5193 // assert(unwrapped.is_ready());
5194 if (unwrapped.has_exception()) {
5195 this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk);
5196 } else {
5197 this->mark_finished_with_result_internal(unwrapped.get(), lk);
5198 }
5199 }
5200 }
5201 };
5202
5203 template<typename F>
5204 struct future_unwrap_shared_state<F,void>: shared_state<void>
5205 {
5206 F wrapped;
5207 typename F::value_type unwrapped;
5208 public:
5209 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
5210 : wrapped(boost::move(f)) {
5211 }
5212
5213 void launch_continuation()
5214 {
5215 boost::unique_lock<boost::mutex> lk(this->mutex);
5216 // assert(wrapped.is_ready());
5217 if (! unwrapped.valid() )
5218 {
5219 if (wrapped.has_exception()) {
5220 this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk);
5221 } else {
5222 unwrapped = wrapped.get();
5223 if (unwrapped.valid())
5224 {
5225 lk.unlock();
5226 boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex);
5227 unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2);
5228 } else {
5229 this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk);
5230 }
5231 }
5232 } else {
5233 // assert(unwrapped.is_ready());
5234 if (unwrapped.has_exception()) {
5235 this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk);
5236 } else {
5237 this->mark_finished_with_result_internal(lk);
5238 }
5239 }
5240 }
5241 };
5242
5243 template <class F, class Rp>
5244 BOOST_THREAD_FUTURE<Rp>
5245 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) {
5246 shared_ptr<future_unwrap_shared_state<F, Rp> >
5247 h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
5248 h->wrapped.future_->set_continuation_ptr(h, lock);
5249
5250 return BOOST_THREAD_FUTURE<Rp>(h);
5251 }
5252}
5253
5254 template <typename R>
5255 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other)
5256 : base_type(other.unwrap()) {}
5257
5258 template <typename R2>
5259 BOOST_THREAD_FUTURE<R2>
5260 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
5261 {
5262 BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
5263
5264 // keep state alive as we move ourself but hold the lock
5265 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5266 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5267
5268 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
5269 }
5270#endif
5271
5272#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
5273namespace detail
5274{
5275 struct input_iterator_tag {};
5276 struct vector_tag {};
5277 struct values_tag {};
5278 template <typename T>
5279 struct alias_t { typedef T type; };
5280
5281 BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {};
5282 BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {};
5283 BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {};
5284 ////////////////////////////////
5285 // detail::future_async_when_all_shared_state
5286 ////////////////////////////////
5287 template<typename F>
5288 struct future_when_all_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
5289 {
5290 typedef csbl::vector<F> vector_type;
5291 typedef typename F::value_type value_type;
5292 vector_type vec_;
5293
5294 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
5295 future_when_all_vector_shared_state* that = static_cast<future_when_all_vector_shared_state*>(that_.get());
5296 try {
5297 boost::wait_for_all(that->vec_.begin(), that->vec_.end());
5298 that->mark_finished_with_result(boost::move(that->vec_));
5299 } catch(...) {
5300 that->mark_exceptional_finish();
5301 }
5302 }
5303 bool run_deferred() {
5304
5305 bool res = false;
5306 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
5307 if (! it->run_if_is_deferred())
5308 {
5309 res = true;
5310 }
5311 }
5312 return res;
5313 }
5314 void init() {
5315 if (! run_deferred())
5316 {
5317 future_when_all_vector_shared_state::run(this->shared_from_this());
5318 return;
5319 }
5320#ifdef BOOST_THREAD_FUTURE_BLOCKING
5321 this->thr_ = boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this());
5322#else
5323 boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this()).detach();
5324#endif
5325 }
5326
5327 public:
5328 template< typename InputIterator>
5329 future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
5330 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
5331 {
5332 }
5333
5334 future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
5335 : vec_(boost::move(v))
5336 {
5337 }
5338
5339#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5340 template< typename T0, typename ...T>
5341 future_when_all_vector_shared_state(values_tag, BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5342 vec_.push_back(boost::forward<T0>(f));
5343 typename alias_t<char[]>::type{
5344 ( //first part of magic unpacker
5345 vec_.push_back(boost::forward<T>(futures)),'0'
5346 )..., '0'
5347 }; //second part of magic unpacker
5348 }
5349#endif
5350
5351 ~future_when_all_vector_shared_state() {}
5352 };
5353
5354 ////////////////////////////////
5355 // detail::future_async_when_any_shared_state
5356 ////////////////////////////////
5357 template<typename F>
5358 struct future_when_any_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
5359 {
5360 typedef csbl::vector<F> vector_type;
5361 typedef typename F::value_type value_type;
5362 vector_type vec_;
5363
5364 static void run(shared_ptr<boost::detail::shared_state_base> that_)
5365 {
5366 future_when_any_vector_shared_state* that = static_cast<future_when_any_vector_shared_state*>(that_.get());
5367 try {
5368 boost::wait_for_any(that->vec_.begin(), that->vec_.end());
5369 that->mark_finished_with_result(boost::move(that->vec_));
5370 } catch(...) {
5371 that->mark_exceptional_finish();
5372 }
5373 }
5374 bool run_deferred() {
5375
5376 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
5377 if (it->run_if_is_deferred_or_ready())
5378 {
5379 return true;
5380 }
5381 }
5382 return false;
5383 }
5384 void init() {
5385 if (run_deferred())
5386 {
5387 future_when_any_vector_shared_state::run(this->shared_from_this());
5388 return;
5389 }
5390
5391#ifdef BOOST_THREAD_FUTURE_BLOCKING
5392 this->thr_ = boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this());
5393#else
5394 boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this()).detach();
5395#endif
5396 }
5397
5398 public:
5399 template< typename InputIterator>
5400 future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
5401 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
5402 {
5403 }
5404
5405 future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
5406 : vec_(boost::move(v))
5407 {
5408 }
5409
5410#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5411 template< typename T0, typename ...T>
5412 future_when_any_vector_shared_state(values_tag,
5413 BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures
5414 ) {
5415 vec_.push_back(boost::forward<T0>(f));
5416 typename alias_t<char[]>::type{
5417 ( //first part of magic unpacker
5418 vec_.push_back(boost::forward<T>(futures))
5419 ,'0'
5420 )...,
5421 '0'
5422 }; //second part of magic unpacker
5423 }
5424#endif
5425
5426 ~future_when_any_vector_shared_state() {}
5427 };
5428
5429#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5430 struct wait_for_all_fctr {
5431 template <class ...T>
5432 void operator()(T&&... v) {
5433 boost::wait_for_all(boost::forward<T>(v)...);
5434 }
5435 };
5436
5437 struct wait_for_any_fctr {
5438 template <class ...T>
5439 void operator()(T&&... v) {
5440 boost::wait_for_any(boost::forward<T>(v)...);
5441 }
5442 };
5443
5444
5445 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
5446 struct accumulate_run_if_is_deferred {
5447 bool operator ()(Tuple& t)
5448 {
5449 return (! csbl::get<i-1>(t).run_if_is_deferred()) || accumulate_run_if_is_deferred<Tuple,i-1>()(t);
5450 }
5451 };
5452 template <class Tuple>
5453 struct accumulate_run_if_is_deferred<Tuple, 0> {
5454 bool operator ()(Tuple& )
5455 {
5456 return false;
5457 }
5458 };
5459
5460
5461 template< typename Tuple, typename T0, typename ...T>
5462 struct future_when_all_tuple_shared_state: future_async_shared_state_base<Tuple>
5463 {
5464 Tuple tup_;
5465 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
5466
5467 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
5468 future_when_all_tuple_shared_state* that = static_cast<future_when_all_tuple_shared_state*>(that_.get());
5469 try {
5470 // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor());
5471 that->wait_for_all(Index());
5472
5473 that->mark_finished_with_result(boost::move(that->tup_));
5474 } catch(...) {
5475 that->mark_exceptional_finish();
5476 }
5477 }
5478
5479 template <size_t ...Indices>
5480 void wait_for_all(tuple_indices<Indices...>) {
5481#if defined BOOST_THREAD_PROVIDES_INVOKE
5482 return invoke<void>(wait_for_all_fctr(), csbl::get<Indices>(tup_)...);
5483#else
5484 return wait_for_all_fctr()(csbl::get<Indices>(tup_)...);
5485#endif
5486 }
5487
5488 bool run_deferred() {
5489
5490 return accumulate_run_if_is_deferred<Tuple>()(tup_);
5491 }
5492 void init() {
5493 if (! run_deferred())
5494 {
5495 future_when_all_tuple_shared_state::run(this->shared_from_this());
5496 return;
5497 }
5498#ifdef BOOST_THREAD_FUTURE_BLOCKING
5499 this->thr_ = boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this());
5500#else
5501 boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()).detach();
5502#endif
5503
5504 }
5505 public:
5506 template< typename F, typename ...Fs>
5507 future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) :
5508 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
5509 {
5510 }
5511
5512 ~future_when_all_tuple_shared_state() {}
5513
5514 };
5515
5516
5517 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
5518 struct apply_any_run_if_is_deferred_or_ready {
5519 bool operator ()(Tuple& t)
5520 {
5521 if (csbl::get<i-1>(t).run_if_is_deferred_or_ready()) return true;
5522 return apply_any_run_if_is_deferred_or_ready<Tuple,i-1>()(t);
5523 }
5524 };
5525 template <class Tuple>
5526 struct apply_any_run_if_is_deferred_or_ready<Tuple, 0> {
5527 bool operator ()(Tuple& )
5528 {
5529 return false;
5530 }
5531 };
5532
5533 template< typename Tuple, typename T0, typename ...T >
5534 struct future_when_any_tuple_shared_state: future_async_shared_state_base<Tuple>
5535 {
5536 Tuple tup_;
5537 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
5538
5539 static void run(shared_ptr<boost::detail::shared_state_base> that_)
5540 {
5541 future_when_any_tuple_shared_state* that = static_cast<future_when_any_tuple_shared_state*>(that_.get());
5542 try {
5543 // TODO make use of apply(that->tup_, wait_for_any_fctr);
5544 that->wait_for_any(Index());
5545
5546 that->mark_finished_with_result(boost::move(that->tup_));
5547 } catch(...) {
5548 that->mark_exceptional_finish();
5549 }
5550 }
5551 template <size_t ...Indices>
5552 void wait_for_any(tuple_indices<Indices...>) {
5553#if defined BOOST_THREAD_PROVIDES_INVOKE
5554 return invoke<void>(wait_for_any_fctr(), csbl::get<Indices>(tup_)...);
5555#else
5556 return wait_for_any_fctr()(csbl::get<Indices>(tup_)...);
5557#endif
5558 }
5559 bool run_deferred() {
5560 return apply_any_run_if_is_deferred_or_ready<Tuple>()(tup_);
5561 }
5562 void init() {
5563 if (run_deferred())
5564 {
5565 future_when_any_tuple_shared_state::run(this->shared_from_this());
5566 return;
5567 }
5568
5569#ifdef BOOST_THREAD_FUTURE_BLOCKING
5570 this->thr_ = boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this());
5571#else
5572 boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()).detach();
5573#endif
5574 }
5575
5576 public:
5577 template< typename F, typename ...Fs>
5578 future_when_any_tuple_shared_state(values_tag,
5579 BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures
5580 ) :
5581 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
5582 {
5583 }
5584
5585 ~future_when_any_tuple_shared_state() {}
5586 };
5587#endif
5588
5589}
5590
5591 template< typename InputIterator>
5592 typename boost::disable_if<is_future_type<InputIterator>,
5593 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
5594 >::type
5595 when_all(InputIterator first, InputIterator last) {
5596 typedef typename InputIterator::value_type value_type;
5597 typedef csbl::vector<value_type> container_type;
5598 typedef detail::future_when_all_vector_shared_state<value_type> factory_type;
5599
5600 if (first==last) return make_ready_future(container_type());
5601 shared_ptr<factory_type >
5602 h(new factory_type(detail::input_iterator_tag_value, first,last));
5603 h->init();
5604 return BOOST_THREAD_FUTURE<container_type>(h);
5605 }
5606
5607 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all() {
5608 return make_ready_future(csbl::tuple<>());
5609 }
5610
5611#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5612 template< typename T0, typename ...T>
5613 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
5614 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5615 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
5616 typedef detail::future_when_all_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
5617
5618 shared_ptr<factory_type>
5619 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
5620 h->init();
5621 return BOOST_THREAD_FUTURE<container_type>(h);
5622 }
5623#endif
5624
5625 template< typename InputIterator>
5626 typename boost::disable_if<is_future_type<InputIterator>,
5627 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
5628 >::type
5629 when_any(InputIterator first, InputIterator last) {
5630 typedef typename InputIterator::value_type value_type;
5631 typedef csbl::vector<value_type> container_type;
5632 typedef detail::future_when_any_vector_shared_state<value_type> factory_type;
5633
5634 if (first==last) return make_ready_future(container_type());
5635 shared_ptr<factory_type >
5636 h(new factory_type(detail::input_iterator_tag_value, first,last));
5637 h->init();
5638 return BOOST_THREAD_FUTURE<container_type>(h);
5639 }
5640
5641 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any() {
5642 return make_ready_future(csbl::tuple<>());
5643 }
5644
5645#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5646 template< typename T0, typename ...T>
5647 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
5648 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5649 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
5650 typedef detail::future_when_any_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
5651
5652 shared_ptr<factory_type>
5653 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
5654 h->init();
5655 return BOOST_THREAD_FUTURE<container_type>(h);
5656 }
5657#endif
5658#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
5659}
5660
5661#endif // BOOST_NO_EXCEPTIONS
5662#endif // header
5663