Ticket #11275: future.hpp

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