]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/thread/include/boost/thread/future.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / thread / include / boost / thread / future.hpp
CommitLineData
7c673cae
FG
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_ != 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 inline explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
1643
1644 explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) :
1645 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1646 {}
1647
1648 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1649 {
1650 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1651 return *this;
1652 }
1653
1654 shared_future<R> share()
1655 {
1656 return shared_future<R>(::boost::move(*this));
1657 }
1658
1659 void swap(BOOST_THREAD_FUTURE& other)
1660 {
1661 static_cast<base_type*>(this)->swap(other);
1662 }
1663
1664 // todo this function must be private and friendship provided to the internal users.
1665 void set_async()
1666 {
1667 this->future_->set_async();
1668 }
1669 // todo this function must be private and friendship provided to the internal users.
1670 void set_deferred()
1671 {
1672 this->future_->set_deferred();
1673 }
1674 bool run_if_is_deferred() {
1675 return this->future_->run_if_is_deferred();
1676 }
1677 bool run_if_is_deferred_or_ready() {
1678 return this->future_->run_if_is_deferred_or_ready();
1679 }
1680 // retrieving the value
1681 move_dest_type get()
1682 {
1683 if (this->future_ == 0)
1684 {
1685 boost::throw_exception(future_uninitialized());
1686 }
1687 unique_lock<boost::mutex> lk(this->future_->mutex);
1688 if (! this->future_->valid(lk))
1689 {
1690 boost::throw_exception(future_uninitialized());
1691 }
1692#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1693 this->future_->invalidate(lk);
1694#endif
1695 return this->future_->get(lk);
1696 }
1697
1698 template <typename R2>
1699 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1700 get_or(BOOST_THREAD_RV_REF(R2) v)
1701 {
1702
1703 if (this->future_ == 0)
1704 {
1705 boost::throw_exception(future_uninitialized());
1706 }
1707 unique_lock<boost::mutex> lk(this->future_->mutex);
1708 if (! this->future_->valid(lk))
1709 {
1710 boost::throw_exception(future_uninitialized());
1711 }
1712 this->future_->wait(lk, false);
1713#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1714 this->future_->invalidate(lk);
1715#endif
1716
1717 if (this->future_->has_value(lk)) {
1718 return this->future_->get(lk);
1719 }
1720 else {
1721 return boost::move(v);
1722 }
1723 }
1724
1725 template <typename R2>
1726 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1727 get_or(R2 const& v) // EXTENSION
1728 {
1729 if (this->future_ == 0)
1730 {
1731 boost::throw_exception(future_uninitialized());
1732 }
1733 unique_lock<boost::mutex> lk(this->future_->mutex);
1734 if (! this->future_->valid(lk))
1735 {
1736 boost::throw_exception(future_uninitialized());
1737 }
1738 this->future_->wait(lk, false);
1739#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1740 this->future_->invalidate(lk);
1741#endif
1742 if (this->future_->has_value(lk)) {
1743 return this->future_->get(lk);
1744 }
1745 else {
1746 return v;
1747 }
1748 }
1749
1750#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1751 template<typename F>
1752 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1753 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1754 template<typename F>
1755 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1756 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1757 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1758 template<typename Ex, typename F>
1759 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1760 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1761 #endif
1762
1763 template <typename R2>
1764 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1765 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION
1766 template <typename R2>
1767 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1768 fallback_to(R2 const& v); // EXTENSION
1769
1770#endif
1771
1772 };
1773
1774 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
1775
1776 template <typename R2>
1777 class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
1778 {
1779 typedef BOOST_THREAD_FUTURE<R2> R;
1780
1781 private:
1782 typedef detail::basic_future<R> base_type;
1783 typedef typename base_type::future_ptr future_ptr;
1784
1785 friend class shared_future<R>;
1786 friend class promise<R>;
1787#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1788 template <typename, typename, typename>
1789 friend struct detail::future_async_continuation_shared_state;
1790 template <typename, typename, typename>
1791 friend struct detail::future_deferred_continuation_shared_state;
1792
1793 template <class F, class Rp, class Fp>
1794 friend BOOST_THREAD_FUTURE<Rp>
1795 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);
1796
1797 template <class F, class Rp, class Fp>
1798 friend BOOST_THREAD_FUTURE<Rp>
1799 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);
1800
1801 template <class F, class Rp, class Fp>
1802 friend BOOST_THREAD_FUTURE<Rp>
1803 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);
1804
1805 template<typename F, typename Rp, typename Fp>
1806 friend BOOST_THREAD_FUTURE<Rp>
1807 detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1808
1809 template<typename F, typename Rp, typename Fp>
1810 friend BOOST_THREAD_FUTURE<Rp>
1811 detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1812
1813 template<typename F, typename Rp, typename Fp>
1814 friend BOOST_THREAD_FUTURE<Rp>
1815 detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1816
1817 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
1818 template<typename Ex, typename F, typename Rp, typename Fp>
1819 friend BOOST_THREAD_FUTURE<Rp>
1820 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);
1821
1822 template<typename Ex, typename F, typename Rp, typename Fp>
1823 friend BOOST_THREAD_FUTURE<Rp>
1824 detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
1825
1826 template <class Rp, class Fp, class Executor>
1827 friend BOOST_THREAD_FUTURE<Rp>
1828 detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f);
1829 #endif
1830
1831#endif
1832#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1833 template<typename F, typename Rp>
1834 friend struct detail::future_unwrap_shared_state;
1835 template <class F, class Rp>
1836 friend BOOST_THREAD_FUTURE<Rp>
1837 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1838#endif
1839#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY)
1840 template< typename InputIterator>
1841 friend typename boost::disable_if<is_future_type<InputIterator>,
1842 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1843 >::type
1844 when_all(InputIterator first, InputIterator last);
1845
1846 friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all();
1847
1848 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1849 template< typename T0, typename ...T>
1850 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1851 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1852 #endif
1853
1854 template< typename InputIterator>
1855 friend typename boost::disable_if<is_future_type<InputIterator>,
1856 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
1857 >::type
1858 when_any(InputIterator first, InputIterator last);
1859
1860 friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any();
1861
1862 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1863 template< typename T0, typename ...T>
1864 friend BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
1865 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures);
1866 #endif
1867#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
1868
1869 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1870 template <class> friend class packaged_task; // todo check if this works in windows
1871 #else
1872 friend class packaged_task<R>;
1873 #endif
1874 friend class detail::future_waiter;
1875
1876 template <class Rp, class Fp>
1877 friend BOOST_THREAD_FUTURE<Rp>
1878 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1879
1880 template <class Rp, class Fp>
1881 friend BOOST_THREAD_FUTURE<Rp>
1882 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1883
1884 typedef typename base_type::move_dest_type move_dest_type;
1885
1886 BOOST_THREAD_FUTURE(future_ptr a_future):
1887 base_type(a_future)
1888 {
1889 }
1890 public:
1891
1892 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1893 typedef future_state::state state;
1894 typedef R value_type; // EXTENSION
1895
1896 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
1897 //BOOST_CONSTEXPR
1898 BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
1899 base_type(ex) {}
1900
1901 ~BOOST_THREAD_FUTURE() {
1902 }
1903
1904 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
1905 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1906 {
1907 }
1908
1909 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1910 {
1911 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1912 return *this;
1913 }
1914
1915 shared_future<R> share()
1916 {
1917 return shared_future<R>(::boost::move(*this));
1918 }
1919
1920 void swap(BOOST_THREAD_FUTURE& other)
1921 {
1922 static_cast<base_type*>(this)->swap(other);
1923 }
1924
1925 // todo this function must be private and friendship provided to the internal users.
1926 void set_async()
1927 {
1928 this->future_->set_async();
1929 }
1930 // todo this function must be private and friendship provided to the internal users.
1931 void set_deferred()
1932 {
1933 this->future_->set_deferred();
1934 }
1935 bool run_if_is_deferred() {
1936 return this->future_->run_if_is_deferred();
1937 }
1938 bool run_if_is_deferred_or_ready() {
1939 return this->future_->run_if_is_deferred_or_ready();
1940 }
1941 // retrieving the value
1942 move_dest_type get()
1943 {
1944 if (this->future_ == 0)
1945 {
1946 boost::throw_exception(future_uninitialized());
1947 }
1948 unique_lock<boost::mutex> lk(this->future_->mutex);
1949 if (! this->future_->valid(lk))
1950 {
1951 boost::throw_exception(future_uninitialized());
1952 }
1953 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1954 this->future_->invalidate(lk);
1955 #endif
1956 return this->future_->get(lk);
1957 }
1958 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
1959 {
1960 if (this->future_ == 0)
1961 {
1962 boost::throw_exception(future_uninitialized());
1963 }
1964 unique_lock<boost::mutex> lk(this->future_->mutex);
1965 if (! this->future_->valid(lk))
1966 {
1967 boost::throw_exception(future_uninitialized());
1968 }
1969 this->future_->wait(lk, false);
1970 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1971 this->future_->invalidate(lk);
1972 #endif
1973 if (this->future_->has_value(lk)) return this->future_->get(lk);
1974 else return boost::move(v);
1975 }
1976
1977 move_dest_type get_or(R const& v) // EXTENSION
1978 {
1979 if (this->future_ == 0)
1980 {
1981 boost::throw_exception(future_uninitialized());
1982 }
1983 unique_lock<boost::mutex> lk(this->future_->mutex);
1984 if (! this->future_->valid(lk))
1985 {
1986 boost::throw_exception(future_uninitialized());
1987 }
1988 this->future_->wait(lk, false);
1989 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1990 this->future_->invalidate(lk);
1991 #endif
1992 if (this->future_->has_value(lk)) return this->future_->get(lk);
1993 else return v;
1994 }
1995
1996
1997 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1998 template<typename F>
1999 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2000 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2001 template<typename F>
2002 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2003 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2004 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2005 template<typename Ex, typename F>
2006 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
2007 then(Ex &ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
2008 #endif
2009 #endif
2010
2011 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
2012 inline
2013 BOOST_THREAD_FUTURE<R2>
2014 unwrap(); // EXTENSION
2015 #endif
2016
2017 };
2018
2019 template <typename R>
2020 class shared_future : public detail::basic_future<R>
2021 {
2022 typedef detail::basic_future<R> base_type;
2023 typedef typename base_type::future_ptr future_ptr;
2024
2025 friend class detail::future_waiter;
2026 friend class promise<R>;
2027
2028#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2029 template <typename, typename, typename>
2030 friend struct detail::future_async_continuation_shared_state;
2031 template <typename, typename, typename>
2032 friend struct detail::future_deferred_continuation_shared_state;
2033
2034 template <class F, class Rp, class Fp>
2035 friend BOOST_THREAD_FUTURE<Rp>
2036 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);
2037
2038 template <class F, class Rp, class Fp>
2039 friend BOOST_THREAD_FUTURE<Rp>
2040 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);
2041
2042 template <class F, class Rp, class Fp>
2043 friend BOOST_THREAD_FUTURE<Rp>
2044 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);
2045#endif
2046#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2047 template <class> friend class packaged_task;// todo check if this works in windows
2048#else
2049 friend class packaged_task<R>;
2050#endif
2051 shared_future(future_ptr a_future):
2052 base_type(a_future)
2053 {}
2054
2055 public:
2056 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future)
2057 typedef R value_type; // EXTENSION
2058
2059 shared_future(shared_future const& other):
2060 base_type(other.future_)
2061 {}
2062
2063 typedef future_state::state state;
2064
2065 BOOST_CONSTEXPR shared_future()
2066 {}
2067 //BOOST_CONSTEXPR
2068 shared_future(exceptional_ptr const& ex):
2069 base_type(ex) {}
2070 ~shared_future()
2071 {}
2072
2073 shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other)
2074 {
2075 this->future_ = other.future_;
2076 return *this;
2077 }
2078
2079 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
2080 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2081 {
2082 }
2083 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
2084 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
2085 {
2086 }
2087
2088 shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
2089 {
2090 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2091 return *this;
2092 }
2093 shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
2094 {
2095 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
2096 return *this;
2097 }
2098
2099 void swap(shared_future& other) BOOST_NOEXCEPT
2100 {
2101 static_cast<base_type*>(this)->swap(other);
2102 }
2103 bool run_if_is_deferred() {
2104 return this->future_->run_if_is_deferred();
2105 }
2106 bool run_if_is_deferred_or_ready() {
2107 return this->future_->run_if_is_deferred_or_ready();
2108 }
2109 // retrieving the value
2110 typename detail::shared_state<R>::shared_future_get_result_type get() const
2111 {
2112 if(!this->future_)
2113 {
2114 boost::throw_exception(future_uninitialized());
2115 }
2116 return this->future_->get_sh();
2117 }
2118
2119 template <typename R2>
2120 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
2121 get_or(BOOST_THREAD_RV_REF(R2) v) const // EXTENSION
2122 {
2123 if(!this->future_)
2124 {
2125 boost::throw_exception(future_uninitialized());
2126 }
2127 this->future_->wait();
2128 if (this->future_->has_value()) return this->future_->get_sh();
2129 else return boost::move(v);
2130 }
2131
2132#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
2133 template<typename F>
2134 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2135 then(BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2136 template<typename F>
2137 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2138 then(launch policy, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2139 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2140 template<typename Ex, typename F>
2141 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
2142 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
2143 #endif
2144#endif
2145
2146 };
2147
2148 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
2149
2150 template <typename R>
2151 class promise
2152 {
2153 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
2154
2155 typedef typename detail::shared_state<R>::source_reference_type source_reference_type;
2156 typedef typename detail::shared_state<R>::rvalue_source_type rvalue_source_type;
2157 typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
2158 typedef typename detail::shared_state<R>::shared_future_get_result_type shared_future_get_result_type;
2159
2160 future_ptr future_;
2161 bool future_obtained;
2162
2163 void lazy_init()
2164 {
2165#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2166#include <boost/detail/atomic_undef_macros.hpp>
2167 if(!atomic_load(&future_))
2168 {
2169 future_ptr blank;
2170 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
2171 }
2172#include <boost/detail/atomic_redef_macros.hpp>
2173#endif
2174 }
2175
2176 public:
2177 BOOST_THREAD_MOVABLE_ONLY(promise)
2178#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2179 template <class Allocator>
2180 promise(boost::allocator_arg_t, Allocator a)
2181 {
2182 typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2;
2183 A2 a2(a);
2184 typedef thread_detail::allocator_destructor<A2> D;
2185
2186 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) );
2187 future_obtained = false;
2188 }
2189#endif
2190 promise():
2191#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2192 future_(),
2193#else
2194 future_(new detail::shared_state<R>()),
2195#endif
2196 future_obtained(false)
2197 {}
2198
2199 ~promise()
2200 {
2201 if(future_)
2202 {
2203 boost::unique_lock<boost::mutex> lock(future_->mutex);
2204
2205 if(!future_->done && !future_->is_constructed)
2206 {
2207 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2208 }
2209 }
2210 }
2211
2212 // Assignment
2213 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2214 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2215 {
2216 BOOST_THREAD_RV(rhs).future_.reset();
2217 BOOST_THREAD_RV(rhs).future_obtained=false;
2218 }
2219 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2220 {
2221 future_=BOOST_THREAD_RV(rhs).future_;
2222 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2223 BOOST_THREAD_RV(rhs).future_.reset();
2224 BOOST_THREAD_RV(rhs).future_obtained=false;
2225 return *this;
2226 }
2227
2228 void swap(promise& other)
2229 {
2230 future_.swap(other.future_);
2231 std::swap(future_obtained,other.future_obtained);
2232 }
2233
2234#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
2235 void set_executor(executor_ptr_type aex)
2236 {
2237 lazy_init();
2238 if (future_.get()==0)
2239 {
2240 boost::throw_exception(promise_moved());
2241 }
2242 boost::lock_guard<boost::mutex> lk(future_->mutex);
2243 future_->set_executor_policy(aex, lk);
2244 }
2245#endif
2246 // Result retrieval
2247 BOOST_THREAD_FUTURE<R> get_future()
2248 {
2249 lazy_init();
2250 if (future_.get()==0)
2251 {
2252 boost::throw_exception(promise_moved());
2253 }
2254 if (future_obtained)
2255 {
2256 boost::throw_exception(future_already_retrieved());
2257 }
2258 future_obtained=true;
2259 return BOOST_THREAD_FUTURE<R>(future_);
2260 }
2261
2262#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2263 template <class TR>
2264 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value(TR const & r)
2265 {
2266 lazy_init();
2267 boost::unique_lock<boost::mutex> lock(future_->mutex);
2268 if(future_->done)
2269 {
2270 boost::throw_exception(promise_already_satisfied());
2271 }
2272 future_->mark_finished_with_result_internal(r, lock);
2273 }
2274#else
2275 void set_value(source_reference_type r)
2276 {
2277 lazy_init();
2278 boost::unique_lock<boost::mutex> lock(future_->mutex);
2279 if(future_->done)
2280 {
2281 boost::throw_exception(promise_already_satisfied());
2282 }
2283 future_->mark_finished_with_result_internal(r, lock);
2284 }
2285#endif
2286
2287 void set_value(rvalue_source_type r)
2288 {
2289 lazy_init();
2290 boost::unique_lock<boost::mutex> lock(future_->mutex);
2291 if(future_->done)
2292 {
2293 boost::throw_exception(promise_already_satisfied());
2294 }
2295#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2296 future_->mark_finished_with_result_internal(boost::move(r), lock);
2297#else
2298 future_->mark_finished_with_result_internal(static_cast<rvalue_source_type>(r), lock);
2299#endif
2300 }
2301
2302#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
2303 template <class ...Args>
2304 void emplace(BOOST_THREAD_FWD_REF(Args) ...args)
2305 {
2306 lazy_init();
2307 boost::unique_lock<boost::mutex> lock(future_->mutex);
2308 if(future_->done)
2309 {
2310 boost::throw_exception(promise_already_satisfied());
2311 }
2312 future_->mark_finished_with_result_internal(lock, boost::forward<Args>(args)...);
2313 }
2314
2315#endif
2316
2317 void set_exception(boost::exception_ptr p)
2318 {
2319 lazy_init();
2320 boost::unique_lock<boost::mutex> lock(future_->mutex);
2321 if(future_->done)
2322 {
2323 boost::throw_exception(promise_already_satisfied());
2324 }
2325 future_->mark_exceptional_finish_internal(p, lock);
2326 }
2327 template <typename E>
2328 void set_exception(E ex)
2329 {
2330 set_exception(boost::copy_exception(ex));
2331 }
2332 // setting the result with deferred notification
2333#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
2334 template <class TR>
2335 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)
2336 {
2337 if (future_.get()==0)
2338 {
2339 boost::throw_exception(promise_moved());
2340 }
2341 future_->set_value_at_thread_exit(r);
2342 }
2343#else
2344 void set_value_at_thread_exit(source_reference_type r)
2345 {
2346 if (future_.get()==0)
2347 {
2348 boost::throw_exception(promise_moved());
2349 }
2350 future_->set_value_at_thread_exit(r);
2351 }
2352#endif
2353 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
2354 {
2355 if (future_.get()==0)
2356 {
2357 boost::throw_exception(promise_moved());
2358 }
2359 future_->set_value_at_thread_exit(boost::move(r));
2360 }
2361 void set_exception_at_thread_exit(exception_ptr e)
2362 {
2363 if (future_.get()==0)
2364 {
2365 boost::throw_exception(promise_moved());
2366 }
2367 future_->set_exception_at_thread_exit(e);
2368 }
2369 template <typename E>
2370 void set_exception_at_thread_exit(E ex)
2371 {
2372 set_exception_at_thread_exit(boost::copy_exception(ex));
2373 }
2374
2375 template<typename F>
2376 void set_wait_callback(F f)
2377 {
2378 lazy_init();
2379 future_->set_wait_callback(f,this);
2380 }
2381
2382 };
2383
2384 template <typename R>
2385 class promise<R&>
2386 {
2387 typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr;
2388
2389 future_ptr future_;
2390 bool future_obtained;
2391
2392 void lazy_init()
2393 {
2394#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2395#include <boost/detail/atomic_undef_macros.hpp>
2396 if(!atomic_load(&future_))
2397 {
2398 future_ptr blank;
2399 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
2400 }
2401#include <boost/detail/atomic_redef_macros.hpp>
2402#endif
2403 }
2404
2405 public:
2406 BOOST_THREAD_MOVABLE_ONLY(promise)
2407#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2408 template <class Allocator>
2409 promise(boost::allocator_arg_t, Allocator a)
2410 {
2411 typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2;
2412 A2 a2(a);
2413 typedef thread_detail::allocator_destructor<A2> D;
2414
2415 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
2416 future_obtained = false;
2417 }
2418#endif
2419 promise():
2420#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2421 future_(),
2422#else
2423 future_(new detail::shared_state<R&>()),
2424#endif
2425 future_obtained(false)
2426 {}
2427
2428 ~promise()
2429 {
2430 if(future_)
2431 {
2432 boost::unique_lock<boost::mutex> lock(future_->mutex);
2433
2434 if(!future_->done && !future_->is_constructed)
2435 {
2436 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2437 }
2438 }
2439 }
2440
2441 // Assignment
2442 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2443 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2444 {
2445 BOOST_THREAD_RV(rhs).future_.reset();
2446 BOOST_THREAD_RV(rhs).future_obtained=false;
2447 }
2448 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2449 {
2450 future_=BOOST_THREAD_RV(rhs).future_;
2451 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2452 BOOST_THREAD_RV(rhs).future_.reset();
2453 BOOST_THREAD_RV(rhs).future_obtained=false;
2454 return *this;
2455 }
2456
2457 void swap(promise& other)
2458 {
2459 future_.swap(other.future_);
2460 std::swap(future_obtained,other.future_obtained);
2461 }
2462
2463 // Result retrieval
2464 BOOST_THREAD_FUTURE<R&> get_future()
2465 {
2466 lazy_init();
2467 if (future_.get()==0)
2468 {
2469 boost::throw_exception(promise_moved());
2470 }
2471 if (future_obtained)
2472 {
2473 boost::throw_exception(future_already_retrieved());
2474 }
2475 future_obtained=true;
2476 return BOOST_THREAD_FUTURE<R&>(future_);
2477 }
2478
2479 void set_value(R& r)
2480 {
2481 lazy_init();
2482 boost::unique_lock<boost::mutex> lock(future_->mutex);
2483 if(future_->done)
2484 {
2485 boost::throw_exception(promise_already_satisfied());
2486 }
2487 future_->mark_finished_with_result_internal(r, lock);
2488 }
2489
2490 void set_exception(boost::exception_ptr p)
2491 {
2492 lazy_init();
2493 boost::unique_lock<boost::mutex> lock(future_->mutex);
2494 if(future_->done)
2495 {
2496 boost::throw_exception(promise_already_satisfied());
2497 }
2498 future_->mark_exceptional_finish_internal(p, lock);
2499 }
2500 template <typename E>
2501 void set_exception(E ex)
2502 {
2503 set_exception(boost::copy_exception(ex));
2504 }
2505
2506 // setting the result with deferred notification
2507 void set_value_at_thread_exit(R& r)
2508 {
2509 if (future_.get()==0)
2510 {
2511 boost::throw_exception(promise_moved());
2512 }
2513 future_->set_value_at_thread_exit(r);
2514 }
2515
2516 void set_exception_at_thread_exit(exception_ptr e)
2517 {
2518 if (future_.get()==0)
2519 {
2520 boost::throw_exception(promise_moved());
2521 }
2522 future_->set_exception_at_thread_exit(e);
2523 }
2524 template <typename E>
2525 void set_exception_at_thread_exit(E ex)
2526 {
2527 set_exception_at_thread_exit(boost::copy_exception(ex));
2528 }
2529
2530 template<typename F>
2531 void set_wait_callback(F f)
2532 {
2533 lazy_init();
2534 future_->set_wait_callback(f,this);
2535 }
2536 };
2537
2538 template <>
2539 class promise<void>
2540 {
2541 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr;
2542
2543 future_ptr future_;
2544 bool future_obtained;
2545
2546 void lazy_init()
2547 {
2548#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2549 if(!atomic_load(&future_))
2550 {
2551 future_ptr blank;
2552 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>));
2553 }
2554#endif
2555 }
2556 public:
2557 BOOST_THREAD_MOVABLE_ONLY(promise)
2558
2559#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2560 template <class Allocator>
2561 promise(boost::allocator_arg_t, Allocator a)
2562 {
2563 typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2;
2564 A2 a2(a);
2565 typedef thread_detail::allocator_destructor<A2> D;
2566
2567 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
2568 future_obtained = false;
2569 }
2570#endif
2571 promise():
2572#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2573 future_(),
2574#else
2575 future_(new detail::shared_state<void>),
2576#endif
2577 future_obtained(false)
2578 {}
2579
2580 ~promise()
2581 {
2582 if(future_)
2583 {
2584 boost::unique_lock<boost::mutex> lock(future_->mutex);
2585
2586 if(!future_->done && !future_->is_constructed)
2587 {
2588 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2589 }
2590 }
2591 }
2592
2593 // Assignment
2594 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2595 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2596 {
2597 // we need to release the future as shared_ptr doesn't implements move semantics
2598 BOOST_THREAD_RV(rhs).future_.reset();
2599 BOOST_THREAD_RV(rhs).future_obtained=false;
2600 }
2601
2602 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2603 {
2604 future_=BOOST_THREAD_RV(rhs).future_;
2605 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2606 BOOST_THREAD_RV(rhs).future_.reset();
2607 BOOST_THREAD_RV(rhs).future_obtained=false;
2608 return *this;
2609 }
2610
2611 void swap(promise& other)
2612 {
2613 future_.swap(other.future_);
2614 std::swap(future_obtained,other.future_obtained);
2615 }
2616
2617 // Result retrieval
2618 BOOST_THREAD_FUTURE<void> get_future()
2619 {
2620 lazy_init();
2621
2622 if (future_.get()==0)
2623 {
2624 boost::throw_exception(promise_moved());
2625 }
2626 if(future_obtained)
2627 {
2628 boost::throw_exception(future_already_retrieved());
2629 }
2630 future_obtained=true;
2631 //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<void>(future_));
2632 return BOOST_THREAD_FUTURE<void>(future_);
2633 }
2634
2635 void set_value()
2636 {
2637 lazy_init();
2638 boost::unique_lock<boost::mutex> lock(future_->mutex);
2639 if(future_->done)
2640 {
2641 boost::throw_exception(promise_already_satisfied());
2642 }
2643 future_->mark_finished_with_result_internal(lock);
2644 }
2645
2646 void set_exception(boost::exception_ptr p)
2647 {
2648 lazy_init();
2649 boost::unique_lock<boost::mutex> lock(future_->mutex);
2650 if(future_->done)
2651 {
2652 boost::throw_exception(promise_already_satisfied());
2653 }
2654 future_->mark_exceptional_finish_internal(p,lock);
2655 }
2656 template <typename E>
2657 void set_exception(E ex)
2658 {
2659 set_exception(boost::copy_exception(ex));
2660 }
2661
2662 // setting the result with deferred notification
2663 void set_value_at_thread_exit()
2664 {
2665 if (future_.get()==0)
2666 {
2667 boost::throw_exception(promise_moved());
2668 }
2669 future_->set_value_at_thread_exit();
2670 }
2671
2672 void set_exception_at_thread_exit(exception_ptr e)
2673 {
2674 if (future_.get()==0)
2675 {
2676 boost::throw_exception(promise_moved());
2677 }
2678 future_->set_exception_at_thread_exit(e);
2679 }
2680 template <typename E>
2681 void set_exception_at_thread_exit(E ex)
2682 {
2683 set_exception_at_thread_exit(boost::copy_exception(ex));
2684 }
2685
2686 template<typename F>
2687 void set_wait_callback(F f)
2688 {
2689 lazy_init();
2690 future_->set_wait_callback(f,this);
2691 }
2692
2693 };
2694}
2695#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2696namespace boost { namespace container {
2697 template <class R, class Alloc>
2698 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
2699 {
2700 };
2701}}
2702#if ! defined BOOST_NO_CXX11_ALLOCATOR
2703namespace std {
2704 template <class R, class Alloc>
2705 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
2706 {
2707 };
2708}
2709#endif
2710#endif
2711
2712namespace boost
2713{
2714
2715 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
2716
2717 namespace detail
2718 {
2719#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2720 template<typename R>
2721 struct task_base_shared_state;
2722#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2723 template<typename R, typename ...ArgTypes>
2724 struct task_base_shared_state<R(ArgTypes...)>:
2725#else
2726 template<typename R>
2727 struct task_base_shared_state<R()>:
2728#endif
2729#else
2730 template<typename R>
2731 struct task_base_shared_state:
2732#endif
2733 detail::shared_state<R>
2734 {
2735 bool started;
2736
2737 task_base_shared_state():
2738 started(false)
2739 {}
2740
2741 void reset()
2742 {
2743 // todo The packaged_task::reset must be as if an assignemnt froma new packaged_task with the same function
2744 // the reset function is an optimization that avoids reallocating a new task.
2745 started=false;
2746 this->validate();
2747 }
2748#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2749 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2750 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2751#else
2752 virtual void do_run()=0;
2753 void run()
2754#endif
2755 {
2756 {
2757 boost::lock_guard<boost::mutex> lk(this->mutex);
2758 if(started)
2759 {
2760 boost::throw_exception(task_already_started());
2761 }
2762 started=true;
2763 }
2764#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2765 do_run(boost::move(args)...);
2766#else
2767 do_run();
2768#endif
2769 }
2770
2771#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2772 virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2773 void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2774#else
2775 virtual void do_apply()=0;
2776 void apply()
2777#endif
2778 {
2779 {
2780 boost::lock_guard<boost::mutex> lk(this->mutex);
2781 if(started)
2782 {
2783 boost::throw_exception(task_already_started());
2784 }
2785 started=true;
2786 }
2787#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2788 do_apply(boost::move(args)...);
2789#else
2790 do_apply();
2791#endif
2792 }
2793
2794 void owner_destroyed()
2795 {
2796 boost::unique_lock<boost::mutex> lk(this->mutex);
2797 if(!started)
2798 {
2799 started=true;
2800 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
2801 }
2802 }
2803 };
2804
2805#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2806 template<typename F, typename R>
2807 struct task_shared_state;
2808#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2809 template<typename F, typename R, typename ...ArgTypes>
2810 struct task_shared_state<F, R(ArgTypes...)>:
2811 task_base_shared_state<R(ArgTypes...)>
2812#else
2813 template<typename F, typename R>
2814 struct task_shared_state<F, R()>:
2815 task_base_shared_state<R()>
2816#endif
2817#else
2818 template<typename F, typename R>
2819 struct task_shared_state:
2820 task_base_shared_state<R>
2821#endif
2822 {
2823 private:
2824 task_shared_state(task_shared_state&);
2825 public:
2826 F f;
2827 task_shared_state(F const& f_):
2828 f(f_)
2829 {}
2830 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
2831 f(boost::move(f_))
2832 {}
2833
2834 F callable()
2835 {
2836 return boost::move(f);
2837 }
2838
2839#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2840 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2841 {
2842 try
2843 {
2844 this->set_value_at_thread_exit(f(boost::move(args)...));
2845 }
2846#else
2847 void do_apply()
2848 {
2849 try
2850 {
2851 this->set_value_at_thread_exit(f());
2852 }
2853#endif
2854 catch(...)
2855 {
2856 this->set_exception_at_thread_exit(current_exception());
2857 }
2858 }
2859
2860#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2861 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2862 {
2863 try
2864 {
2865 this->mark_finished_with_result(f(boost::move(args)...));
2866 }
2867#else
2868 void do_run()
2869 {
2870 try
2871 {
2872#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2873 R res((f()));
2874 this->mark_finished_with_result(boost::move(res));
2875#else
2876 this->mark_finished_with_result(f());
2877#endif
2878 }
2879#endif
2880 catch(...)
2881 {
2882 this->mark_exceptional_finish();
2883 }
2884 }
2885 };
2886
2887#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2888#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2889 template<typename F, typename R, typename ...ArgTypes>
2890 struct task_shared_state<F, R&(ArgTypes...)>:
2891 task_base_shared_state<R&(ArgTypes...)>
2892#else
2893 template<typename F, typename R>
2894 struct task_shared_state<F, R&()>:
2895 task_base_shared_state<R&()>
2896#endif
2897#else
2898 template<typename F, typename R>
2899 struct task_shared_state<F,R&>:
2900 task_base_shared_state<R&>
2901#endif
2902 {
2903 private:
2904 task_shared_state(task_shared_state&);
2905 public:
2906 F f;
2907 task_shared_state(F const& f_):
2908 f(f_)
2909 {}
2910 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
2911 f(boost::move(f_))
2912 {}
2913
2914 F callable()
2915 {
2916 return f;
2917 }
2918
2919#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2920 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2921 {
2922 try
2923 {
2924 this->set_value_at_thread_exit(f(boost::move(args)...));
2925 }
2926#else
2927 void do_apply()
2928 {
2929 try
2930 {
2931 this->set_value_at_thread_exit(f());
2932 }
2933#endif
2934 catch(...)
2935 {
2936 this->set_exception_at_thread_exit(current_exception());
2937 }
2938 }
2939
2940#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2941 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2942 {
2943 try
2944 {
2945 this->mark_finished_with_result(f(boost::move(args)...));
2946 }
2947#else
2948 void do_run()
2949 {
2950 try
2951 {
2952 R& res((f()));
2953 this->mark_finished_with_result(res);
2954 }
2955#endif
2956 catch(...)
2957 {
2958 this->mark_exceptional_finish();
2959 }
2960 }
2961 };
2962
2963#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
2964
2965#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2966#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2967 template<typename R, typename ...ArgTypes>
2968 struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>:
2969 task_base_shared_state<R(ArgTypes...)>
2970#else
2971 template<typename R>
2972 struct task_shared_state<R (*)(), R()>:
2973 task_base_shared_state<R()>
2974#endif
2975#else
2976 template<typename R>
2977 struct task_shared_state<R (*)(), R> :
2978 task_base_shared_state<R>
2979#endif
2980 {
2981 private:
2982 task_shared_state(task_shared_state&);
2983#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2984 typedef R (*CallableType)(ArgTypes ... );
2985#else
2986 typedef R (*CallableType)();
2987#endif
2988 public:
2989 CallableType f;
2990 task_shared_state(CallableType f_):
2991 f(f_)
2992 {}
2993
2994 CallableType callable()
2995 {
2996 return f;
2997 }
2998
2999#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3000 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3001 {
3002 try
3003 {
3004 this->set_value_at_thread_exit(f(boost::move(args)...));
3005 }
3006#else
3007 void do_apply()
3008 {
3009 try
3010 {
3011 R r((f()));
3012 this->set_value_at_thread_exit(boost::move(r));
3013 }
3014#endif
3015 catch(...)
3016 {
3017 this->set_exception_at_thread_exit(current_exception());
3018 }
3019 }
3020
3021
3022#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3023 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3024 {
3025 try
3026 {
3027 this->mark_finished_with_result(f(boost::move(args)...));
3028 }
3029#else
3030 void do_run()
3031 {
3032 try
3033 {
3034 R res((f()));
3035 this->mark_finished_with_result(boost::move(res));
3036 }
3037#endif
3038 catch(...)
3039 {
3040 this->mark_exceptional_finish();
3041 }
3042 }
3043 };
3044#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3045#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3046 template<typename R, typename ...ArgTypes>
3047 struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>:
3048 task_base_shared_state<R&(ArgTypes...)>
3049#else
3050 template<typename R>
3051 struct task_shared_state<R& (*)(), R&()>:
3052 task_base_shared_state<R&()>
3053#endif
3054#else
3055 template<typename R>
3056 struct task_shared_state<R& (*)(), R&> :
3057 task_base_shared_state<R&>
3058#endif
3059 {
3060 private:
3061 task_shared_state(task_shared_state&);
3062 public:
3063#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3064 typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... );
3065#else
3066 typedef R& (*CallableType)();
3067#endif
3068 CallableType f;
3069 task_shared_state(CallableType f_):
3070 f(f_)
3071 {}
3072
3073 CallableType callable()
3074 {
3075 return boost::move(f);
3076 }
3077
3078#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3079 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3080 {
3081 try
3082 {
3083 this->set_value_at_thread_exit(f(boost::move(args)...));
3084 }
3085#else
3086 void do_apply()
3087 {
3088 try
3089 {
3090 this->set_value_at_thread_exit(f());
3091 }
3092#endif
3093 catch(...)
3094 {
3095 this->set_exception_at_thread_exit(current_exception());
3096 }
3097 }
3098
3099
3100#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3101 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3102 {
3103 try
3104 {
3105 this->mark_finished_with_result(f(boost::move(args)...));
3106 }
3107#else
3108 void do_run()
3109 {
3110 try
3111 {
3112 this->mark_finished_with_result(f());
3113 }
3114#endif
3115 catch(...)
3116 {
3117 this->mark_exceptional_finish();
3118 }
3119 }
3120 };
3121#endif
3122#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3123#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3124 template<typename F, typename ...ArgTypes>
3125 struct task_shared_state<F, void(ArgTypes...)>:
3126 task_base_shared_state<void(ArgTypes...)>
3127#else
3128 template<typename F>
3129 struct task_shared_state<F, void()>:
3130 task_base_shared_state<void()>
3131#endif
3132#else
3133 template<typename F>
3134 struct task_shared_state<F,void>:
3135 task_base_shared_state<void>
3136#endif
3137 {
3138 private:
3139 task_shared_state(task_shared_state&);
3140 public:
3141 typedef F CallableType;
3142 F f;
3143 task_shared_state(F const& f_):
3144 f(f_)
3145 {}
3146 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
3147 f(boost::move(f_))
3148 {}
3149 F callable()
3150 {
3151 return boost::move(f);
3152 }
3153#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3154 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3155 {
3156 try
3157 {
3158 f(boost::move(args)...);
3159#else
3160 void do_apply()
3161 {
3162 try
3163 {
3164 f();
3165#endif
3166 this->set_value_at_thread_exit();
3167 }
3168 catch(...)
3169 {
3170 this->set_exception_at_thread_exit(current_exception());
3171 }
3172 }
3173
3174#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3175 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3176 {
3177 try
3178 {
3179 f(boost::move(args)...);
3180#else
3181 void do_run()
3182 {
3183 try
3184 {
3185 f();
3186#endif
3187 this->mark_finished_with_result();
3188 }
3189 catch(...)
3190 {
3191 this->mark_exceptional_finish();
3192 }
3193 }
3194 };
3195
3196#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3197#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3198 template<typename ...ArgTypes>
3199 struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>:
3200 task_base_shared_state<void(ArgTypes...)>
3201#else
3202 template<>
3203 struct task_shared_state<void (*)(), void()>:
3204 task_base_shared_state<void()>
3205#endif
3206#else
3207 template<>
3208 struct task_shared_state<void (*)(),void>:
3209 task_base_shared_state<void>
3210#endif
3211 {
3212 private:
3213 task_shared_state(task_shared_state&);
3214#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3215 typedef void (*CallableType)(ArgTypes...);
3216#else
3217 typedef void (*CallableType)();
3218#endif
3219 public:
3220 CallableType f;
3221 task_shared_state(CallableType f_):
3222 f(f_)
3223 {}
3224 CallableType callable()
3225 {
3226 return f;
3227 }
3228#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3229 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3230 {
3231 try
3232 {
3233 f(boost::move(args)...);
3234#else
3235 void do_apply()
3236 {
3237 try
3238 {
3239 f();
3240#endif
3241 this->set_value_at_thread_exit();
3242 }
3243 catch(...)
3244 {
3245 this->set_exception_at_thread_exit(current_exception());
3246 }
3247 }
3248
3249#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3250 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3251 {
3252 try
3253 {
3254 f(boost::move(args)...);
3255#else
3256 void do_run()
3257 {
3258 try
3259 {
3260 f();
3261#endif
3262 this->mark_finished_with_result();
3263 }
3264 catch(...)
3265 {
3266 this->mark_exceptional_finish();
3267 }
3268 }
3269 };
3270 }
3271
3272#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3273 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3274 template<typename R, typename ...ArgTypes>
3275 class packaged_task<R(ArgTypes...)>
3276 {
3277 typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr;
3278 boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task;
3279 #else
3280 template<typename R>
3281 class packaged_task<R()>
3282 {
3283 typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr;
3284 boost::shared_ptr<detail::task_base_shared_state<R()> > task;
3285 #endif
3286#else
3287 template<typename R>
3288 class packaged_task
3289 {
3290 typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr;
3291 boost::shared_ptr<detail::task_base_shared_state<R> > task;
3292#endif
3293 bool future_obtained;
3294 struct dummy;
3295
3296 public:
3297 typedef R result_type;
3298 BOOST_THREAD_MOVABLE_ONLY(packaged_task)
3299
3300 packaged_task():
3301 future_obtained(false)
3302 {}
3303
3304 // construction and destruction
3305#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3306
3307#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3308 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3309 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
3310 {
3311 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3312 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3313 task= task_ptr(new task_shared_state_type(f, boost::move(args)...));
3314 future_obtained=false;
3315 }
3316 #else
3317 explicit packaged_task(R(*f)())
3318 {
3319 typedef R(*FR)();
3320 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3321 task= task_ptr(new task_shared_state_type(f));
3322 future_obtained=false;
3323 }
3324 #endif
3325#else
3326 explicit packaged_task(R(*f)())
3327 {
3328 typedef R(*FR)();
3329 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3330 task= task_ptr(new task_shared_state_type(f));
3331 future_obtained=false;
3332 }
3333#endif
3334#endif
3335#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
3336 template <class F>
3337 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
3338 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3339 )
3340 {
3341 typedef typename decay<F>::type FR;
3342#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3343 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3344 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3345 #else
3346 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3347 #endif
3348#else
3349 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3350#endif
3351 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
3352 future_obtained = false;
3353
3354 }
3355
3356#else
3357 template <class F>
3358 explicit packaged_task(F const& f
3359 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3360 )
3361 {
3362#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3363 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3364 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3365 #else
3366 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3367 #endif
3368#else
3369 typedef detail::task_shared_state<F,R> task_shared_state_type;
3370#endif
3371 task = task_ptr(new task_shared_state_type(f));
3372 future_obtained=false;
3373 }
3374 template <class F>
3375 explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
3376 {
3377#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3378#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3379 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3380 task = task_ptr(new task_shared_state_type(boost::move(f)));
3381#else
3382 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3383 task = task_ptr(new task_shared_state_type(boost::move(f)));
3384#endif
3385#else
3386 typedef detail::task_shared_state<F,R> task_shared_state_type;
3387 task = task_ptr(new task_shared_state_type(boost::move(f)));
3388#endif
3389 future_obtained=false;
3390
3391 }
3392#endif
3393
3394#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3395#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3396 template <class Allocator>
3397 packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
3398 {
3399 typedef R(*FR)();
3400#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3401 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3402 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3403 #else
3404 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3405 #endif
3406#else
3407 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3408#endif
3409 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3410 A2 a2(a);
3411 typedef thread_detail::allocator_destructor<A2> D;
3412
3413 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3414 future_obtained = false;
3415 }
3416#endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3417
3418#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3419 template <class F, class Allocator>
3420 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
3421 {
3422 typedef typename decay<F>::type FR;
3423
3424#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3425 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3426 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3427 #else
3428 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3429 #endif
3430#else
3431 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3432#endif
3433 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3434 A2 a2(a);
3435 typedef thread_detail::allocator_destructor<A2> D;
3436
3437 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
3438 future_obtained = false;
3439 }
3440#else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3441 template <class F, class Allocator>
3442 packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
3443 {
3444#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3445 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3446 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3447 #else
3448 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3449 #endif
3450#else
3451 typedef detail::task_shared_state<F,R> task_shared_state_type;
3452#endif
3453 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3454 A2 a2(a);
3455 typedef thread_detail::allocator_destructor<A2> D;
3456
3457 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3458 future_obtained = false;
3459 }
3460 template <class F, class Allocator>
3461 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
3462 {
3463#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3464 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3465 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3466 #else
3467 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3468 #endif
3469#else
3470 typedef detail::task_shared_state<F,R> task_shared_state_type;
3471#endif
3472 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3473 A2 a2(a);
3474 typedef thread_detail::allocator_destructor<A2> D;
3475
3476 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) );
3477 future_obtained = false;
3478 }
3479
3480#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
3481#endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3482
3483 ~packaged_task() {
3484 if(task) {
3485 task->owner_destroyed();
3486 }
3487 }
3488
3489 // assignment
3490 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
3491 : future_obtained(BOOST_THREAD_RV(other).future_obtained) {
3492 task.swap(BOOST_THREAD_RV(other).task);
3493 BOOST_THREAD_RV(other).future_obtained=false;
3494 }
3495 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT {
3496
3497#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3498 packaged_task temp(boost::move(other));
3499#else
3500 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
3501#endif
3502 swap(temp);
3503 return *this;
3504 }
3505
3506#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
3507 void set_executor(executor_ptr_type aex)
3508 {
3509 if (!valid())
3510 boost::throw_exception(task_moved());
3511 boost::lock_guard<boost::mutex> lk(task->mutex);
3512 task->set_executor_policy(aex, lk);
3513 }
3514#endif
3515 void reset() {
3516 if (!valid())
3517 boost::throw_exception(future_error(system::make_error_code(future_errc::no_state)));
3518
3519 // As if *this = packaged_task(task->callable());
3520
3521 task->reset();
3522 future_obtained=false;
3523 }
3524
3525 void swap(packaged_task& other) BOOST_NOEXCEPT {
3526 task.swap(other.task);
3527 std::swap(future_obtained,other.future_obtained);
3528 }
3529 bool valid() const BOOST_NOEXCEPT {
3530 return task.get()!=0;
3531 }
3532
3533 // result retrieval
3534 BOOST_THREAD_FUTURE<R> get_future() {
3535 if(!task) {
3536 boost::throw_exception(task_moved());
3537 } else if(!future_obtained) {
3538 future_obtained=true;
3539 return BOOST_THREAD_FUTURE<R>(task);
3540 } else {
3541 boost::throw_exception(future_already_retrieved());
3542 }
3543 }
3544
3545 // execution
3546#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3547 void operator()(ArgTypes... args) {
3548 if(!task) {
3549 boost::throw_exception(task_moved());
3550 }
3551 task->run(boost::move(args)...);
3552 }
3553 void make_ready_at_thread_exit(ArgTypes... args) {
3554 if(!task) {
3555 boost::throw_exception(task_moved());
3556 }
3557 if (task->has_value()) {
3558 boost::throw_exception(promise_already_satisfied());
3559 }
3560 task->apply(boost::move(args)...);
3561 }
3562#else
3563 void operator()() {
3564 if(!task) {
3565 boost::throw_exception(task_moved());
3566 }
3567 task->run();
3568 }
3569 void make_ready_at_thread_exit() {
3570 if(!task) {
3571 boost::throw_exception(task_moved());
3572 }
3573 if (task->has_value()) boost::throw_exception(promise_already_satisfied());
3574 task->apply();
3575 }
3576#endif
3577 template<typename F>
3578 void set_wait_callback(F f) {
3579 task->set_wait_callback(f,this);
3580 }
3581 };
3582}
3583#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3584namespace boost { namespace container {
3585 template <class R, class Alloc>
3586 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
3587 {};
3588}}
3589#if ! defined BOOST_NO_CXX11_ALLOCATOR
3590namespace std {
3591 template <class R, class Alloc>
3592 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
3593 {};
3594}
3595#endif
3596#endif
3597
3598namespace boost
3599{
3600 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
3601
3602namespace detail
3603{
3604 ////////////////////////////////
3605 // make_future_deferred_shared_state
3606 ////////////////////////////////
3607 template <class Rp, class Fp>
3608 BOOST_THREAD_FUTURE<Rp>
3609 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
3610 shared_ptr<future_deferred_shared_state<Rp, Fp> >
3611 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
3612 return BOOST_THREAD_FUTURE<Rp>(h);
3613 }
3614
3615 ////////////////////////////////
3616 // make_future_async_shared_state
3617 ////////////////////////////////
3618 template <class Rp, class Fp>
3619 BOOST_THREAD_FUTURE<Rp>
3620 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
3621 shared_ptr<future_async_shared_state<Rp, Fp> >
3622 h(new future_async_shared_state<Rp, Fp>());
3623 h->init(boost::forward<Fp>(f));
3624 return BOOST_THREAD_FUTURE<Rp>(h);
3625 }
3626}
3627
3628 ////////////////////////////////
3629 // template <class F, class... ArgTypes>
3630 // future<R> async(launch policy, F&&, ArgTypes&&...);
3631 ////////////////////////////////
3632
3633#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3634
3635#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3636 template <class R, class... ArgTypes>
3637 BOOST_THREAD_FUTURE<R>
3638 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3639 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3640 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3641 typedef typename BF::result_type Rp;
3642
3643 if (underlying_cast<int>(policy) & int(launch::async)) {
3644 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3645 BF(
3646 f
3647 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3648 )
3649 ));
3650 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3651 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3652 BF(
3653 f
3654 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3655 )
3656 ));
3657 } else {
3658 std::terminate();
3659 //BOOST_THREAD_FUTURE<R> ret;
3660 //return ::boost::move(ret);
3661 }
3662 }
3663
3664#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3665
3666 template <class R>
3667 BOOST_THREAD_FUTURE<R>
3668 async(launch policy, R(*f)()) {
3669 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3670 typedef packaged_task<R()> packaged_task_type;
3671 #else
3672 typedef packaged_task<R> packaged_task_type;
3673 #endif
3674
3675 if (underlying_cast<int>(policy) & int(launch::async)) {
3676 packaged_task_type pt( f );
3677 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
3678 ret.set_async();
3679 boost::thread( boost::move(pt) ).detach();
3680 return ::boost::move(ret);
3681 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3682 std::terminate();
3683 //BOOST_THREAD_FUTURE<R> ret;
3684 //return ::boost::move(ret);
3685 } else {
3686 std::terminate();
3687 //BOOST_THREAD_FUTURE<R> ret;
3688 //return ::boost::move(ret);
3689 }
3690 }
3691#endif
3692#endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3693
3694#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3695
3696 template <class F, class ...ArgTypes>
3697 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3698 typename decay<ArgTypes>::type...
3699 )>::type>
3700 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3701 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3702 typedef typename BF::result_type Rp;
3703
3704 if (underlying_cast<int>(policy) & int(launch::async)) {
3705 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3706 BF(
3707 thread_detail::decay_copy(boost::forward<F>(f))
3708 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3709 )
3710 ));
3711 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3712 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3713 BF(
3714 thread_detail::decay_copy(boost::forward<F>(f))
3715 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3716 )
3717 ));
3718 } else {
3719 std::terminate();
3720 //BOOST_THREAD_FUTURE<R> ret;
3721 //return ::boost::move(ret);
3722 }
3723 }
3724
3725#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3726
3727 template <class F>
3728 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3729 async(launch policy, BOOST_THREAD_FWD_REF(F) f) {
3730 typedef typename boost::result_of<typename decay<F>::type()>::type R;
3731#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3732 typedef packaged_task<R()> packaged_task_type;
3733#else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3734 typedef packaged_task<R> packaged_task_type;
3735#endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3736
3737 if (underlying_cast<int>(policy) & int(launch::async)) {
3738 packaged_task_type pt( boost::forward<F>(f) );
3739 BOOST_THREAD_FUTURE<R> ret = pt.get_future();
3740 ret.set_async();
3741 boost::thread( boost::move(pt) ).detach();
3742 return ::boost::move(ret);
3743 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
3744 std::terminate();
3745 //BOOST_THREAD_FUTURE<R> ret;
3746 //return ::boost::move(ret);
3747 // return boost::detail::make_future_deferred_shared_state<Rp>(
3748 // BF(
3749 // thread_detail::decay_copy(boost::forward<F>(f))
3750 // )
3751 // );
3752 } else {
3753 std::terminate();
3754 //BOOST_THREAD_FUTURE<R> ret;
3755 //return ::boost::move(ret);
3756 }
3757 }
3758#endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3759
3760#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
3761namespace detail {
3762
3763 /////////////////////////
3764 /// shared_state_nullary_task
3765 /////////////////////////
3766 template<typename Rp, typename Fp>
3767 struct shared_state_nullary_task
3768 {
3769
3770 typedef shared_ptr<shared_state_base > storage_type;
3771 storage_type that;
3772 Fp f_;
3773 public:
3774
3775 shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f)
3776 : that(st), f_(boost::move(f))
3777 {};
3778
3779#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
3780 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
3781 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
3782 : that(x.that), f_(x.f_)
3783 {}
3784 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
3785 {
3786 if (this != &x) {
3787 that=x.that;
3788 f_=x.f_;
3789 }
3790 return *this;
3791 }
3792 // move
3793 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
3794 : that(x.that), f_(boost::move(x.f_))
3795 {
3796 x.that.reset();
3797 }
3798 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
3799 {
3800 if (this != &x) {
3801 that=x.that;
3802 f_=boost::move(x.f_);
3803 x.that.reset();
3804 }
3805 return *this;
3806 }
3807#endif
3808 void operator()() {
3809 shared_ptr<shared_state<Rp> > that_ = static_pointer_cast<shared_state<Rp> >(that);
3810 try {
3811 that_->mark_finished_with_result(f_());
3812 } catch(...) {
3813 that_->mark_exceptional_finish();
3814 }
3815 }
3816 ~shared_state_nullary_task()
3817 {
3818 }
3819 };
3820
3821 template<typename Fp>
3822 struct shared_state_nullary_task<void, Fp>
3823 {
3824 typedef shared_ptr<shared_state_base > storage_type;
3825 storage_type that;
3826 Fp f_;
3827 public:
3828 shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f)
3829 : that(st), f_(boost::move(f))
3830 {};
3831
3832#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
3833 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
3834 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
3835 : that(x.that), f_(x.f_)
3836 {}
3837 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
3838 {
3839 if (this != &x) {
3840 that=x.that;
3841 f_=x.f_;
3842 }
3843 return *this;
3844 }
3845 // move
3846 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT
3847 : that(x.that), f_(boost::move(x.f_))
3848 {
3849 x.that.reset();
3850 }
3851 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
3852 if (this != &x) {
3853 that=x.that;
3854 f_=boost::move(x.f_);
3855 x.that.reset();
3856 }
3857 return *this;
3858 }
3859#endif
3860 void operator()() {
3861 shared_ptr<shared_state<void> > that_ = static_pointer_cast<shared_state<void> >(that);
3862 try {
3863 f_();
3864 that_->mark_finished_with_result();
3865 } catch(...) {
3866 that_->mark_exceptional_finish();
3867 }
3868 }
3869 };
3870
3871}
3872 BOOST_THREAD_DCL_MOVABLE_BEG2(R,F) detail::shared_state_nullary_task<R,F> BOOST_THREAD_DCL_MOVABLE_END
3873namespace detail {
3874
3875 /////////////////////////
3876 /// future_executor_shared_state_base
3877 /////////////////////////
3878 template<typename Rp>
3879 struct future_executor_shared_state: shared_state<Rp>
3880 {
3881 typedef shared_state<Rp> base_type;
3882 protected:
3883 public:
3884 future_executor_shared_state() {
3885 }
3886
3887 template <class Fp, class Executor>
3888 void init(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f)
3889 {
3890 typedef typename decay<Fp>::type Cont;
3891 this->set_executor_policy(executor_ptr_type(new executor_ref<Executor>(ex)));
3892 shared_state_nullary_task<Rp,Cont> t(this->shared_from_this(), boost::forward<Fp>(f));
3893 ex.submit(boost::move(t));
3894 }
3895
3896 ~future_executor_shared_state() {}
3897 };
3898
3899 ////////////////////////////////
3900 // make_future_executor_shared_state
3901 ////////////////////////////////
3902 template <class Rp, class Fp, class Executor>
3903 BOOST_THREAD_FUTURE<Rp>
3904 make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) {
3905 shared_ptr<future_executor_shared_state<Rp> >
3906 h(new future_executor_shared_state<Rp>());
3907 h->init(ex, boost::forward<Fp>(f));
3908 return BOOST_THREAD_FUTURE<Rp>(h);
3909 }
3910
3911} // detail
3912
3913 ////////////////////////////////
3914 // template <class Executor, class F, class... ArgTypes>
3915 // future<R> async(Executor& ex, F&&, ArgTypes&&...);
3916 ////////////////////////////////
3917
3918//#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
3919#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
3920
3921#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3922
3923 template <class Executor, class R, class... ArgTypes>
3924 BOOST_THREAD_FUTURE<R>
3925 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3926 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3927 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3928 typedef typename BF::result_type Rp;
3929
3930 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
3931 BF(
3932 f
3933 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3934 )
3935 ));
3936 }
3937#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3938
3939 template <class Executor, class F, class ...ArgTypes>
3940 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3941 typename decay<ArgTypes>::type...
3942 )>::type>
3943 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
3944 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3945 typedef typename BF::result_type Rp;
3946
3947 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
3948 BF(
3949 thread_detail::decay_copy(boost::forward<F>(f))
3950 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3951 )
3952 ));
3953 }
3954
3955#else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
3956#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3957
3958 template <class Executor, class R>
3959 BOOST_THREAD_FUTURE<R>
3960 async(Executor& ex, R(*f)()) {
3961 typedef R(*F)();
3962 typedef detail::invoker<F> BF;
3963 typedef typename BF::result_type Rp;
3964
3965 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
3966 BF(
3967 f
3968 )
3969 ));
3970 }
3971
3972 template <class Executor, class R, class A1>
3973 BOOST_THREAD_FUTURE<R>
3974 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) {
3975 typedef R(*F)(BOOST_THREAD_FWD_REF(A1));
3976 typedef detail::invoker<F, typename decay<A1>::type> BF;
3977 typedef typename BF::result_type Rp;
3978
3979 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
3980 BF(
3981 f
3982 , thread_detail::decay_copy(boost::forward<A1>(a1))
3983 )
3984 ));
3985 }
3986#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3987
3988 template <class Executor, class F>
3989 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3990 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) {
3991 typedef detail::invoker<typename decay<F>::type> BF;
3992 typedef typename BF::result_type Rp;
3993
3994 return boost::detail::make_future_executor_shared_state<Rp>(ex,
3995 BF(
3996 thread_detail::decay_copy(boost::forward<F>(f))
3997 )
3998 );
3999 }
4000
4001 template <class Executor, class F, class A1>
4002 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4003 typename decay<A1>::type
4004 )>::type>
4005 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) {
4006 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type> BF;
4007 typedef typename BF::result_type Rp;
4008
4009 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4010 BF(
4011 thread_detail::decay_copy(boost::forward<F>(f))
4012 , thread_detail::decay_copy(boost::forward<A1>(a1))
4013 )
4014 ));
4015 }
4016
4017 template <class Executor, class F, class A1, class A2>
4018 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4019 typename decay<A1>::type, typename decay<A2>::type
4020 )>::type>
4021 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) {
4022 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type, typename decay<A2>::type> BF;
4023 typedef typename BF::result_type Rp;
4024
4025 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
4026 BF(
4027 thread_detail::decay_copy(boost::forward<F>(f))
4028 , thread_detail::decay_copy(boost::forward<A1>(a1))
4029 , thread_detail::decay_copy(boost::forward<A2>(a2))
4030 )
4031 ));
4032 }
4033
4034#endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4035#endif
4036
4037 ////////////////////////////////
4038 // template <class F, class... ArgTypes>
4039 // future<R> async(F&&, ArgTypes&&...);
4040 ////////////////////////////////
4041
4042#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
4043 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
4044 template <class R, class... ArgTypes>
4045 BOOST_THREAD_FUTURE<R>
4046 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4047 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
4048 }
4049 #else
4050 template <class R>
4051 BOOST_THREAD_FUTURE<R>
4052 async(R(*f)()) {
4053 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
4054 }
4055 #endif
4056#endif
4057
4058#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
4059 template <class F, class ...ArgTypes>
4060 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
4061 typename decay<ArgTypes>::type...
4062 )>::type>
4063 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
4064 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
4065 }
4066#else
4067 template <class F>
4068 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
4069 async(BOOST_THREAD_FWD_REF(F) f) {
4070 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
4071 }
4072#endif
4073
4074 ////////////////////////////////
4075 // make_future deprecated
4076 ////////////////////////////////
4077 template <typename T>
4078 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) {
4079 typedef typename decay<T>::type future_value_type;
4080 promise<future_value_type> p;
4081 p.set_value(boost::forward<future_value_type>(value));
4082 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4083 }
4084
4085#if defined BOOST_THREAD_USES_MOVE
4086 inline BOOST_THREAD_FUTURE<void> make_future() {
4087 promise<void> p;
4088 p.set_value();
4089 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4090 }
4091#endif
4092
4093 ////////////////////////////////
4094 // make_ready_future
4095 ////////////////////////////////
4096 namespace detail {
4097 template <class T>
4098 struct deduced_type_impl
4099 {
4100 typedef T type;
4101 };
4102
4103 template <class T>
4104 struct deduced_type_impl<reference_wrapper<T> const>
4105 {
4106 typedef T& type;
4107 };
4108 template <class T>
4109 struct deduced_type_impl<reference_wrapper<T> >
4110 {
4111 typedef T& type;
4112 };
4113#if __cplusplus > 201103L
4114 template <class T>
4115 struct deduced_type_impl<std::reference_wrapper<T> >
4116 {
4117 typedef T& type;
4118 };
4119#endif
4120 template <class T>
4121 struct deduced_type
4122 {
4123 typedef typename detail::deduced_type_impl<typename decay<T>::type>::type type;
4124 };
4125
4126 }
4127
4128
4129#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4130 template <int = 0, int..., class T>
4131#else
4132 template <class T>
4133#endif
4134 BOOST_THREAD_FUTURE<typename detail::deduced_type<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) {
4135 typedef typename detail::deduced_type<T>::type future_value_type;
4136 promise<future_value_type> p;
4137 p.set_value(boost::forward<T>(value));
4138 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4139 }
4140
4141 // explicit overloads
4142 template <class T>
4143 BOOST_THREAD_FUTURE<T> make_ready_future(typename remove_reference<T>::type & x)
4144 {
4145 promise<T> p;
4146 p.set_value(x);
4147 return p.get_future();
4148 }
4149
4150 template <class T>
4151 BOOST_THREAD_FUTURE<T> make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference<T>::type) x)
4152 {
4153 promise<T> p;
4154 p.set_value(forward<typename remove_reference<T>::type>(x));
4155 return p.get_future();
4156 }
4157
4158 // variadic overload
4159#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
4160 template <class T, class ...Args>
4161 BOOST_THREAD_FUTURE<T> make_ready_future(Args&&... args)
4162 {
4163 promise<T> p;
4164 p.emplace(forward<Args>(args)...);
4165 return p.get_future();
4166
4167 }
4168#endif
4169
4170 template <typename T, typename T1>
4171 BOOST_THREAD_FUTURE<T> make_ready_no_decay_future(T1 value) {
4172 typedef T future_value_type;
4173 promise<future_value_type> p;
4174 p.set_value(value);
4175 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4176 }
4177
4178#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined BOOST_THREAD_USES_MOVE
4179 inline BOOST_THREAD_FUTURE<void> make_ready_future() {
4180 promise<void> p;
4181 p.set_value();
4182 return p.get_future();
4183 }
4184#endif
4185
4186
4187 template <typename T>
4188 BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) {
4189 promise<T> p;
4190 p.set_exception(ex);
4191 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4192 }
4193
4194 template <typename T, typename E>
4195 BOOST_THREAD_FUTURE<T> make_exceptional_future(E ex) {
4196 promise<T> p;
4197 p.set_exception(boost::copy_exception(ex));
4198 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4199 }
4200
4201 template <typename T>
4202 BOOST_THREAD_FUTURE<T> make_exceptional_future() {
4203 promise<T> p;
4204 p.set_exception(boost::current_exception());
4205 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4206 }
4207 template <typename T>
4208 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) {
4209 return make_exceptional_future<T>(ex);
4210 }
4211
4212#if 0
4213 template<typename CLOSURE>
4214 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
4215 typedef decltype(closure()) T;
4216 promise<T> p;
4217 try {
4218 p.set_value(closure());
4219 } catch(...) {
4220 p.set_exception(std::current_exception());
4221 }
4222 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
4223 }
4224#endif
4225
4226 ////////////////////////////////
4227 // make_shared_future deprecated
4228 ////////////////////////////////
4229 template <typename T>
4230 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) {
4231 typedef typename decay<T>::type future_type;
4232 promise<future_type> p;
4233 p.set_value(boost::forward<T>(value));
4234 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
4235 }
4236
4237 inline shared_future<void> make_shared_future() {
4238 promise<void> p;
4239 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
4240 }
4241
4242 ////////////////////////////////
4243 // detail::future_async_continuation_shared_state
4244 ////////////////////////////////
4245#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
4246
4247namespace detail
4248{
4249 //////////////////////
4250 // detail::continuation_shared_state
4251 //////////////////////
4252 template<typename F, typename Rp, typename Fp, class ShSt=shared_state<Rp> >
4253 struct continuation_shared_state: ShSt
4254 {
4255 F parent;
4256 Fp continuation;
4257
4258 public:
4259 continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4260 : parent(boost::move(f)),
4261 continuation(boost::move(c))
4262 {
4263 }
4264
4265 void init(boost::unique_lock<boost::mutex> &lock)
4266 {
4267 parent.future_->set_continuation_ptr(this->shared_from_this(), lock);
4268 }
4269
4270 void call() {
4271 try {
4272 this->mark_finished_with_result(this->continuation(boost::move(this->parent)));
4273 } catch(...) {
4274 this->mark_exceptional_finish();
4275 }
4276 // make sure parent is really cleared to prevent memory "leaks"
4277 this->parent = F();
4278 }
4279
4280 void call(boost::unique_lock<boost::mutex>& lck) {
4281 try {
4282 relocker relock(lck);
4283
4284 // neither continuation nor parent are protected by the lock - call() must only
4285 // be called once, and no one else must modify it.
4286 Rp res = this->continuation(boost::move(this->parent));
4287
4288 // make sure parent is really cleared to prevent memory "leaks"
4289 this->parent = F();
4290
4291 relock.lock();
4292
4293 this->mark_finished_with_result_internal(boost::move(res), lck);
4294 } catch (...) {
4295 this->mark_exceptional_finish_internal(current_exception(), lck);
4296
4297 // make sure parent is really cleared to prevent memory "leaks"
4298 relocker relock(lck);
4299 this->parent = F();
4300 }
4301 }
4302
4303 static void run(shared_ptr<boost::detail::shared_state_base> that_)
4304 {
4305 continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get());
4306 that->call();
4307 }
4308
4309 ~continuation_shared_state() {}
4310 };
4311
4312 template<typename F, typename Fp, class ShSt>
4313 struct continuation_shared_state<F, void, Fp, ShSt>: ShSt
4314 {
4315 F parent;
4316 Fp continuation;
4317
4318 public:
4319 continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4320 : parent(boost::move(f)),
4321 continuation(boost::move(c))
4322 {
4323 }
4324
4325 void init(boost::unique_lock<boost::mutex> &lock)
4326 {
4327 parent.future_->set_continuation_ptr(this->shared_from_this(), lock);
4328 }
4329
4330 void call()
4331 {
4332 try {
4333 this->continuation(boost::move(this->parent));
4334 this->mark_finished_with_result();
4335 } catch(...) {
4336 this->mark_exceptional_finish();
4337 }
4338 // make sure parent is really cleared to prevent memory "leaks"
4339 this->parent = F();
4340 }
4341
4342 void call(boost::unique_lock<boost::mutex>& lck) {
4343 try {
4344 {
4345 relocker relock(lck);
4346 // neither continuation nor parent are protected by the lock - call() must only
4347 // be called once, and no one else must modify it.
4348 this->continuation(boost::move(this->parent));
4349
4350 // make sure parent is really cleared to prevent memory "leaks"
4351 this->parent = F();
4352 }
4353 this->mark_finished_with_result_internal(lck);
4354 } catch (...) {
4355 this->mark_exceptional_finish_internal(current_exception(), lck);
4356
4357 // make sure parent is really cleared to prevent memory "leaks"
4358 relocker relock(lck);
4359 this->parent = F();
4360 }
4361 }
4362
4363 static void run(shared_ptr<boost::detail::shared_state_base> that_)
4364 {
4365 continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get());
4366 that->call();
4367 }
4368
4369 ~continuation_shared_state() {}
4370 };
4371 /////////////////////////
4372 /// future_async_continuation_shared_state
4373 /////////////////////////
4374
4375 template<typename F, typename Rp, typename Fp>
4376 struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
4377 {
4378 typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
4379 public:
4380 future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4381 : base_type(boost::move(f), boost::forward<Fp>(c))
4382 { }
4383
4384 void launch_continuation() {
4385#if defined BOOST_THREAD_FUTURE_BLOCKING
4386 boost::lock_guard<boost::mutex> lk(this->mutex);
4387 this->thr_ = boost::thread(&future_async_continuation_shared_state::run, static_shared_from_this(this));
4388#else
4389 boost::thread(&base_type::run, static_shared_from_this(this)).detach();
4390#endif
4391 }
4392 };
4393
4394 /////////////////////////
4395 /// future_sync_continuation_shared_state
4396 /////////////////////////
4397
4398 template<typename F, typename Rp, typename Fp>
4399 struct future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
4400 {
4401 typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
4402 public:
4403 future_sync_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4404 : base_type(boost::move(f), boost::forward<Fp>(c))
4405 { }
4406
4407 void launch_continuation() {
4408 this->call();
4409 }
4410 };
4411
4412
4413 /////////////////////////
4414 /// future_executor_continuation_shared_state
4415 /////////////////////////
4416#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4417
4418 template <typename FutureExecutorContinuationSharedState>
4419 struct run_it {
4420 shared_ptr<FutureExecutorContinuationSharedState> that_;
4421
4422#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
4423 BOOST_THREAD_COPYABLE_AND_MOVABLE(run_it)
4424 run_it(run_it const& x) //BOOST_NOEXCEPT
4425 : that_(x.that_)
4426 {}
4427 run_it& operator=(BOOST_THREAD_COPY_ASSIGN_REF(run_it) x) //BOOST_NOEXCEPT
4428 {
4429 if (this != &x) {
4430 that_=x.that_;
4431 }
4432 return *this;
4433 }
4434 // move
4435 run_it(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT
4436 : that_(x.that_)
4437 {
4438 x.that_.reset();
4439 }
4440 run_it& operator=(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT {
4441 if (this != &x) {
4442 that_=x.that;
4443 x.that_.reset();
4444 }
4445 return *this;
4446 }
4447#endif
4448 run_it(shared_ptr<FutureExecutorContinuationSharedState> that) : that_ (that) {}
4449
4450 void operator()()
4451 {
4452 that_->run(that_);
4453 }
4454 };
4455
4456}
4457 BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::run_it<F> BOOST_THREAD_DCL_MOVABLE_END
4458
4459namespace detail {
4460
4461 template<typename F, typename Rp, typename Fp>
4462 struct future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4463 {
4464 typedef continuation_shared_state<F,Rp,Fp> base_type;
4465
4466 public:
4467 future_executor_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4468 : base_type(boost::move(f), boost::forward<Fp>(c))
4469 {
4470 }
4471
4472 template <class Ex>
4473 void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
4474 {
4475 this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
4476 this->base_type::init(lk);
4477 }
4478
4479 void launch_continuation() {
4480 run_it<base_type> fct(static_shared_from_this(this));
4481 this->get_executor()->submit(boost::move(fct));
4482 }
4483
4484 ~future_executor_continuation_shared_state() {}
4485 };
4486#endif
4487
4488 /////////////////////////
4489 /// shared_future_async_continuation_shared_state
4490 /////////////////////////
4491
4492 template<typename F, typename Rp, typename Fp>
4493 struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
4494 {
4495 typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
4496
4497 public:
4498 shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4499 : base_type(boost::move(f), boost::forward<Fp>(c))
4500 {
4501 }
4502
4503 void launch_continuation() {
4504#if defined BOOST_THREAD_FUTURE_BLOCKING
4505 boost::lock_guard<boost::mutex> lk(this->mutex);
4506 this->thr_ = boost::thread(&base_type::run, static_shared_from_this(this));
4507#else
4508 boost::thread(&base_type::run, static_shared_from_this(this)).detach();
4509#endif
4510 }
4511 };
4512
4513 /////////////////////////
4514 /// shared_future_async_continuation_shared_state
4515 /////////////////////////
4516
4517 template<typename F, typename Rp, typename Fp>
4518 struct shared_future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
4519 {
4520 typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
4521
4522 public:
4523 shared_future_sync_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4524 : base_type(boost::move(f), boost::forward<Fp>(c))
4525 {
4526 }
4527
4528 void launch_continuation() {
4529 this->call();
4530 }
4531 };
4532
4533
4534 /////////////////////////
4535 /// shared_future_executor_continuation_shared_state
4536 /////////////////////////
4537#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4538
4539 template<typename F, typename Rp, typename Fp>
4540 struct shared_future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4541 {
4542 typedef continuation_shared_state<F,Rp,Fp> base_type;
4543
4544 public:
4545
4546 shared_future_executor_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4547 : base_type(boost::move(f), boost::forward<Fp>(c))
4548 {
4549 }
4550
4551 template <class Ex>
4552 void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
4553 {
4554 this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
4555 this->base_type::init(lk);
4556 }
4557
4558 void launch_continuation() {
4559 run_it<base_type> fct(static_shared_from_this(this));
4560 this->get_executor()->submit(boost::move(fct));
4561 }
4562
4563 ~shared_future_executor_continuation_shared_state() {}
4564 };
4565
4566#endif
4567 //////////////////////////
4568 /// future_deferred_continuation_shared_state
4569 //////////////////////////
4570 template<typename F, typename Rp, typename Fp>
4571 struct future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4572 {
4573 typedef continuation_shared_state<F,Rp,Fp> base_type;
4574 public:
4575 future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
4576 : base_type(boost::move(f), boost::forward<Fp>(c))
4577 {
4578 this->set_deferred();
4579 }
4580
4581 virtual void execute(boost::unique_lock<boost::mutex>& lk) {
4582 this->parent.wait();
4583 this->call(lk);
4584 }
4585
4586 virtual void launch_continuation() { }
4587 };
4588
4589 //////////////////////////
4590 /// shared_future_deferred_continuation_shared_state
4591 //////////////////////////
4592 template<typename F, typename Rp, typename Fp>
4593 struct shared_future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
4594 {
4595 typedef continuation_shared_state<F,Rp,Fp> base_type;
4596
4597 public:
4598 shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
4599 : base_type(boost::move(f), boost::forward<Fp>(c))
4600 {
4601 this->set_deferred();
4602 }
4603
4604 virtual void execute(boost::unique_lock<boost::mutex>& lk) {
4605 this->parent.wait();
4606 this->call(lk);
4607 }
4608
4609 virtual void launch_continuation() { }
4610 };
4611
4612 ////////////////////////////////
4613 // make_future_deferred_continuation_shared_state
4614 ////////////////////////////////
4615 template<typename F, typename Rp, typename Fp>
4616 BOOST_THREAD_FUTURE<Rp>
4617 make_future_deferred_continuation_shared_state(
4618 boost::unique_lock<boost::mutex> &lock,
4619 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) {
4620 typedef typename decay<Fp>::type Cont;
4621 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Cont> >
4622 h(new future_deferred_continuation_shared_state<F, Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4623 h->init(lock);
4624 return BOOST_THREAD_FUTURE<Rp>(h);
4625 }
4626
4627 ////////////////////////////////
4628 // make_future_async_continuation_shared_state
4629 ////////////////////////////////
4630 template<typename F, typename Rp, typename Fp>
4631 BOOST_THREAD_FUTURE<Rp>
4632 make_future_async_continuation_shared_state(
4633 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4634 BOOST_THREAD_FWD_REF(Fp) c) {
4635 typedef typename decay<Fp>::type Cont;
4636 shared_ptr<future_async_continuation_shared_state<F,Rp, Cont> >
4637 h(new future_async_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4638 h->init(lock);
4639
4640 return BOOST_THREAD_FUTURE<Rp>(h);
4641 }
4642 ////////////////////////////////
4643 // make_future_sync_continuation_shared_state
4644 ////////////////////////////////
4645 template<typename F, typename Rp, typename Fp>
4646 BOOST_THREAD_FUTURE<Rp>
4647 make_future_sync_continuation_shared_state(
4648 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4649 BOOST_THREAD_FWD_REF(Fp) c) {
4650 typedef typename decay<Fp>::type Cont;
4651 shared_ptr<future_sync_continuation_shared_state<F,Rp, Cont> >
4652 h(new future_sync_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4653 h->init(lock);
4654
4655 return BOOST_THREAD_FUTURE<Rp>(h);
4656 }
4657
4658 ////////////////////////////////
4659 // make_future_executor_continuation_shared_state
4660 ////////////////////////////////
4661#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4662
4663 template<typename Ex, typename F, typename Rp, typename Fp>
4664 BOOST_THREAD_FUTURE<Rp>
4665 make_future_executor_continuation_shared_state(Ex& ex,
4666 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
4667 BOOST_THREAD_FWD_REF(Fp) c) {
4668 typedef typename decay<Fp>::type Cont;
4669 shared_ptr<future_executor_continuation_shared_state<F,Rp, Cont> >
4670 h(new future_executor_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
4671 h->init(lock, ex);
4672
4673 return BOOST_THREAD_FUTURE<Rp>(h);
4674 }
4675#endif
4676
4677 ////////////////////////////////
4678 // make_shared_future_deferred_continuation_shared_state
4679 ////////////////////////////////
4680 template<typename F, typename Rp, typename Fp>
4681 BOOST_THREAD_FUTURE<Rp>
4682 make_shared_future_deferred_continuation_shared_state(
4683 boost::unique_lock<boost::mutex> &lock,
4684 F f, BOOST_THREAD_FWD_REF(Fp) c) {
4685 typedef typename decay<Fp>::type Cont;
4686 shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Cont> >
4687 h(new shared_future_deferred_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c)));
4688 h->init(lock);
4689
4690 return BOOST_THREAD_FUTURE<Rp>(h);
4691 }
4692 ////////////////////////////////
4693 // make_shared_future_async_continuation_shared_state
4694 ////////////////////////////////
4695 template<typename F, typename Rp, typename Fp>
4696 BOOST_THREAD_FUTURE<Rp>
4697 make_shared_future_async_continuation_shared_state(
4698 boost::unique_lock<boost::mutex> &lock, F f,
4699 BOOST_THREAD_FWD_REF(Fp) c) {
4700 typedef typename decay<Fp>::type Cont;
4701 shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Cont> >
4702 h(new shared_future_async_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
4703 h->init(lock);
4704
4705 return BOOST_THREAD_FUTURE<Rp>(h);
4706 }
4707 ////////////////////////////////
4708 // make_shared_future_sync_continuation_shared_state
4709 ////////////////////////////////
4710 template<typename F, typename Rp, typename Fp>
4711 BOOST_THREAD_FUTURE<Rp>
4712 make_shared_future_sync_continuation_shared_state(
4713 boost::unique_lock<boost::mutex> &lock, F f,
4714 BOOST_THREAD_FWD_REF(Fp) c) {
4715 typedef typename decay<Fp>::type Cont;
4716 shared_ptr<shared_future_sync_continuation_shared_state<F,Rp, Cont> >
4717 h(new shared_future_sync_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
4718 h->init(lock);
4719
4720 return BOOST_THREAD_FUTURE<Rp>(h);
4721 }
4722 ////////////////////////////////
4723 // make_shared_future_executor_continuation_shared_state
4724 ////////////////////////////////
4725#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4726 template<typename Ex, typename F, typename Rp, typename Fp>
4727 BOOST_THREAD_FUTURE<Rp>
4728 make_shared_future_executor_continuation_shared_state(Ex& ex,
4729 boost::unique_lock<boost::mutex> &lock, F f,
4730 BOOST_THREAD_FWD_REF(Fp) c) {
4731 typedef typename decay<Fp>::type Cont;
4732 shared_ptr<shared_future_executor_continuation_shared_state<F, Rp, Cont> >
4733 h(new shared_future_executor_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c)));
4734 h->init(lock, ex);
4735
4736 return BOOST_THREAD_FUTURE<Rp>(h);
4737 }
4738#endif
4739}
4740
4741 ////////////////////////////////
4742 // template<typename F>
4743 // auto future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4744 ////////////////////////////////
4745 template <typename R>
4746 template <typename F>
4747 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
4748 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
4749 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4750 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4751
4752 // keep state alive as we move ourself but hold the lock
4753 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4754 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4755
4756 if (underlying_cast<int>(policy) & int(launch::async)) {
4757 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4758 lock, boost::move(*this), boost::forward<F>(func)
4759 )));
4760 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
4761 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4762 lock, boost::move(*this), boost::forward<F>(func)
4763 )));
4764#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4765 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
4766 assert(this->future_->get_executor());
4767 typedef executor Ex;
4768 Ex& ex = *(this->future_->get_executor());
4769 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4770 lock, boost::move(*this), boost::forward<F>(func)
4771 )));
4772#endif
4773 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
4774
4775 launch policy_ = this->launch_policy(lock);
4776 if (underlying_cast<int>(policy_) & int(launch::async)) {
4777 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4778 lock, boost::move(*this), boost::forward<F>(func)
4779 )));
4780 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
4781 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4782 lock, boost::move(*this), boost::forward<F>(func)
4783 )));
4784#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4785 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
4786 assert(this->future_->get_executor());
4787 typedef executor Ex;
4788 Ex& ex = *(this->future_->get_executor());
4789 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4790 lock, boost::move(*this), boost::forward<F>(func)
4791 )));
4792#endif
4793 } else {
4794 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4795 lock, boost::move(*this), boost::forward<F>(func)
4796 )));
4797 }
4798 } else {
4799 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4800 lock, boost::move(*this), boost::forward<F>(func)
4801 )));
4802 }
4803 }
4804#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4805 ////////////////////////////////
4806 // template<typename Ex, typename F>
4807 // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4808 ////////////////////////////////
4809 template <typename R>
4810 template <typename Ex, typename F>
4811 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
4812 BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
4813 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4814 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4815
4816 // keep state alive as we move ourself but hold the lock
4817 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4818 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4819
4820 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4821 lock, boost::move(*this), boost::forward<F>(func)
4822 )));
4823 }
4824#endif
4825 ////////////////////////////////
4826 // template<typename F>
4827 // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4828 ////////////////////////////////
4829 template <typename R>
4830 template <typename F>
4831 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
4832 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) {
4833
4834#ifndef BOOST_THREAD_CONTINUATION_SYNC
4835 return this->then(this->launch_policy(), boost::forward<F>(func));
4836#else
4837 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4838 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4839
4840 // keep state alive as we move ourself but hold the lock
4841 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4842 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4843
4844 launch policy = this->launch_policy(lock);
4845 if (underlying_cast<int>(policy) & int(launch::deferred)) {
4846 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4847 lock, boost::move(*this), boost::forward<F>(func)
4848 )));
4849 } else {
4850 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4851 lock, boost::move(*this), boost::forward<F>(func)
4852 )));
4853 }
4854#endif
4855
4856 }
4857
4858 ////////////////////////////////
4859 // template<typename F>
4860 // auto future<future<R2> >::then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4861 ////////////////////////////////
4862 template <typename R2>
4863 template <typename F>
4864 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
4865 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
4866 typedef BOOST_THREAD_FUTURE<R2> R;
4867 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4868 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4869
4870 // keep state alive as we move ourself but hold the lock
4871 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4872 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4873
4874 if (underlying_cast<int>(policy) & int(launch::async)) {
4875 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4876 lock, boost::move(*this), boost::forward<F>(func)
4877 )));
4878 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
4879 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4880 lock, boost::move(*this), boost::forward<F>(func)
4881 )));
4882 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
4883 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4884 lock, boost::move(*this), boost::forward<F>(func)
4885 )));
4886#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4887 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
4888 assert(this->future_->get_executor());
4889 typedef executor Ex;
4890 Ex& ex = *(this->future_->get_executor());
4891 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4892 lock, boost::move(*this), boost::forward<F>(func)
4893 )));
4894#endif
4895 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
4896 launch policy_ = this->launch_policy(lock);
4897
4898 if (underlying_cast<int>(policy_) & int(launch::async)) {
4899 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4900 lock, boost::move(*this), boost::forward<F>(func)
4901 )));
4902 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
4903 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4904 lock, boost::move(*this), boost::forward<F>(func)
4905 )));
4906 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
4907 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4908 lock, boost::move(*this), boost::forward<F>(func)
4909 )));
4910#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4911 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
4912 assert(this->future_->get_executor());
4913 typedef executor Ex;
4914 Ex& ex = *(this->future_->get_executor());
4915 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4916 lock, boost::move(*this), boost::forward<F>(func)
4917 )));
4918#endif
4919 } else {
4920 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4921 lock, boost::move(*this), boost::forward<F>(func)
4922 )));
4923 }
4924 } else {
4925 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4926 lock, boost::move(*this), boost::forward<F>(func)
4927 )));
4928 }
4929 }
4930
4931#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
4932 ////////////////////////////////
4933 // template<typename Ex, typename F>
4934 // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4935 ////////////////////////////////
4936 template <typename R2>
4937 template <typename Ex, typename F>
4938 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
4939 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
4940 typedef BOOST_THREAD_FUTURE<R2> R;
4941 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4942 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4943
4944 // keep state alive as we move ourself but hold the lock
4945 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4946 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4947
4948 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
4949 lock, boost::move(*this), boost::forward<F>(func)
4950 )));
4951 }
4952#endif
4953
4954 ////////////////////////////////
4955 // template<typename F>
4956 // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4957 ////////////////////////////////
4958 template <typename R2>
4959 template <typename F>
4960 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
4961 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) {
4962
4963#ifndef BOOST_THREAD_CONTINUATION_SYNC
4964 return this->then(this->launch_policy(), boost::forward<F>(func));
4965#else
4966 typedef BOOST_THREAD_FUTURE<R2> R;
4967 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
4968 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4969
4970 // keep state alive as we move ourself but hold the lock
4971 shared_ptr<detail::shared_state_base> sentinel(this->future_);
4972 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
4973
4974 launch policy = this->launch_policy(lock);
4975
4976 if (underlying_cast<int>(policy) & int(launch::deferred)) {
4977 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4978 lock, boost::move(*this), boost::forward<F>(func)
4979 )));
4980 } else {
4981 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
4982 lock, boost::move(*this), boost::forward<F>(func)
4983 )));
4984 }
4985#endif
4986 }
4987
4988 ////////////////////////////////
4989 // template<typename F>
4990 // auto shared_future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
4991 ////////////////////////////////
4992 template <typename R>
4993 template <typename F>
4994 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
4995 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const
4996 {
4997 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
4998 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4999
5000 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5001 if (underlying_cast<int>(policy) & int(launch::async)) {
5002 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5003 lock, *this, boost::forward<F>(func)
5004 )));
5005 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
5006 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5007 lock, *this, boost::forward<F>(func)
5008 )));
5009 } else if (underlying_cast<int>(policy) & int(launch::sync)) {
5010 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5011 lock, *this, boost::forward<F>(func)
5012 )));
5013#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5014 } else if (underlying_cast<int>(policy) & int(launch::executor)) {
5015 typedef executor Ex;
5016 Ex& ex = *(this->future_->get_executor());
5017 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5018 lock, *this, boost::forward<F>(func)
5019 )));
5020#endif
5021 } else if (underlying_cast<int>(policy) & int(launch::inherit)) {
5022
5023 launch policy_ = this->launch_policy(lock);
5024 if (underlying_cast<int>(policy_) & int(launch::async)) {
5025 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5026 lock, *this, boost::forward<F>(func)
5027 )));
5028 } else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
5029 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5030 lock, *this, boost::forward<F>(func)
5031 )));
5032 } else if (underlying_cast<int>(policy_) & int(launch::sync)) {
5033 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5034 lock, *this, boost::forward<F>(func)
5035 )));
5036#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5037 } else if (underlying_cast<int>(policy_) & int(launch::executor)) {
5038 typedef executor Ex;
5039 Ex& ex = *(this->future_->get_executor());
5040 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5041 lock, *this, boost::forward<F>(func)
5042 )));
5043#endif
5044 } else {
5045 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5046 lock, *this, boost::forward<F>(func)
5047 )));
5048 }
5049
5050 } else {
5051 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
5052 lock, *this, boost::forward<F>(func)
5053 )));
5054 }
5055 }
5056#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
5057 ////////////////////////////////
5058 // template<typename Ex, typename F>
5059 // auto shared_future<R>::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5060 ////////////////////////////////
5061 template <typename R>
5062 template <typename Ex, typename F>
5063 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5064 shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const
5065 {
5066 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5067 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
5068
5069 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5070 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
5071 lock, *this, boost::forward<F>(func)
5072 )));
5073 }
5074#endif
5075
5076 ////////////////////////////////
5077 // template<typename F>
5078 // auto shared_future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
5079 ////////////////////////////////
5080 template <typename R>
5081 template <typename F>
5082 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
5083 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const {
5084#ifndef BOOST_THREAD_CONTINUATION_SYNC
5085 return this->then(this->launch_policy(), boost::forward<F>(func));
5086#else
5087 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
5088 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
5089
5090 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
5091 launch policy = this->launch_policy(lock);
5092 if (underlying_cast<int>(policy) & int(launch::deferred)) {
5093 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
5094 lock, *this, boost::forward<F>(func)
5095 )));
5096 } else {
5097 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
5098 lock, *this, boost::forward<F>(func)
5099 )));
5100 }
5101#endif
5102 }
5103
5104namespace detail
5105{
5106 template <typename T>
5107 struct mfallbacker_to
5108 {
5109 T value_;
5110 typedef T result_type;
5111 mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
5112 : value_(boost::move(v))
5113 {}
5114
5115 T operator()(BOOST_THREAD_FUTURE<T> fut) {
5116 return fut.get_or(boost::move(value_));
5117 }
5118 };
5119 template <typename T>
5120 struct cfallbacker_to
5121 {
5122 T value_;
5123 typedef T result_type;
5124 cfallbacker_to(T const& v)
5125 : value_(v)
5126 {}
5127
5128 T operator()(BOOST_THREAD_FUTURE<T> fut) const {
5129 return fut.get_or(value_);
5130
5131 }
5132 };
5133}
5134 ////////////////////////////////
5135 // future<R> future<R>::fallback_to(R&& v);
5136 ////////////////////////////////
5137
5138 template <typename R>
5139 template <typename R2>
5140 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
5141 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) {
5142 return then(detail::mfallbacker_to<R>(boost::move(v)));
5143 }
5144
5145 template <typename R>
5146 template <typename R2>
5147 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
5148 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) {
5149 return then(detail::cfallbacker_to<R>(v));
5150 }
5151
5152#endif
5153
5154#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
5155namespace detail
5156{
5157 /////////////////////////
5158 /// future_unwrap_shared_state
5159 /////////////////////////
5160
5161 template<typename F, typename Rp>
5162 struct future_unwrap_shared_state: shared_state<Rp>
5163 {
5164 F wrapped;
5165 typename F::value_type unwrapped;
5166 public:
5167 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
5168 : wrapped(boost::move(f)) {
5169 }
5170
5171 void launch_continuation()
5172 {
5173 boost::unique_lock<boost::mutex> lk(this->mutex);
5174 // assert(wrapped.is_ready());
5175 if (! unwrapped.valid() )
5176 {
5177 if (wrapped.has_exception()) {
5178 this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk);
5179 } else {
5180 unwrapped = wrapped.get();
5181 if (unwrapped.valid())
5182 {
5183 lk.unlock();
5184 boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex);
5185 unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2);
5186 } else {
5187 this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk);
5188 }
5189 }
5190 } else {
5191 // assert(unwrapped.is_ready());
5192 if (unwrapped.has_exception()) {
5193 this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk);
5194 } else {
5195 this->mark_finished_with_result_internal(unwrapped.get(), lk);
5196 }
5197 }
5198 }
5199 };
5200
5201 template<typename F>
5202 struct future_unwrap_shared_state<F,void>: shared_state<void>
5203 {
5204 F wrapped;
5205 typename F::value_type unwrapped;
5206 public:
5207 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
5208 : wrapped(boost::move(f)) {
5209 }
5210
5211 void launch_continuation()
5212 {
5213 boost::unique_lock<boost::mutex> lk(this->mutex);
5214 // assert(wrapped.is_ready());
5215 if (! unwrapped.valid() )
5216 {
5217 if (wrapped.has_exception()) {
5218 this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk);
5219 } else {
5220 unwrapped = wrapped.get();
5221 if (unwrapped.valid())
5222 {
5223 lk.unlock();
5224 boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex);
5225 unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2);
5226 } else {
5227 this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk);
5228 }
5229 }
5230 } else {
5231 // assert(unwrapped.is_ready());
5232 if (unwrapped.has_exception()) {
5233 this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk);
5234 } else {
5235 this->mark_finished_with_result_internal(lk);
5236 }
5237 }
5238 }
5239 };
5240
5241 template <class F, class Rp>
5242 BOOST_THREAD_FUTURE<Rp>
5243 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) {
5244 shared_ptr<future_unwrap_shared_state<F, Rp> >
5245 h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
5246 h->wrapped.future_->set_continuation_ptr(h, lock);
5247
5248 return BOOST_THREAD_FUTURE<Rp>(h);
5249 }
5250}
5251
5252 template <typename R>
5253 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other)
5254 : base_type(other.unwrap()) {}
5255
5256 template <typename R2>
5257 BOOST_THREAD_FUTURE<R2>
5258 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
5259 {
5260 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
5261
5262 // keep state alive as we move ourself but hold the lock
5263 shared_ptr<detail::shared_state_base> sentinel(this->future_);
5264 boost::unique_lock<boost::mutex> lock(sentinel->mutex);
5265
5266 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
5267 }
5268#endif
5269
5270#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
5271namespace detail
5272{
5273 struct input_iterator_tag {};
5274 struct vector_tag {};
5275 struct values_tag {};
5276 template <typename T>
5277 struct alias_t { typedef T type; };
5278
5279 BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {};
5280 BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {};
5281 BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {};
5282 ////////////////////////////////
5283 // detail::future_async_when_all_shared_state
5284 ////////////////////////////////
5285 template<typename F>
5286 struct future_when_all_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
5287 {
5288 typedef csbl::vector<F> vector_type;
5289 typedef typename F::value_type value_type;
5290 vector_type vec_;
5291
5292 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
5293 future_when_all_vector_shared_state* that = static_cast<future_when_all_vector_shared_state*>(that_.get());
5294 try {
5295 boost::wait_for_all(that->vec_.begin(), that->vec_.end());
5296 that->mark_finished_with_result(boost::move(that->vec_));
5297 } catch(...) {
5298 that->mark_exceptional_finish();
5299 }
5300 }
5301 bool run_deferred() {
5302
5303 bool res = false;
5304 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
5305 if (! it->run_if_is_deferred())
5306 {
5307 res = true;
5308 }
5309 }
5310 return res;
5311 }
5312 void init() {
5313 if (! run_deferred())
5314 {
5315 future_when_all_vector_shared_state::run(this->shared_from_this());
5316 return;
5317 }
5318#ifdef BOOST_THREAD_FUTURE_BLOCKING
5319 this->thr_ = boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this());
5320#else
5321 boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this()).detach();
5322#endif
5323 }
5324
5325 public:
5326 template< typename InputIterator>
5327 future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
5328 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
5329 {
5330 }
5331
5332 future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
5333 : vec_(boost::move(v))
5334 {
5335 }
5336
5337#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5338 template< typename T0, typename ...T>
5339 future_when_all_vector_shared_state(values_tag, BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5340 vec_.push_back(boost::forward<T0>(f));
5341 typename alias_t<char[]>::type{
5342 ( //first part of magic unpacker
5343 vec_.push_back(boost::forward<T>(futures)),'0'
5344 )..., '0'
5345 }; //second part of magic unpacker
5346 }
5347#endif
5348
5349 ~future_when_all_vector_shared_state() {}
5350 };
5351
5352 ////////////////////////////////
5353 // detail::future_async_when_any_shared_state
5354 ////////////////////////////////
5355 template<typename F>
5356 struct future_when_any_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
5357 {
5358 typedef csbl::vector<F> vector_type;
5359 typedef typename F::value_type value_type;
5360 vector_type vec_;
5361
5362 static void run(shared_ptr<boost::detail::shared_state_base> that_)
5363 {
5364 future_when_any_vector_shared_state* that = static_cast<future_when_any_vector_shared_state*>(that_.get());
5365 try {
5366 boost::wait_for_any(that->vec_.begin(), that->vec_.end());
5367 that->mark_finished_with_result(boost::move(that->vec_));
5368 } catch(...) {
5369 that->mark_exceptional_finish();
5370 }
5371 }
5372 bool run_deferred() {
5373
5374 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
5375 if (it->run_if_is_deferred_or_ready())
5376 {
5377 return true;
5378 }
5379 }
5380 return false;
5381 }
5382 void init() {
5383 if (run_deferred())
5384 {
5385 future_when_any_vector_shared_state::run(this->shared_from_this());
5386 return;
5387 }
5388
5389#ifdef BOOST_THREAD_FUTURE_BLOCKING
5390 this->thr_ = boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this());
5391#else
5392 boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this()).detach();
5393#endif
5394 }
5395
5396 public:
5397 template< typename InputIterator>
5398 future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
5399 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
5400 {
5401 }
5402
5403 future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
5404 : vec_(boost::move(v))
5405 {
5406 }
5407
5408#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5409 template< typename T0, typename ...T>
5410 future_when_any_vector_shared_state(values_tag,
5411 BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures
5412 ) {
5413 vec_.push_back(boost::forward<T0>(f));
5414 typename alias_t<char[]>::type{
5415 ( //first part of magic unpacker
5416 vec_.push_back(boost::forward<T>(futures))
5417 ,'0'
5418 )...,
5419 '0'
5420 }; //second part of magic unpacker
5421 }
5422#endif
5423
5424 ~future_when_any_vector_shared_state() {}
5425 };
5426
5427#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5428 struct wait_for_all_fctr {
5429 template <class ...T>
5430 void operator()(T&&... v) {
5431 boost::wait_for_all(boost::forward<T>(v)...);
5432 }
5433 };
5434
5435 struct wait_for_any_fctr {
5436 template <class ...T>
5437 void operator()(T&&... v) {
5438 boost::wait_for_any(boost::forward<T>(v)...);
5439 }
5440 };
5441
5442
5443 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
5444 struct accumulate_run_if_is_deferred {
5445 bool operator ()(Tuple& t)
5446 {
5447 return (! csbl::get<i-1>(t).run_if_is_deferred()) || accumulate_run_if_is_deferred<Tuple,i-1>()(t);
5448 }
5449 };
5450 template <class Tuple>
5451 struct accumulate_run_if_is_deferred<Tuple, 0> {
5452 bool operator ()(Tuple& )
5453 {
5454 return false;
5455 }
5456 };
5457
5458
5459 template< typename Tuple, typename T0, typename ...T>
5460 struct future_when_all_tuple_shared_state: future_async_shared_state_base<Tuple>
5461 {
5462 Tuple tup_;
5463 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
5464
5465 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
5466 future_when_all_tuple_shared_state* that = static_cast<future_when_all_tuple_shared_state*>(that_.get());
5467 try {
5468 // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor());
5469 that->wait_for_all(Index());
5470
5471 that->mark_finished_with_result(boost::move(that->tup_));
5472 } catch(...) {
5473 that->mark_exceptional_finish();
5474 }
5475 }
5476
5477 template <size_t ...Indices>
5478 void wait_for_all(tuple_indices<Indices...>) {
5479#if defined BOOST_THREAD_PROVIDES_INVOKE
5480 return invoke<void>(wait_for_all_fctr(), csbl::get<Indices>(tup_)...);
5481#else
5482 return wait_for_all_fctr()(csbl::get<Indices>(tup_)...);
5483#endif
5484 }
5485
5486 bool run_deferred() {
5487
5488 return accumulate_run_if_is_deferred<Tuple>()(tup_);
5489 }
5490 void init() {
5491 if (! run_deferred())
5492 {
5493 future_when_all_tuple_shared_state::run(this->shared_from_this());
5494 return;
5495 }
5496#ifdef BOOST_THREAD_FUTURE_BLOCKING
5497 this->thr_ = boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this());
5498#else
5499 boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()).detach();
5500#endif
5501
5502 }
5503 public:
5504 template< typename F, typename ...Fs>
5505 future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) :
5506 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
5507 {
5508 }
5509
5510 ~future_when_all_tuple_shared_state() {}
5511
5512 };
5513
5514
5515 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
5516 struct apply_any_run_if_is_deferred_or_ready {
5517 bool operator ()(Tuple& t)
5518 {
5519 if (csbl::get<i-1>(t).run_if_is_deferred_or_ready()) return true;
5520 return apply_any_run_if_is_deferred_or_ready<Tuple,i-1>()(t);
5521 }
5522 };
5523 template <class Tuple>
5524 struct apply_any_run_if_is_deferred_or_ready<Tuple, 0> {
5525 bool operator ()(Tuple& )
5526 {
5527 return false;
5528 }
5529 };
5530
5531 template< typename Tuple, typename T0, typename ...T >
5532 struct future_when_any_tuple_shared_state: future_async_shared_state_base<Tuple>
5533 {
5534 Tuple tup_;
5535 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
5536
5537 static void run(shared_ptr<boost::detail::shared_state_base> that_)
5538 {
5539 future_when_any_tuple_shared_state* that = static_cast<future_when_any_tuple_shared_state*>(that_.get());
5540 try {
5541 // TODO make use of apply(that->tup_, wait_for_any_fctr);
5542 that->wait_for_any(Index());
5543
5544 that->mark_finished_with_result(boost::move(that->tup_));
5545 } catch(...) {
5546 that->mark_exceptional_finish();
5547 }
5548 }
5549 template <size_t ...Indices>
5550 void wait_for_any(tuple_indices<Indices...>) {
5551#if defined BOOST_THREAD_PROVIDES_INVOKE
5552 return invoke<void>(wait_for_any_fctr(), csbl::get<Indices>(tup_)...);
5553#else
5554 return wait_for_any_fctr()(csbl::get<Indices>(tup_)...);
5555#endif
5556 }
5557 bool run_deferred() {
5558 return apply_any_run_if_is_deferred_or_ready<Tuple>()(tup_);
5559 }
5560 void init() {
5561 if (run_deferred())
5562 {
5563 future_when_any_tuple_shared_state::run(this->shared_from_this());
5564 return;
5565 }
5566
5567#ifdef BOOST_THREAD_FUTURE_BLOCKING
5568 this->thr_ = boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this());
5569#else
5570 boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()).detach();
5571#endif
5572 }
5573
5574 public:
5575 template< typename F, typename ...Fs>
5576 future_when_any_tuple_shared_state(values_tag,
5577 BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures
5578 ) :
5579 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
5580 {
5581 }
5582
5583 ~future_when_any_tuple_shared_state() {}
5584 };
5585#endif
5586
5587}
5588
5589 template< typename InputIterator>
5590 typename boost::disable_if<is_future_type<InputIterator>,
5591 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
5592 >::type
5593 when_all(InputIterator first, InputIterator last) {
5594 typedef typename InputIterator::value_type value_type;
5595 typedef csbl::vector<value_type> container_type;
5596 typedef detail::future_when_all_vector_shared_state<value_type> factory_type;
5597
5598 if (first==last) return make_ready_future(container_type());
5599 shared_ptr<factory_type >
5600 h(new factory_type(detail::input_iterator_tag_value, first,last));
5601 h->init();
5602 return BOOST_THREAD_FUTURE<container_type>(h);
5603 }
5604
5605 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all() {
5606 return make_ready_future(csbl::tuple<>());
5607 }
5608
5609#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5610 template< typename T0, typename ...T>
5611 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
5612 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5613 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
5614 typedef detail::future_when_all_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
5615
5616 shared_ptr<factory_type>
5617 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
5618 h->init();
5619 return BOOST_THREAD_FUTURE<container_type>(h);
5620 }
5621#endif
5622
5623 template< typename InputIterator>
5624 typename boost::disable_if<is_future_type<InputIterator>,
5625 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
5626 >::type
5627 when_any(InputIterator first, InputIterator last) {
5628 typedef typename InputIterator::value_type value_type;
5629 typedef csbl::vector<value_type> container_type;
5630 typedef detail::future_when_any_vector_shared_state<value_type> factory_type;
5631
5632 if (first==last) return make_ready_future(container_type());
5633 shared_ptr<factory_type >
5634 h(new factory_type(detail::input_iterator_tag_value, first,last));
5635 h->init();
5636 return BOOST_THREAD_FUTURE<container_type>(h);
5637 }
5638
5639 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any() {
5640 return make_ready_future(csbl::tuple<>());
5641 }
5642
5643#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
5644 template< typename T0, typename ...T>
5645 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
5646 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
5647 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
5648 typedef detail::future_when_any_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
5649
5650 shared_ptr<factory_type>
5651 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
5652 h->init();
5653 return BOOST_THREAD_FUTURE<container_type>(h);
5654 }
5655#endif
5656#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
5657}
5658
5659#endif // BOOST_NO_EXCEPTION
5660#endif // header