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

source code of boost/libs/thread/include/boost/thread/future.hpp