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