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