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