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