comparison DEPENDENCIES/generic/include/boost/thread/future.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 // (C) Copyright 2008-10 Anthony Williams
2 // (C) Copyright 2011-2013 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 #ifndef BOOST_NO_EXCEPTIONS
17
18 //#include <boost/thread/detail/log.hpp>
19 #include <boost/detail/scoped_enum_emulation.hpp>
20 #include <stdexcept>
21 #include <boost/thread/detail/move.hpp>
22 #include <boost/thread/detail/async_func.hpp>
23 #include <boost/thread/thread_time.hpp>
24 #include <boost/thread/mutex.hpp>
25 #include <boost/thread/condition_variable.hpp>
26 #include <boost/thread/lock_algorithms.hpp>
27 #include <boost/thread/lock_types.hpp>
28 #include <boost/exception_ptr.hpp>
29 #include <boost/shared_ptr.hpp>
30 #include <boost/scoped_ptr.hpp>
31 #include <boost/type_traits/is_fundamental.hpp>
32 #include <boost/thread/detail/is_convertible.hpp>
33 #include <boost/type_traits/remove_reference.hpp>
34 #include <boost/type_traits/remove_cv.hpp>
35 #include <boost/type_traits/is_void.hpp>
36 #include <boost/mpl/if.hpp>
37 #include <boost/config.hpp>
38 #include <boost/throw_exception.hpp>
39 #include <algorithm>
40 #include <boost/function.hpp>
41 #include <boost/bind.hpp>
42 #include <boost/ref.hpp>
43 #include <boost/scoped_array.hpp>
44 #include <boost/enable_shared_from_this.hpp>
45 #include <boost/utility/enable_if.hpp>
46 #include <list>
47 #include <boost/next_prior.hpp>
48 #include <vector>
49
50 #include <boost/thread/future_error_code.hpp>
51 #ifdef BOOST_THREAD_USES_CHRONO
52 #include <boost/chrono/system_clocks.hpp>
53 #endif
54
55 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
56 #include <boost/thread/detail/memory.hpp>
57 #endif
58
59 #include <boost/utility/result_of.hpp>
60 #include <boost/thread/thread_only.hpp>
61
62 #if defined BOOST_THREAD_PROVIDES_FUTURE
63 #define BOOST_THREAD_FUTURE future
64 #else
65 #define BOOST_THREAD_FUTURE unique_future
66 #endif
67
68 namespace boost
69 {
70
71 //enum class launch
72 BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
73 {
74 none = 0,
75 async = 1,
76 deferred = 2,
77 any = async | deferred
78 }
79 BOOST_SCOPED_ENUM_DECLARE_END(launch)
80
81 //enum class future_status
82 BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
83 {
84 ready,
85 timeout,
86 deferred
87 }
88 BOOST_SCOPED_ENUM_DECLARE_END(future_status)
89
90 class BOOST_SYMBOL_VISIBLE future_error
91 : public std::logic_error
92 {
93 system::error_code ec_;
94 public:
95 future_error(system::error_code ec)
96 : logic_error(ec.message()),
97 ec_(ec)
98 {
99 }
100
101 const system::error_code& code() const BOOST_NOEXCEPT
102 {
103 return ec_;
104 }
105 };
106
107 class BOOST_SYMBOL_VISIBLE future_uninitialized:
108 public future_error
109 {
110 public:
111 future_uninitialized() :
112 future_error(system::make_error_code(future_errc::no_state))
113 {}
114 };
115 class BOOST_SYMBOL_VISIBLE broken_promise:
116 public future_error
117 {
118 public:
119 broken_promise():
120 future_error(system::make_error_code(future_errc::broken_promise))
121 {}
122 };
123 class BOOST_SYMBOL_VISIBLE future_already_retrieved:
124 public future_error
125 {
126 public:
127 future_already_retrieved():
128 future_error(system::make_error_code(future_errc::future_already_retrieved))
129 {}
130 };
131 class BOOST_SYMBOL_VISIBLE promise_already_satisfied:
132 public future_error
133 {
134 public:
135 promise_already_satisfied():
136 future_error(system::make_error_code(future_errc::promise_already_satisfied))
137 {}
138 };
139
140 class BOOST_SYMBOL_VISIBLE task_already_started:
141 public future_error
142 {
143 public:
144 task_already_started():
145 future_error(system::make_error_code(future_errc::promise_already_satisfied))
146 {}
147 };
148
149 class BOOST_SYMBOL_VISIBLE task_moved:
150 public future_error
151 {
152 public:
153 task_moved():
154 future_error(system::make_error_code(future_errc::no_state))
155 {}
156 };
157
158 class promise_moved:
159 public future_error
160 {
161 public:
162 promise_moved():
163 future_error(system::make_error_code(future_errc::no_state))
164 {}
165 };
166
167 namespace future_state
168 {
169 enum state { uninitialized, waiting, ready, moved, deferred };
170 }
171
172 namespace detail
173 {
174 struct relocker
175 {
176 boost::unique_lock<boost::mutex>& lock_;
177 bool unlocked_;
178
179 relocker(boost::unique_lock<boost::mutex>& lk):
180 lock_(lk)
181 {
182 lock_.unlock();
183 unlocked_=true;
184 }
185 ~relocker()
186 {
187 if (unlocked_) {
188 lock_.lock();
189 }
190 }
191 void lock() {
192 if (unlocked_) {
193 lock_.lock();
194 unlocked_=false;
195 }
196 }
197 private:
198 relocker& operator=(relocker const&);
199 };
200
201 struct shared_state_base : enable_shared_from_this<shared_state_base>
202 {
203 typedef std::list<boost::condition_variable_any*> waiter_list;
204 // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
205 typedef shared_ptr<shared_state_base> continuation_ptr_type;
206
207 boost::exception_ptr exception;
208 bool done;
209 bool is_deferred_;
210 launch policy_;
211 bool is_constructed;
212 mutable boost::mutex mutex;
213 boost::condition_variable waiters;
214 waiter_list external_waiters;
215 boost::function<void()> callback;
216 // This declaration should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
217 bool thread_was_interrupted;
218 // This declaration should be only included conditionally, but is included to maintain the same layout.
219 continuation_ptr_type continuation_ptr;
220
221 // This declaration should be only included conditionally, but is included to maintain the same layout.
222 virtual void launch_continuation(boost::unique_lock<boost::mutex>&)
223 {
224 }
225
226 shared_state_base():
227 done(false),
228 is_deferred_(false),
229 policy_(launch::none),
230 is_constructed(false),
231 thread_was_interrupted(false),
232 continuation_ptr()
233 {}
234 virtual ~shared_state_base()
235 {}
236
237 void set_deferred()
238 {
239 is_deferred_ = true;
240 policy_ = launch::deferred;
241 }
242 void set_async()
243 {
244 is_deferred_ = false;
245 policy_ = launch::async;
246 }
247
248 waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
249 {
250 boost::unique_lock<boost::mutex> lock(mutex);
251 do_callback(lock);
252 return external_waiters.insert(external_waiters.end(),&cv);
253 }
254
255 void remove_external_waiter(waiter_list::iterator it)
256 {
257 boost::lock_guard<boost::mutex> lock(mutex);
258 external_waiters.erase(it);
259 }
260
261 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
262 void do_continuation(boost::unique_lock<boost::mutex>& lock)
263 {
264 if (continuation_ptr) {
265 continuation_ptr->launch_continuation(lock);
266 if (! lock.owns_lock())
267 lock.lock();
268 continuation_ptr.reset();
269 }
270 }
271 #else
272 void do_continuation(boost::unique_lock<boost::mutex>&)
273 {
274 }
275 #endif
276 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
277 void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
278 {
279 continuation_ptr= continuation;
280 if (done) {
281 do_continuation(lock);
282 }
283 }
284 #endif
285 void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
286 {
287 done=true;
288 waiters.notify_all();
289 for(waiter_list::const_iterator it=external_waiters.begin(),
290 end=external_waiters.end();it!=end;++it)
291 {
292 (*it)->notify_all();
293 }
294 do_continuation(lock);
295 }
296 void make_ready()
297 {
298 boost::unique_lock<boost::mutex> lock(mutex);
299 mark_finished_internal(lock);
300 }
301
302 void do_callback(boost::unique_lock<boost::mutex>& lock)
303 {
304 if(callback && !done)
305 {
306 boost::function<void()> local_callback=callback;
307 relocker relock(lock);
308 local_callback();
309 }
310 }
311
312 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true)
313 {
314 do_callback(lk);
315 //if (!done) // fixme why this doesn't work?
316 {
317 if (is_deferred_)
318 {
319 is_deferred_=false;
320 execute(lk);
321 //lk.unlock();
322 }
323 else
324 {
325 while(!done)
326 {
327 waiters.wait(lk);
328 }
329 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
330 if(rethrow && thread_was_interrupted)
331 {
332 throw boost::thread_interrupted();
333 }
334 #endif
335 if(rethrow && exception)
336 {
337 boost::rethrow_exception(exception);
338 }
339 }
340 }
341 }
342
343 virtual void wait(bool rethrow=true)
344 {
345 boost::unique_lock<boost::mutex> lock(mutex);
346 wait_internal(lock, rethrow);
347 }
348
349 #if defined BOOST_THREAD_USES_DATETIME
350 bool timed_wait_until(boost::system_time const& target_time)
351 {
352 boost::unique_lock<boost::mutex> lock(mutex);
353 if (is_deferred_)
354 return false;
355
356 do_callback(lock);
357 while(!done)
358 {
359 bool const success=waiters.timed_wait(lock,target_time);
360 if(!success && !done)
361 {
362 return false;
363 }
364 }
365 return true;
366 }
367 #endif
368 #ifdef BOOST_THREAD_USES_CHRONO
369
370 template <class Clock, class Duration>
371 future_status
372 wait_until(const chrono::time_point<Clock, Duration>& abs_time)
373 {
374 boost::unique_lock<boost::mutex> lock(mutex);
375 if (is_deferred_)
376 return future_status::deferred;
377 do_callback(lock);
378 while(!done)
379 {
380 cv_status const st=waiters.wait_until(lock,abs_time);
381 if(st==cv_status::timeout && !done)
382 {
383 return future_status::timeout;
384 }
385 }
386 return future_status::ready;
387 }
388 #endif
389 void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
390 {
391 exception=e;
392 mark_finished_internal(lock);
393 }
394
395 void mark_exceptional_finish()
396 {
397 boost::unique_lock<boost::mutex> lock(mutex);
398 mark_exceptional_finish_internal(boost::current_exception(), lock);
399 }
400
401 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
402 void mark_interrupted_finish()
403 {
404 boost::unique_lock<boost::mutex> lock(mutex);
405 thread_was_interrupted=true;
406 mark_finished_internal(lock);
407 }
408
409 void set_interrupted_at_thread_exit()
410 {
411 unique_lock<boost::mutex> lk(mutex);
412 thread_was_interrupted=true;
413 if (has_value(lk))
414 {
415 throw_exception(promise_already_satisfied());
416 }
417 detail::make_ready_at_thread_exit(shared_from_this());
418 }
419 #endif
420
421 void set_exception_at_thread_exit(exception_ptr e)
422 {
423 unique_lock<boost::mutex> lk(mutex);
424 if (has_value(lk))
425 {
426 throw_exception(promise_already_satisfied());
427 }
428 exception=e;
429 this->is_constructed = true;
430 detail::make_ready_at_thread_exit(shared_from_this());
431
432 }
433
434 bool has_value() const
435 {
436 boost::lock_guard<boost::mutex> lock(mutex);
437 return done && !(exception
438 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
439 || thread_was_interrupted
440 #endif
441 );
442 }
443
444 bool has_value(unique_lock<boost::mutex>& ) const
445 {
446 return done && !(exception
447 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
448 || thread_was_interrupted
449 #endif
450 );
451 }
452
453 bool has_exception() const
454 {
455 boost::lock_guard<boost::mutex> lock(mutex);
456 return done && (exception
457 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
458 || thread_was_interrupted
459 #endif
460 );
461 }
462
463 bool has_exception(unique_lock<boost::mutex>&) const
464 {
465 return done && (exception
466 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
467 || thread_was_interrupted
468 #endif
469 );
470 }
471
472 bool is_deferred(boost::lock_guard<boost::mutex>&) const {
473 return is_deferred_;
474 }
475
476 launch launch_policy(boost::unique_lock<boost::mutex>&) const
477 {
478 return policy_;
479 }
480
481 future_state::state get_state() const
482 {
483 boost::lock_guard<boost::mutex> guard(mutex);
484 if(!done)
485 {
486 return future_state::waiting;
487 }
488 else
489 {
490 return future_state::ready;
491 }
492 }
493
494 exception_ptr get_exception_ptr()
495 {
496 boost::unique_lock<boost::mutex> lock(mutex);
497 return get_exception_ptr(lock);
498 }
499 exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock)
500 {
501 wait_internal(lock, false);
502 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
503 if(thread_was_interrupted)
504 {
505 return copy_exception(boost::thread_interrupted());
506 }
507 #endif
508 return exception;
509 }
510
511 template<typename F,typename U>
512 void set_wait_callback(F f,U* u)
513 {
514 boost::lock_guard<boost::mutex> lock(mutex);
515 callback=boost::bind(f,boost::ref(*u));
516 }
517
518 virtual void execute(boost::unique_lock<boost::mutex>&) {}
519
520 private:
521 shared_state_base(shared_state_base const&);
522 shared_state_base& operator=(shared_state_base const&);
523 };
524
525 template<typename T>
526 struct future_traits
527 {
528 typedef boost::scoped_ptr<T> storage_type;
529 struct dummy;
530 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
531 typedef T const& source_reference_type;
532 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
533 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
534 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
535 typedef T move_dest_type;
536 #elif defined BOOST_THREAD_USES_MOVE
537 typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,T&>::type source_reference_type;
538 //typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
539 //typedef typename boost::mpl::if_c<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
540 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
541 typedef T move_dest_type;
542 #else
543 typedef T& source_reference_type;
544 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
545 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
546 #endif
547
548
549 typedef const T& shared_future_get_result_type;
550
551 static void init(storage_type& storage,source_reference_type t)
552 {
553 storage.reset(new T(t));
554 }
555
556 static void init(storage_type& storage,rvalue_source_type t)
557 {
558 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
559 storage.reset(new T(boost::forward<T>(t)));
560 #else
561 storage.reset(new T(static_cast<rvalue_source_type>(t)));
562 #endif
563 }
564
565 static void cleanup(storage_type& storage)
566 {
567 storage.reset();
568 }
569 };
570
571 template<typename T>
572 struct future_traits<T&>
573 {
574 typedef T* storage_type;
575 typedef T& source_reference_type;
576 //struct rvalue_source_type
577 //{};
578 typedef T& move_dest_type;
579 typedef T& shared_future_get_result_type;
580
581 static void init(storage_type& storage,T& t)
582 {
583 storage=&t;
584 }
585
586 static void cleanup(storage_type& storage)
587 {
588 storage=0;
589 }
590 };
591
592 template<>
593 struct future_traits<void>
594 {
595 typedef bool storage_type;
596 typedef void move_dest_type;
597 typedef void shared_future_get_result_type;
598
599 static void init(storage_type& storage)
600 {
601 storage=true;
602 }
603
604 static void cleanup(storage_type& storage)
605 {
606 storage=false;
607 }
608
609 };
610
611 // Used to create stand-alone futures
612 template<typename T>
613 struct shared_state:
614 detail::shared_state_base
615 {
616 typedef typename future_traits<T>::storage_type storage_type;
617 typedef typename future_traits<T>::source_reference_type source_reference_type;
618 typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
619 typedef typename future_traits<T>::move_dest_type move_dest_type;
620 typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type;
621
622 storage_type result;
623
624 shared_state():
625 result(0)
626 {}
627
628 ~shared_state()
629 {}
630
631 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
632 {
633 future_traits<T>::init(result,result_);
634 this->mark_finished_internal(lock);
635 }
636
637 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
638 {
639 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
640 future_traits<T>::init(result,boost::forward<T>(result_));
641 #else
642 future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
643 #endif
644 this->mark_finished_internal(lock);
645 }
646
647 void mark_finished_with_result(source_reference_type result_)
648 {
649 boost::unique_lock<boost::mutex> lock(mutex);
650 this->mark_finished_with_result_internal(result_, lock);
651 }
652
653 void mark_finished_with_result(rvalue_source_type result_)
654 {
655 boost::unique_lock<boost::mutex> lock(mutex);
656
657 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
658 mark_finished_with_result_internal(boost::forward<T>(result_), lock);
659 #else
660 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
661 #endif
662 }
663
664 virtual move_dest_type get()
665 {
666 wait();
667 return boost::move(*result);
668 }
669
670 virtual shared_future_get_result_type get_sh()
671 {
672 wait();
673 return *result;
674 }
675
676 //void set_value_at_thread_exit(const T & result_)
677 void set_value_at_thread_exit(source_reference_type result_)
678 {
679 unique_lock<boost::mutex> lk(this->mutex);
680 if (this->has_value(lk))
681 {
682 throw_exception(promise_already_satisfied());
683 }
684 //future_traits<T>::init(result,result_);
685 result.reset(new T(result_));
686
687 this->is_constructed = true;
688 detail::make_ready_at_thread_exit(shared_from_this());
689 }
690 //void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_)
691 void set_value_at_thread_exit(rvalue_source_type result_)
692 {
693 unique_lock<boost::mutex> lk(this->mutex);
694 if (this->has_value(lk))
695 throw_exception(promise_already_satisfied());
696 result.reset(new T(boost::move(result_)));
697 //future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
698 this->is_constructed = true;
699 detail::make_ready_at_thread_exit(shared_from_this());
700 }
701
702
703 private:
704 shared_state(shared_state const&);
705 shared_state& operator=(shared_state const&);
706 };
707
708 template<typename T>
709 struct shared_state<T&>:
710 detail::shared_state_base
711 {
712 typedef typename future_traits<T&>::storage_type storage_type;
713 typedef typename future_traits<T&>::source_reference_type source_reference_type;
714 typedef typename future_traits<T&>::move_dest_type move_dest_type;
715 typedef typename future_traits<T&>::shared_future_get_result_type shared_future_get_result_type;
716
717 T* result;
718
719 shared_state():
720 result(0)
721 {}
722
723 ~shared_state()
724 {
725 }
726
727 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
728 {
729 //future_traits<T>::init(result,result_);
730 result= &result_;
731 mark_finished_internal(lock);
732 }
733
734 void mark_finished_with_result(source_reference_type result_)
735 {
736 boost::unique_lock<boost::mutex> lock(mutex);
737 mark_finished_with_result_internal(result_, lock);
738 }
739
740 virtual T& get()
741 {
742 wait();
743 return *result;
744 }
745
746 virtual T& get_sh()
747 {
748 wait();
749 return *result;
750 }
751
752 void set_value_at_thread_exit(T& result_)
753 {
754 unique_lock<boost::mutex> lk(this->mutex);
755 if (this->has_value(lk))
756 throw_exception(promise_already_satisfied());
757 //future_traits<T>::init(result,result_);
758 result= &result_;
759 this->is_constructed = true;
760 detail::make_ready_at_thread_exit(shared_from_this());
761 }
762
763 private:
764 shared_state(shared_state const&);
765 shared_state& operator=(shared_state const&);
766 };
767
768 template<>
769 struct shared_state<void>:
770 detail::shared_state_base
771 {
772 typedef void shared_future_get_result_type;
773
774 shared_state()
775 {}
776
777 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
778 {
779 mark_finished_internal(lock);
780 }
781
782 void mark_finished_with_result()
783 {
784 boost::unique_lock<boost::mutex> lock(mutex);
785 mark_finished_with_result_internal(lock);
786 }
787
788 virtual void get()
789 {
790 this->wait();
791 }
792
793 virtual void get_sh()
794 {
795 wait();
796 }
797
798 void set_value_at_thread_exit()
799 {
800 unique_lock<boost::mutex> lk(this->mutex);
801 if (this->has_value(lk))
802 {
803 throw_exception(promise_already_satisfied());
804 }
805 this->is_constructed = true;
806 detail::make_ready_at_thread_exit(shared_from_this());
807 }
808 private:
809 shared_state(shared_state const&);
810 shared_state& operator=(shared_state const&);
811 };
812
813 /////////////////////////
814 /// future_async_shared_state_base
815 /////////////////////////
816 template<typename Rp>
817 struct future_async_shared_state_base: shared_state<Rp>
818 {
819 typedef shared_state<Rp> base_type;
820 protected:
821 boost::thread thr_;
822 void join()
823 {
824 if (thr_.joinable()) thr_.join();
825 }
826 public:
827 future_async_shared_state_base()
828 {
829 this->set_async();
830 }
831 explicit future_async_shared_state_base(BOOST_THREAD_RV_REF(boost::thread) th) :
832 thr_(boost::move(th))
833 {
834 this->set_async();
835 }
836
837 ~future_async_shared_state_base()
838 {
839 join();
840 }
841
842 virtual void wait(bool rethrow)
843 {
844 join();
845 this->base_type::wait(rethrow);
846 }
847 };
848
849 /////////////////////////
850 /// future_async_shared_state
851 /////////////////////////
852 template<typename Rp, typename Fp>
853 struct future_async_shared_state: future_async_shared_state_base<Rp>
854 {
855 typedef future_async_shared_state_base<Rp> base_type;
856
857 public:
858 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) :
859 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f)))
860 {
861 }
862
863 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
864 {
865 try
866 {
867 that->mark_finished_with_result(f());
868 }
869 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
870 catch(thread_interrupted& )
871 {
872 that->mark_interrupted_finish();
873 }
874 #endif
875 catch(...)
876 {
877 that->mark_exceptional_finish();
878 }
879 }
880 };
881
882 template<typename Fp>
883 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void>
884 {
885 typedef future_async_shared_state_base<void> base_type;
886
887 public:
888 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) :
889 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f)))
890 {
891 }
892
893 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
894 {
895 try
896 {
897 f();
898 that->mark_finished_with_result();
899 }
900 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
901 catch(thread_interrupted& )
902 {
903 that->mark_interrupted_finish();
904 }
905 #endif
906 catch(...)
907 {
908 that->mark_exceptional_finish();
909 }
910 }
911 };
912
913 template<typename Rp, typename Fp>
914 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&>
915 {
916 typedef future_async_shared_state_base<Rp&> base_type;
917
918 public:
919 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) :
920 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f)))
921 {
922 }
923
924 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
925 {
926 try
927 {
928 that->mark_finished_with_result(f());
929 }
930 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
931 catch(thread_interrupted& )
932 {
933 that->mark_interrupted_finish();
934 }
935 #endif
936 catch(...)
937 {
938 that->mark_exceptional_finish();
939 }
940 }
941 };
942
943 //////////////////////////
944 /// future_deferred_shared_state
945 //////////////////////////
946 template<typename Rp, typename Fp>
947 struct future_deferred_shared_state: shared_state<Rp>
948 {
949 typedef shared_state<Rp> base_type;
950 Fp func_;
951
952 public:
953 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
954 : func_(boost::forward<Fp>(f))
955 {
956 this->set_deferred();
957 }
958
959 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
960 try
961 {
962 Fp local_fuct=boost::move(func_);
963 relocker relock(lck);
964 Rp res = local_fuct();
965 relock.lock();
966 this->mark_finished_with_result_internal(boost::move(res), lck);
967 }
968 catch (...)
969 {
970 this->mark_exceptional_finish_internal(current_exception(), lck);
971 }
972 }
973 };
974 template<typename Rp, typename Fp>
975 struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
976 {
977 typedef shared_state<Rp&> base_type;
978 Fp func_;
979
980 public:
981 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
982 : func_(boost::forward<Fp>(f))
983 {
984 this->set_deferred();
985 }
986
987 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
988 try
989 {
990 this->mark_finished_with_result_internal(func_(), lck);
991 }
992 catch (...)
993 {
994 this->mark_exceptional_finish_internal(current_exception(), lck);
995 }
996 }
997 };
998
999 template<typename Fp>
1000 struct future_deferred_shared_state<void,Fp>: shared_state<void>
1001 {
1002 typedef shared_state<void> base_type;
1003 Fp func_;
1004
1005 public:
1006 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
1007 : func_(boost::forward<Fp>(f))
1008 {
1009 this->set_deferred();
1010 }
1011
1012 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1013 try
1014 {
1015 Fp local_fuct=boost::move(func_);
1016 relocker relock(lck);
1017 local_fuct();
1018 relock.lock();
1019 this->mark_finished_with_result_internal(lck);
1020 }
1021 catch (...)
1022 {
1023 this->mark_exceptional_finish_internal(current_exception(), lck);
1024 }
1025 }
1026 };
1027
1028 // template<typename T, typename Allocator>
1029 // struct shared_state_alloc: public shared_state<T>
1030 // {
1031 // typedef shared_state<T> base;
1032 // Allocator alloc_;
1033 //
1034 // public:
1035 // explicit shared_state_alloc(const Allocator& a)
1036 // : alloc_(a) {}
1037 //
1038 // };
1039 class future_waiter
1040 {
1041 struct registered_waiter;
1042 typedef std::vector<int>::size_type count_type;
1043
1044 struct registered_waiter
1045 {
1046 boost::shared_ptr<detail::shared_state_base> future_;
1047 detail::shared_state_base::waiter_list::iterator wait_iterator;
1048 count_type index;
1049
1050 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future,
1051 detail::shared_state_base::waiter_list::iterator wait_iterator_,
1052 count_type index_):
1053 future_(a_future),wait_iterator(wait_iterator_),index(index_)
1054 {}
1055 };
1056
1057 struct all_futures_lock
1058 {
1059 #ifdef _MANAGED
1060 typedef std::ptrdiff_t count_type_portable;
1061 #else
1062 typedef count_type count_type_portable;
1063 #endif
1064 count_type_portable count;
1065 boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
1066
1067 all_futures_lock(std::vector<registered_waiter>& futures):
1068 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
1069 {
1070 for(count_type_portable i=0;i<count;++i)
1071 {
1072 #if defined __DECCXX || defined __SUNPRO_CC || defined __hpux
1073 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move();
1074 #else
1075 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex);
1076 #endif
1077 }
1078 }
1079
1080 void lock()
1081 {
1082 boost::lock(locks.get(),locks.get()+count);
1083 }
1084
1085 void unlock()
1086 {
1087 for(count_type_portable i=0;i<count;++i)
1088 {
1089 locks[i].unlock();
1090 }
1091 }
1092 };
1093
1094 boost::condition_variable_any cv;
1095 std::vector<registered_waiter> futures;
1096 count_type future_count;
1097
1098 public:
1099 future_waiter():
1100 future_count(0)
1101 {}
1102
1103 template<typename F>
1104 void add(F& f)
1105 {
1106 if(f.future_)
1107 {
1108 futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count));
1109 }
1110 ++future_count;
1111 }
1112
1113 count_type wait()
1114 {
1115 all_futures_lock lk(futures);
1116 for(;;)
1117 {
1118 for(count_type i=0;i<futures.size();++i)
1119 {
1120 if(futures[i].future_->done)
1121 {
1122 return futures[i].index;
1123 }
1124 }
1125 cv.wait(lk);
1126 }
1127 }
1128
1129 ~future_waiter()
1130 {
1131 for(count_type i=0;i<futures.size();++i)
1132 {
1133 futures[i].future_->remove_external_waiter(futures[i].wait_iterator);
1134 }
1135 }
1136
1137 };
1138
1139 }
1140
1141 template <typename R>
1142 class BOOST_THREAD_FUTURE;
1143
1144 template <typename R>
1145 class shared_future;
1146
1147 template<typename T>
1148 struct is_future_type
1149 {
1150 BOOST_STATIC_CONSTANT(bool, value=false);
1151 typedef void type;
1152 };
1153
1154 template<typename T>
1155 struct is_future_type<BOOST_THREAD_FUTURE<T> >
1156 {
1157 BOOST_STATIC_CONSTANT(bool, value=true);
1158 typedef T type;
1159 };
1160
1161 template<typename T>
1162 struct is_future_type<shared_future<T> >
1163 {
1164 BOOST_STATIC_CONSTANT(bool, value=true);
1165 typedef T type;
1166 };
1167
1168 template<typename Iterator>
1169 typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
1170 {
1171 for(Iterator current=begin;current!=end;++current)
1172 {
1173 current->wait();
1174 }
1175 }
1176
1177 template<typename F1,typename F2>
1178 typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
1179 {
1180 f1.wait();
1181 f2.wait();
1182 }
1183
1184 template<typename F1,typename F2,typename F3>
1185 void wait_for_all(F1& f1,F2& f2,F3& f3)
1186 {
1187 f1.wait();
1188 f2.wait();
1189 f3.wait();
1190 }
1191
1192 template<typename F1,typename F2,typename F3,typename F4>
1193 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
1194 {
1195 f1.wait();
1196 f2.wait();
1197 f3.wait();
1198 f4.wait();
1199 }
1200
1201 template<typename F1,typename F2,typename F3,typename F4,typename F5>
1202 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
1203 {
1204 f1.wait();
1205 f2.wait();
1206 f3.wait();
1207 f4.wait();
1208 f5.wait();
1209 }
1210
1211 template<typename Iterator>
1212 typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
1213 {
1214 if(begin==end)
1215 return end;
1216
1217 detail::future_waiter waiter;
1218 for(Iterator current=begin;current!=end;++current)
1219 {
1220 waiter.add(*current);
1221 }
1222 return boost::next(begin,waiter.wait());
1223 }
1224
1225 template<typename F1,typename F2>
1226 typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2)
1227 {
1228 detail::future_waiter waiter;
1229 waiter.add(f1);
1230 waiter.add(f2);
1231 return waiter.wait();
1232 }
1233
1234 template<typename F1,typename F2,typename F3>
1235 unsigned wait_for_any(F1& f1,F2& f2,F3& f3)
1236 {
1237 detail::future_waiter waiter;
1238 waiter.add(f1);
1239 waiter.add(f2);
1240 waiter.add(f3);
1241 return waiter.wait();
1242 }
1243
1244 template<typename F1,typename F2,typename F3,typename F4>
1245 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
1246 {
1247 detail::future_waiter waiter;
1248 waiter.add(f1);
1249 waiter.add(f2);
1250 waiter.add(f3);
1251 waiter.add(f4);
1252 return waiter.wait();
1253 }
1254
1255 template<typename F1,typename F2,typename F3,typename F4,typename F5>
1256 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
1257 {
1258 detail::future_waiter waiter;
1259 waiter.add(f1);
1260 waiter.add(f2);
1261 waiter.add(f3);
1262 waiter.add(f4);
1263 waiter.add(f5);
1264 return waiter.wait();
1265 }
1266
1267 template <typename R>
1268 class promise;
1269
1270 template <typename R>
1271 class packaged_task;
1272
1273 namespace detail
1274 {
1275 /// Common implementation for all the futures independently of the return type
1276 class base_future
1277 {
1278 //BOOST_THREAD_MOVABLE(base_future)
1279
1280 };
1281 /// Common implementation for future and shared_future.
1282 template <typename R>
1283 class basic_future : public base_future
1284 {
1285 protected:
1286 public:
1287
1288 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
1289
1290 future_ptr future_;
1291
1292 basic_future(future_ptr a_future):
1293 future_(a_future)
1294 {
1295 }
1296 // Copy construction from a shared_future
1297 explicit basic_future(const shared_future<R>&) BOOST_NOEXCEPT;
1298
1299 public:
1300 typedef future_state::state state;
1301
1302 BOOST_THREAD_MOVABLE(basic_future)
1303 basic_future(): future_() {}
1304 ~basic_future() {}
1305
1306 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
1307 future_(BOOST_THREAD_RV(other).future_)
1308 {
1309 BOOST_THREAD_RV(other).future_.reset();
1310 }
1311 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
1312 {
1313 future_=BOOST_THREAD_RV(other).future_;
1314 BOOST_THREAD_RV(other).future_.reset();
1315 return *this;
1316 }
1317 void swap(basic_future& that) BOOST_NOEXCEPT
1318 {
1319 future_.swap(that.future_);
1320 }
1321 // functions to check state, and wait for ready
1322 state get_state() const
1323 {
1324 if(!future_)
1325 {
1326 return future_state::uninitialized;
1327 }
1328 return future_->get_state();
1329 }
1330
1331 bool is_ready() const
1332 {
1333 return get_state()==future_state::ready;
1334 }
1335
1336 bool has_exception() const
1337 {
1338 return future_ && future_->has_exception();
1339 }
1340
1341 bool has_value() const
1342 {
1343 return future_ && future_->has_value();
1344 }
1345
1346 launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
1347 {
1348 if ( future_ ) return future_->launch_policy(lk);
1349 else return launch(launch::none);
1350 }
1351
1352 exception_ptr get_exception_ptr()
1353 {
1354 return future_
1355 ? future_->get_exception_ptr()
1356 : exception_ptr();
1357 }
1358
1359 bool valid() const BOOST_NOEXCEPT
1360 {
1361 return future_ != 0;
1362 }
1363
1364
1365 void wait() const
1366 {
1367 if(!future_)
1368 {
1369 boost::throw_exception(future_uninitialized());
1370 }
1371 future_->wait(false);
1372 }
1373
1374 #if defined BOOST_THREAD_USES_DATETIME
1375 template<typename Duration>
1376 bool timed_wait(Duration const& rel_time) const
1377 {
1378 return timed_wait_until(boost::get_system_time()+rel_time);
1379 }
1380
1381 bool timed_wait_until(boost::system_time const& abs_time) const
1382 {
1383 if(!future_)
1384 {
1385 boost::throw_exception(future_uninitialized());
1386 }
1387 return future_->timed_wait_until(abs_time);
1388 }
1389 #endif
1390 #ifdef BOOST_THREAD_USES_CHRONO
1391 template <class Rep, class Period>
1392 future_status
1393 wait_for(const chrono::duration<Rep, Period>& rel_time) const
1394 {
1395 return wait_until(chrono::steady_clock::now() + rel_time);
1396
1397 }
1398 template <class Clock, class Duration>
1399 future_status
1400 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
1401 {
1402 if(!future_)
1403 {
1404 boost::throw_exception(future_uninitialized());
1405 }
1406 return future_->wait_until(abs_time);
1407 }
1408 #endif
1409
1410 };
1411
1412 } // detail
1413 BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
1414
1415 namespace detail
1416 {
1417 #if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
1418 template <class Rp, class Fp>
1419 BOOST_THREAD_FUTURE<Rp>
1420 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1421
1422 template <class Rp, class Fp>
1423 BOOST_THREAD_FUTURE<Rp>
1424 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1425 #endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
1426 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1427 template<typename F, typename Rp, typename Fp>
1428 struct future_deferred_continuation_shared_state;
1429 template<typename F, typename Rp, typename Fp>
1430 struct future_async_continuation_shared_state;
1431
1432 template <class F, class Rp, class Fp>
1433 BOOST_THREAD_FUTURE<Rp>
1434 make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1435
1436 template <class F, class Rp, class Fp>
1437 BOOST_THREAD_FUTURE<Rp>
1438 make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
1439 #endif
1440 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1441 template<typename F, typename Rp>
1442 struct future_unwrap_shared_state;
1443 template <class F, class Rp>
1444 inline BOOST_THREAD_FUTURE<Rp>
1445 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1446 #endif
1447 }
1448
1449 template <typename R>
1450 class BOOST_THREAD_FUTURE : public detail::basic_future<R>
1451 {
1452 private:
1453 typedef detail::basic_future<R> base_type;
1454 typedef typename base_type::future_ptr future_ptr;
1455
1456 friend class shared_future<R>;
1457 friend class promise<R>;
1458 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1459 template <typename, typename, typename>
1460 friend struct detail::future_async_continuation_shared_state;
1461 template <typename, typename, typename>
1462 friend struct detail::future_deferred_continuation_shared_state;
1463
1464 template <class F, class Rp, class Fp>
1465 friend BOOST_THREAD_FUTURE<Rp>
1466 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);
1467
1468 template <class F, class Rp, class Fp>
1469 friend BOOST_THREAD_FUTURE<Rp>
1470 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);
1471 #endif
1472 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1473 template<typename F, typename Rp>
1474 friend struct detail::future_unwrap_shared_state;
1475 template <class F, class Rp>
1476 friend BOOST_THREAD_FUTURE<Rp>
1477 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1478 #endif
1479 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1480 template <class> friend class packaged_task; // todo check if this works in windows
1481 #else
1482 friend class packaged_task<R>;
1483 #endif
1484 friend class detail::future_waiter;
1485
1486 template <class Rp, class Fp>
1487 friend BOOST_THREAD_FUTURE<Rp>
1488 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1489
1490 template <class Rp, class Fp>
1491 friend BOOST_THREAD_FUTURE<Rp>
1492 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1493
1494
1495 typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
1496
1497 BOOST_THREAD_FUTURE(future_ptr a_future):
1498 base_type(a_future)
1499 {
1500 }
1501
1502 public:
1503 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1504 typedef future_state::state state;
1505 typedef R value_type; // EXTENSION
1506
1507 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
1508
1509 ~BOOST_THREAD_FUTURE() {}
1510
1511 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
1512 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1513 {
1514 }
1515 inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
1516
1517 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1518 {
1519 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1520 return *this;
1521 }
1522
1523 shared_future<R> share()
1524 {
1525 return shared_future<R>(::boost::move(*this));
1526 }
1527
1528 void swap(BOOST_THREAD_FUTURE& other)
1529 {
1530 static_cast<base_type*>(this)->swap(other);
1531 }
1532
1533 // todo this function must be private and friendship provided to the internal users.
1534 void set_async()
1535 {
1536 this->future_->set_async();
1537 }
1538 // todo this function must be private and friendship provided to the internal users.
1539 void set_deferred()
1540 {
1541 this->future_->set_deferred();
1542 }
1543
1544 // retrieving the value
1545 move_dest_type get()
1546 {
1547 if(!this->future_)
1548 {
1549 boost::throw_exception(future_uninitialized());
1550 }
1551 future_ptr fut_=this->future_;
1552 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1553 this->future_.reset();
1554 #endif
1555 return fut_->get();
1556 }
1557
1558 template <typename R2>
1559 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1560 get_or(BOOST_THREAD_RV_REF(R2) v)
1561 {
1562 if(!this->future_)
1563 {
1564 boost::throw_exception(future_uninitialized());
1565 }
1566 this->future_->wait(false);
1567 future_ptr fut_=this->future_;
1568 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1569 this->future_.reset();
1570 #endif
1571 if (fut_->has_value()) {
1572 return fut_->get();
1573 }
1574 else {
1575 return boost::move(v);
1576 }
1577 }
1578
1579 template <typename R2>
1580 typename boost::disable_if< is_void<R2>, move_dest_type>::type
1581 get_or(R2 const& v) // EXTENSION
1582 {
1583 if(!this->future_)
1584 {
1585 boost::throw_exception(future_uninitialized());
1586 }
1587 this->future_->wait(false);
1588 future_ptr fut_=this->future_;
1589 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1590 this->future_.reset();
1591 #endif
1592 if (fut_->has_value()) {
1593 return fut_->get();
1594 }
1595 else {
1596 return v;
1597 }
1598 }
1599
1600
1601 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1602
1603 // template<typename F>
1604 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
1605
1606 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
1607 // template<typename RF>
1608 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
1609 // template<typename RF>
1610 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&));
1611 //#endif
1612 template<typename F>
1613 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1614 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1615 template<typename F>
1616 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1617 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1618
1619 template <typename R2>
1620 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1621 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION
1622 template <typename R2>
1623 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
1624 fallback_to(R2 const& v); // EXTENSION
1625
1626 #endif
1627
1628 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1629 // inline
1630 // typename boost::enable_if<
1631 // is_future_type<value_type>,
1632 // value_type
1633 // //BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type>
1634 // >::type
1635 // unwrap();
1636 //#endif
1637
1638 };
1639
1640 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
1641
1642 template <typename R2>
1643 class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
1644 {
1645 typedef BOOST_THREAD_FUTURE<R2> R;
1646
1647 private:
1648 typedef detail::basic_future<R> base_type;
1649 typedef typename base_type::future_ptr future_ptr;
1650
1651 friend class shared_future<R>;
1652 friend class promise<R>;
1653 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1654 template <typename, typename, typename>
1655 friend struct detail::future_async_continuation_shared_state;
1656 template <typename, typename, typename>
1657 friend struct detail::future_deferred_continuation_shared_state;
1658
1659 template <class F, class Rp, class Fp>
1660 friend BOOST_THREAD_FUTURE<Rp>
1661 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);
1662
1663 template <class F, class Rp, class Fp>
1664 friend BOOST_THREAD_FUTURE<Rp>
1665 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);
1666 #endif
1667 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1668 template<typename F, typename Rp>
1669 friend struct detail::future_unwrap_shared_state;
1670 template <class F, class Rp>
1671 friend BOOST_THREAD_FUTURE<Rp>
1672 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
1673 #endif
1674 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1675 template <class> friend class packaged_task; // todo check if this works in windows
1676 #else
1677 friend class packaged_task<R>;
1678 #endif
1679 friend class detail::future_waiter;
1680
1681 template <class Rp, class Fp>
1682 friend BOOST_THREAD_FUTURE<Rp>
1683 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1684
1685 template <class Rp, class Fp>
1686 friend BOOST_THREAD_FUTURE<Rp>
1687 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
1688
1689
1690 typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
1691
1692 BOOST_THREAD_FUTURE(future_ptr a_future):
1693 base_type(a_future)
1694 {
1695 }
1696
1697 public:
1698 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1699 typedef future_state::state state;
1700 typedef R value_type; // EXTENSION
1701
1702 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
1703
1704 ~BOOST_THREAD_FUTURE() {}
1705
1706 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
1707 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1708 {
1709 }
1710
1711 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1712 {
1713 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1714 return *this;
1715 }
1716
1717 shared_future<R> share()
1718 {
1719 return shared_future<R>(::boost::move(*this));
1720 }
1721
1722 void swap(BOOST_THREAD_FUTURE& other)
1723 {
1724 static_cast<base_type*>(this)->swap(other);
1725 }
1726
1727 // todo this function must be private and friendship provided to the internal users.
1728 void set_async()
1729 {
1730 this->future_->set_async();
1731 }
1732 // todo this function must be private and friendship provided to the internal users.
1733 void set_deferred()
1734 {
1735 this->future_->set_deferred();
1736 }
1737
1738 // retrieving the value
1739 move_dest_type get()
1740 {
1741 if(!this->future_)
1742 {
1743 boost::throw_exception(future_uninitialized());
1744 }
1745 future_ptr fut_=this->future_;
1746 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1747 this->future_.reset();
1748 #endif
1749 return fut_->get();
1750 }
1751 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
1752 {
1753 if(!this->future_)
1754 {
1755 boost::throw_exception(future_uninitialized());
1756 }
1757 this->future_->wait(false);
1758 future_ptr fut_=this->future_;
1759 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1760 this->future_.reset();
1761 #endif
1762 if (fut_->has_value()) return fut_->get();
1763 else return boost::move(v);
1764 }
1765
1766 move_dest_type get_or(R const& v) // EXTENSION
1767 {
1768 if(!this->future_)
1769 {
1770 boost::throw_exception(future_uninitialized());
1771 }
1772 this->future_->wait(false);
1773 future_ptr fut_=this->future_;
1774 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1775 this->future_.reset();
1776 #endif
1777 if (fut_->has_value()) return fut_->get();
1778 else return v;
1779 }
1780
1781
1782 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1783
1784 // template<typename F>
1785 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
1786
1787 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
1788 // template<typename RF>
1789 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
1790 // template<typename RF>
1791 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&));
1792 //#endif
1793 template<typename F>
1794 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1795 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1796 template<typename F>
1797 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
1798 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1799 #endif
1800
1801 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1802 inline
1803 BOOST_THREAD_FUTURE<R2>
1804 unwrap(); // EXTENSION
1805 #endif
1806
1807 };
1808
1809 template <typename R>
1810 class shared_future : public detail::basic_future<R>
1811 {
1812
1813 typedef detail::basic_future<R> base_type;
1814 typedef typename base_type::future_ptr future_ptr;
1815
1816 friend class detail::future_waiter;
1817 friend class promise<R>;
1818
1819 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1820 template <typename, typename, typename>
1821 friend struct detail::future_async_continuation_shared_state;
1822 template <typename, typename, typename>
1823 friend struct detail::future_deferred_continuation_shared_state;
1824
1825 template <class F, class Rp, class Fp>
1826 friend BOOST_THREAD_FUTURE<Rp>
1827 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);
1828
1829 template <class F, class Rp, class Fp>
1830 friend BOOST_THREAD_FUTURE<Rp>
1831 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);
1832 #endif
1833 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1834 template <class> friend class packaged_task;// todo check if this works in windows
1835 #else
1836 friend class packaged_task<R>;
1837 #endif
1838 shared_future(future_ptr a_future):
1839 base_type(a_future)
1840 {}
1841
1842 public:
1843 BOOST_THREAD_MOVABLE(shared_future)
1844 typedef R value_type; // EXTENSION
1845
1846 shared_future(shared_future const& other):
1847 base_type(other)
1848 {}
1849
1850 typedef future_state::state state;
1851
1852 BOOST_CONSTEXPR shared_future()
1853 {}
1854
1855 ~shared_future()
1856 {}
1857
1858 shared_future& operator=(shared_future const& other)
1859 {
1860 shared_future(other).swap(*this);
1861 return *this;
1862 }
1863 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
1864 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1865 {
1866 BOOST_THREAD_RV(other).future_.reset();
1867 }
1868 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
1869 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1870 {
1871 }
1872
1873 shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
1874 {
1875 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1876 return *this;
1877 }
1878 shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
1879 {
1880 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1881 return *this;
1882 }
1883
1884 void swap(shared_future& other) BOOST_NOEXCEPT
1885 {
1886 static_cast<base_type*>(this)->swap(other);
1887 }
1888
1889 // retrieving the value
1890 typename detail::shared_state<R>::shared_future_get_result_type get()
1891 {
1892 if(!this->future_)
1893 {
1894 boost::throw_exception(future_uninitialized());
1895 }
1896
1897 return this->future_->get_sh();
1898 }
1899
1900 template <typename R2>
1901 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
1902 get_or(BOOST_THREAD_RV_REF(R2) v) // EXTENSION
1903 {
1904 if(!this->future_)
1905 {
1906 boost::throw_exception(future_uninitialized());
1907 }
1908 future_ptr fut_=this->future_;
1909 fut_->wait();
1910 if (fut_->has_value()) return fut_->get_sh();
1911 else return boost::move(v);
1912 }
1913
1914 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1915
1916 // template<typename F>
1917 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
1918 // template<typename F>
1919 // auto then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
1920
1921 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
1922 // template<typename RF>
1923 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(shared_future&));
1924 // template<typename RF>
1925 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(shared_future&));
1926 //#endif
1927 template<typename F>
1928 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
1929 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1930 template<typename F>
1931 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
1932 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
1933 #endif
1934 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
1935 // inline
1936 // typename boost::enable_if_c<
1937 // is_future_type<value_type>::value,
1938 // BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type>
1939 // >::type
1940 // unwrap();
1941 //#endif
1942
1943 };
1944
1945 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
1946
1947 namespace detail
1948 {
1949 /// Copy construction from a shared_future
1950 template <typename R>
1951 inline basic_future<R>::basic_future(const shared_future<R>& other) BOOST_NOEXCEPT
1952 : future_(other.future_)
1953 {
1954 }
1955 }
1956
1957 template <typename R>
1958 class promise
1959 {
1960 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
1961
1962 future_ptr future_;
1963 bool future_obtained;
1964
1965 void lazy_init()
1966 {
1967 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
1968 #include <boost/detail/atomic_undef_macros.hpp>
1969 if(!atomic_load(&future_))
1970 {
1971 future_ptr blank;
1972 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
1973 }
1974 #include <boost/detail/atomic_redef_macros.hpp>
1975 #endif
1976 }
1977
1978 public:
1979 BOOST_THREAD_MOVABLE_ONLY(promise)
1980 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
1981 template <class Allocator>
1982 promise(boost::allocator_arg_t, Allocator a)
1983 {
1984 typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2;
1985 A2 a2(a);
1986 typedef thread_detail::allocator_destructor<A2> D;
1987
1988 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) );
1989 future_obtained = false;
1990 }
1991 #endif
1992 promise():
1993 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
1994 future_(),
1995 #else
1996 future_(new detail::shared_state<R>()),
1997 #endif
1998 future_obtained(false)
1999 {}
2000
2001 ~promise()
2002 {
2003 if(future_)
2004 {
2005 boost::unique_lock<boost::mutex> lock(future_->mutex);
2006
2007 if(!future_->done && !future_->is_constructed)
2008 {
2009 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2010 }
2011 }
2012 }
2013
2014 // Assignment
2015 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2016 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2017 {
2018 BOOST_THREAD_RV(rhs).future_.reset();
2019 BOOST_THREAD_RV(rhs).future_obtained=false;
2020 }
2021 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2022 {
2023 future_=BOOST_THREAD_RV(rhs).future_;
2024 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2025 BOOST_THREAD_RV(rhs).future_.reset();
2026 BOOST_THREAD_RV(rhs).future_obtained=false;
2027 return *this;
2028 }
2029
2030 void swap(promise& other)
2031 {
2032 future_.swap(other.future_);
2033 std::swap(future_obtained,other.future_obtained);
2034 }
2035
2036 // Result retrieval
2037 BOOST_THREAD_FUTURE<R> get_future()
2038 {
2039 lazy_init();
2040 if (future_.get()==0)
2041 {
2042 boost::throw_exception(promise_moved());
2043 }
2044 if (future_obtained)
2045 {
2046 boost::throw_exception(future_already_retrieved());
2047 }
2048 future_obtained=true;
2049 return BOOST_THREAD_FUTURE<R>(future_);
2050 }
2051
2052 void set_value(typename detail::future_traits<R>::source_reference_type r)
2053 {
2054 lazy_init();
2055 boost::unique_lock<boost::mutex> lock(future_->mutex);
2056 if(future_->done)
2057 {
2058 boost::throw_exception(promise_already_satisfied());
2059 }
2060 future_->mark_finished_with_result_internal(r, lock);
2061 }
2062
2063 // void set_value(R && r);
2064 void set_value(typename detail::future_traits<R>::rvalue_source_type r)
2065 {
2066 lazy_init();
2067 boost::unique_lock<boost::mutex> lock(future_->mutex);
2068 if(future_->done)
2069 {
2070 boost::throw_exception(promise_already_satisfied());
2071 }
2072 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2073 future_->mark_finished_with_result_internal(boost::forward<R>(r), lock);
2074 #else
2075 future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r), lock);
2076 #endif
2077 }
2078
2079 void set_exception(boost::exception_ptr p)
2080 {
2081 lazy_init();
2082 boost::unique_lock<boost::mutex> lock(future_->mutex);
2083 if(future_->done)
2084 {
2085 boost::throw_exception(promise_already_satisfied());
2086 }
2087 future_->mark_exceptional_finish_internal(p, lock);
2088 }
2089 template <typename E>
2090 void set_exception(E ex)
2091 {
2092 set_exception(copy_exception(ex));
2093 }
2094 // setting the result with deferred notification
2095 void set_value_at_thread_exit(const R& r)
2096 {
2097 if (future_.get()==0)
2098 {
2099 boost::throw_exception(promise_moved());
2100 }
2101 future_->set_value_at_thread_exit(r);
2102 }
2103
2104 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
2105 {
2106 if (future_.get()==0)
2107 {
2108 boost::throw_exception(promise_moved());
2109 }
2110 future_->set_value_at_thread_exit(boost::move(r));
2111 }
2112 void set_exception_at_thread_exit(exception_ptr e)
2113 {
2114 if (future_.get()==0)
2115 {
2116 boost::throw_exception(promise_moved());
2117 }
2118 future_->set_exception_at_thread_exit(e);
2119 }
2120 template <typename E>
2121 void set_exception_at_thread_exit(E ex)
2122 {
2123 set_exception_at_thread_exit(copy_exception(ex));
2124 }
2125
2126 template<typename F>
2127 void set_wait_callback(F f)
2128 {
2129 lazy_init();
2130 future_->set_wait_callback(f,this);
2131 }
2132
2133 };
2134
2135 template <typename R>
2136 class promise<R&>
2137 {
2138 typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr;
2139
2140 future_ptr future_;
2141 bool future_obtained;
2142
2143 void lazy_init()
2144 {
2145 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2146 #include <boost/detail/atomic_undef_macros.hpp>
2147 if(!atomic_load(&future_))
2148 {
2149 future_ptr blank;
2150 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
2151 }
2152 #include <boost/detail/atomic_redef_macros.hpp>
2153 #endif
2154 }
2155
2156 public:
2157 BOOST_THREAD_MOVABLE_ONLY(promise)
2158 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2159 template <class Allocator>
2160 promise(boost::allocator_arg_t, Allocator a)
2161 {
2162 typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2;
2163 A2 a2(a);
2164 typedef thread_detail::allocator_destructor<A2> D;
2165
2166 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
2167 future_obtained = false;
2168 }
2169 #endif
2170 promise():
2171 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2172 future_(),
2173 #else
2174 future_(new detail::shared_state<R&>()),
2175 #endif
2176 future_obtained(false)
2177 {}
2178
2179 ~promise()
2180 {
2181 if(future_)
2182 {
2183 boost::unique_lock<boost::mutex> lock(future_->mutex);
2184
2185 if(!future_->done && !future_->is_constructed)
2186 {
2187 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2188 }
2189 }
2190 }
2191
2192 // Assignment
2193 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2194 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2195 {
2196 BOOST_THREAD_RV(rhs).future_.reset();
2197 BOOST_THREAD_RV(rhs).future_obtained=false;
2198 }
2199 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2200 {
2201 future_=BOOST_THREAD_RV(rhs).future_;
2202 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2203 BOOST_THREAD_RV(rhs).future_.reset();
2204 BOOST_THREAD_RV(rhs).future_obtained=false;
2205 return *this;
2206 }
2207
2208 void swap(promise& other)
2209 {
2210 future_.swap(other.future_);
2211 std::swap(future_obtained,other.future_obtained);
2212 }
2213
2214 // Result retrieval
2215 BOOST_THREAD_FUTURE<R&> get_future()
2216 {
2217 lazy_init();
2218 if (future_.get()==0)
2219 {
2220 boost::throw_exception(promise_moved());
2221 }
2222 if (future_obtained)
2223 {
2224 boost::throw_exception(future_already_retrieved());
2225 }
2226 future_obtained=true;
2227 return BOOST_THREAD_FUTURE<R&>(future_);
2228 }
2229
2230 void set_value(R& r)
2231 {
2232 lazy_init();
2233 boost::unique_lock<boost::mutex> lock(future_->mutex);
2234 if(future_->done)
2235 {
2236 boost::throw_exception(promise_already_satisfied());
2237 }
2238 future_->mark_finished_with_result_internal(r, lock);
2239 }
2240
2241 void set_exception(boost::exception_ptr p)
2242 {
2243 lazy_init();
2244 boost::unique_lock<boost::mutex> lock(future_->mutex);
2245 if(future_->done)
2246 {
2247 boost::throw_exception(promise_already_satisfied());
2248 }
2249 future_->mark_exceptional_finish_internal(p, lock);
2250 }
2251 template <typename E>
2252 void set_exception(E ex)
2253 {
2254 set_exception(copy_exception(ex));
2255 }
2256
2257 // setting the result with deferred notification
2258 void set_value_at_thread_exit(R& r)
2259 {
2260 if (future_.get()==0)
2261 {
2262 boost::throw_exception(promise_moved());
2263 }
2264 future_->set_value_at_thread_exit(r);
2265 }
2266
2267 void set_exception_at_thread_exit(exception_ptr e)
2268 {
2269 if (future_.get()==0)
2270 {
2271 boost::throw_exception(promise_moved());
2272 }
2273 future_->set_exception_at_thread_exit(e);
2274 }
2275 template <typename E>
2276 void set_exception_at_thread_exit(E ex)
2277 {
2278 set_exception_at_thread_exit(copy_exception(ex));
2279 }
2280
2281 template<typename F>
2282 void set_wait_callback(F f)
2283 {
2284 lazy_init();
2285 future_->set_wait_callback(f,this);
2286 }
2287
2288 };
2289 template <>
2290 class promise<void>
2291 {
2292 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr;
2293
2294 future_ptr future_;
2295 bool future_obtained;
2296
2297 void lazy_init()
2298 {
2299 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2300 if(!atomic_load(&future_))
2301 {
2302 future_ptr blank;
2303 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>));
2304 }
2305 #endif
2306 }
2307 public:
2308 BOOST_THREAD_MOVABLE_ONLY(promise)
2309
2310 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2311 template <class Allocator>
2312 promise(boost::allocator_arg_t, Allocator a)
2313 {
2314 typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2;
2315 A2 a2(a);
2316 typedef thread_detail::allocator_destructor<A2> D;
2317
2318 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
2319 future_obtained = false;
2320 }
2321 #endif
2322 promise():
2323 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
2324 future_(),
2325 #else
2326 future_(new detail::shared_state<void>),
2327 #endif
2328 future_obtained(false)
2329 {}
2330
2331 ~promise()
2332 {
2333 if(future_)
2334 {
2335 boost::unique_lock<boost::mutex> lock(future_->mutex);
2336
2337 if(!future_->done && !future_->is_constructed)
2338 {
2339 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
2340 }
2341 }
2342 }
2343
2344 // Assignment
2345 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
2346 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
2347 {
2348 // we need to release the future as shared_ptr doesn't implements move semantics
2349 BOOST_THREAD_RV(rhs).future_.reset();
2350 BOOST_THREAD_RV(rhs).future_obtained=false;
2351 }
2352
2353 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
2354 {
2355 future_=BOOST_THREAD_RV(rhs).future_;
2356 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
2357 BOOST_THREAD_RV(rhs).future_.reset();
2358 BOOST_THREAD_RV(rhs).future_obtained=false;
2359 return *this;
2360 }
2361
2362 void swap(promise& other)
2363 {
2364 future_.swap(other.future_);
2365 std::swap(future_obtained,other.future_obtained);
2366 }
2367
2368 // Result retrieval
2369 BOOST_THREAD_FUTURE<void> get_future()
2370 {
2371 lazy_init();
2372
2373 if (future_.get()==0)
2374 {
2375 boost::throw_exception(promise_moved());
2376 }
2377 if(future_obtained)
2378 {
2379 boost::throw_exception(future_already_retrieved());
2380 }
2381 future_obtained=true;
2382 return BOOST_THREAD_FUTURE<void>(future_);
2383 }
2384
2385 void set_value()
2386 {
2387 lazy_init();
2388 boost::unique_lock<boost::mutex> lock(future_->mutex);
2389 if(future_->done)
2390 {
2391 boost::throw_exception(promise_already_satisfied());
2392 }
2393 future_->mark_finished_with_result_internal(lock);
2394 }
2395
2396 void set_exception(boost::exception_ptr p)
2397 {
2398 lazy_init();
2399 boost::unique_lock<boost::mutex> lock(future_->mutex);
2400 if(future_->done)
2401 {
2402 boost::throw_exception(promise_already_satisfied());
2403 }
2404 future_->mark_exceptional_finish_internal(p,lock);
2405 }
2406 template <typename E>
2407 void set_exception(E ex)
2408 {
2409 set_exception(copy_exception(ex));
2410 }
2411
2412 // setting the result with deferred notification
2413 void set_value_at_thread_exit()
2414 {
2415 if (future_.get()==0)
2416 {
2417 boost::throw_exception(promise_moved());
2418 }
2419 future_->set_value_at_thread_exit();
2420 }
2421
2422 void set_exception_at_thread_exit(exception_ptr e)
2423 {
2424 if (future_.get()==0)
2425 {
2426 boost::throw_exception(promise_moved());
2427 }
2428 future_->set_exception_at_thread_exit(e);
2429 }
2430 template <typename E>
2431 void set_exception_at_thread_exit(E ex)
2432 {
2433 set_exception_at_thread_exit(copy_exception(ex));
2434 }
2435
2436 template<typename F>
2437 void set_wait_callback(F f)
2438 {
2439 lazy_init();
2440 future_->set_wait_callback(f,this);
2441 }
2442
2443 };
2444
2445 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2446 namespace container
2447 {
2448 template <class R, class Alloc>
2449 struct uses_allocator<promise<R> , Alloc> : true_type
2450 {
2451 };
2452 }
2453 #endif
2454
2455 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
2456
2457 namespace detail
2458 {
2459 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2460 template<typename R>
2461 struct task_base_shared_state;
2462 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2463 template<typename R, typename ...ArgTypes>
2464 struct task_base_shared_state<R(ArgTypes...)>:
2465 #else
2466 template<typename R>
2467 struct task_base_shared_state<R()>:
2468 #endif
2469 #else
2470 template<typename R>
2471 struct task_base_shared_state:
2472 #endif
2473 detail::shared_state<R>
2474 {
2475 bool started;
2476
2477 task_base_shared_state():
2478 started(false)
2479 {}
2480
2481 void reset()
2482 {
2483 started=false;
2484 }
2485 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2486 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2487 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2488 #else
2489 virtual void do_run()=0;
2490 void run()
2491 #endif
2492 {
2493 {
2494 boost::lock_guard<boost::mutex> lk(this->mutex);
2495 if(started)
2496 {
2497 boost::throw_exception(task_already_started());
2498 }
2499 started=true;
2500 }
2501 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2502 do_run(boost::forward<ArgTypes>(args)...);
2503 #else
2504 do_run();
2505 #endif
2506 }
2507
2508 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2509 virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2510 void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2511 #else
2512 virtual void do_apply()=0;
2513 void apply()
2514 #endif
2515 {
2516 {
2517 boost::lock_guard<boost::mutex> lk(this->mutex);
2518 if(started)
2519 {
2520 boost::throw_exception(task_already_started());
2521 }
2522 started=true;
2523 }
2524 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2525 do_apply(boost::forward<ArgTypes>(args)...);
2526 #else
2527 do_apply();
2528 #endif
2529 }
2530
2531 void owner_destroyed()
2532 {
2533 boost::unique_lock<boost::mutex> lk(this->mutex);
2534 if(!started)
2535 {
2536 started=true;
2537 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
2538 }
2539 }
2540
2541 };
2542
2543 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2544 template<typename F, typename R>
2545 struct task_shared_state;
2546 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2547 template<typename F, typename R, typename ...ArgTypes>
2548 struct task_shared_state<F, R(ArgTypes...)>:
2549 task_base_shared_state<R(ArgTypes...)>
2550 #else
2551 template<typename F, typename R>
2552 struct task_shared_state<F, R()>:
2553 task_base_shared_state<R()>
2554 #endif
2555 #else
2556 template<typename F, typename R>
2557 struct task_shared_state:
2558 task_base_shared_state<R>
2559 #endif
2560 {
2561 private:
2562 task_shared_state(task_shared_state&);
2563 public:
2564 F f;
2565 task_shared_state(F const& f_):
2566 f(f_)
2567 {}
2568 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
2569 f(boost::move(f_))
2570 {}
2571
2572 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2573 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2574 {
2575 try
2576 {
2577 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
2578 }
2579 #else
2580 void do_apply()
2581 {
2582 try
2583 {
2584 this->set_value_at_thread_exit(f());
2585 }
2586 #endif
2587 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2588 catch(thread_interrupted& )
2589 {
2590 this->set_interrupted_at_thread_exit();
2591 }
2592 #endif
2593 catch(...)
2594 {
2595 this->set_exception_at_thread_exit(current_exception());
2596 }
2597 }
2598
2599 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2600 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2601 {
2602 try
2603 {
2604 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
2605 }
2606 #else
2607 void do_run()
2608 {
2609 try
2610 {
2611 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2612 R res((f()));
2613 this->mark_finished_with_result(boost::move(res));
2614 #else
2615 this->mark_finished_with_result(f());
2616 #endif
2617 }
2618 #endif
2619 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2620 catch(thread_interrupted& )
2621 {
2622 this->mark_interrupted_finish();
2623 }
2624 #endif
2625 catch(...)
2626 {
2627 this->mark_exceptional_finish();
2628 }
2629 }
2630 };
2631
2632 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2633 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2634 template<typename F, typename R, typename ...ArgTypes>
2635 struct task_shared_state<F, R&(ArgTypes...)>:
2636 task_base_shared_state<R&(ArgTypes...)>
2637 #else
2638 template<typename F, typename R>
2639 struct task_shared_state<F, R&()>:
2640 task_base_shared_state<R&()>
2641 #endif
2642 #else
2643 template<typename F, typename R>
2644 struct task_shared_state<F,R&>:
2645 task_base_shared_state<R&>
2646 #endif
2647 {
2648 private:
2649 task_shared_state(task_shared_state&);
2650 public:
2651 F f;
2652 task_shared_state(F const& f_):
2653 f(f_)
2654 {}
2655 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
2656 f(boost::move(f_))
2657 {}
2658
2659 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2660 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2661 {
2662 try
2663 {
2664 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
2665 }
2666 #else
2667 void do_apply()
2668 {
2669 try
2670 {
2671 this->set_value_at_thread_exit(f());
2672 }
2673 #endif
2674 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2675 catch(thread_interrupted& )
2676 {
2677 this->set_interrupted_at_thread_exit();
2678 }
2679 #endif
2680 catch(...)
2681 {
2682 this->set_exception_at_thread_exit(current_exception());
2683 }
2684 }
2685
2686 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2687 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2688 {
2689 try
2690 {
2691 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
2692 }
2693 #else
2694 void do_run()
2695 {
2696 try
2697 {
2698 R& res((f()));
2699 this->mark_finished_with_result(res);
2700 }
2701 #endif
2702 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2703 catch(thread_interrupted& )
2704 {
2705 this->mark_interrupted_finish();
2706 }
2707 #endif
2708 catch(...)
2709 {
2710 this->mark_exceptional_finish();
2711 }
2712 }
2713 };
2714
2715 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
2716
2717 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2718 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2719 template<typename R, typename ...ArgTypes>
2720 struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>:
2721 task_base_shared_state<R(ArgTypes...)>
2722 #else
2723 template<typename R>
2724 struct task_shared_state<R (*)(), R()>:
2725 task_base_shared_state<R()>
2726 #endif
2727 #else
2728 template<typename R>
2729 struct task_shared_state<R (*)(), R> :
2730 task_base_shared_state<R>
2731 #endif
2732 {
2733 private:
2734 task_shared_state(task_shared_state&);
2735 public:
2736 R (*f)();
2737 task_shared_state(R (*f_)()):
2738 f(f_)
2739 {}
2740
2741
2742 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2743 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2744 {
2745 try
2746 {
2747 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
2748 }
2749 #else
2750 void do_apply()
2751 {
2752 try
2753 {
2754 R r((f()));
2755 this->set_value_at_thread_exit(boost::move(r));
2756 }
2757 #endif
2758 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2759 catch(thread_interrupted& )
2760 {
2761 this->set_interrupted_at_thread_exit();
2762 }
2763 #endif
2764 catch(...)
2765 {
2766 this->set_exception_at_thread_exit(current_exception());
2767 }
2768 }
2769
2770
2771 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2772 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2773 {
2774 try
2775 {
2776 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
2777 }
2778 #else
2779 void do_run()
2780 {
2781 try
2782 {
2783 R res((f()));
2784 this->mark_finished_with_result(boost::move(res));
2785 }
2786 #endif
2787 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2788 catch(thread_interrupted& )
2789 {
2790 this->mark_interrupted_finish();
2791 }
2792 #endif
2793 catch(...)
2794 {
2795 this->mark_exceptional_finish();
2796 }
2797 }
2798 };
2799 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2800 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2801 template<typename R, typename ...ArgTypes>
2802 struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>:
2803 task_base_shared_state<R&(ArgTypes...)>
2804 #else
2805 template<typename R>
2806 struct task_shared_state<R& (*)(), R&()>:
2807 task_base_shared_state<R&()>
2808 #endif
2809 #else
2810 template<typename R>
2811 struct task_shared_state<R& (*)(), R&> :
2812 task_base_shared_state<R&>
2813 #endif
2814 {
2815 private:
2816 task_shared_state(task_shared_state&);
2817 public:
2818 R& (*f)();
2819 task_shared_state(R& (*f_)()):
2820 f(f_)
2821 {}
2822
2823
2824 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2825 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2826 {
2827 try
2828 {
2829 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
2830 }
2831 #else
2832 void do_apply()
2833 {
2834 try
2835 {
2836 this->set_value_at_thread_exit(f());
2837 }
2838 #endif
2839 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2840 catch(thread_interrupted& )
2841 {
2842 this->set_interrupted_at_thread_exit();
2843 }
2844 #endif
2845 catch(...)
2846 {
2847 this->set_exception_at_thread_exit(current_exception());
2848 }
2849 }
2850
2851
2852 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2853 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2854 {
2855 try
2856 {
2857 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
2858 }
2859 #else
2860 void do_run()
2861 {
2862 try
2863 {
2864 this->mark_finished_with_result(f());
2865 }
2866 #endif
2867 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2868 catch(thread_interrupted& )
2869 {
2870 this->mark_interrupted_finish();
2871 }
2872 #endif
2873 catch(...)
2874 {
2875 this->mark_exceptional_finish();
2876 }
2877 }
2878 };
2879 #endif
2880 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2881 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2882 template<typename F, typename ...ArgTypes>
2883 struct task_shared_state<F, void(ArgTypes...)>:
2884 task_base_shared_state<void(ArgTypes...)>
2885 #else
2886 template<typename F>
2887 struct task_shared_state<F, void()>:
2888 task_base_shared_state<void()>
2889 #endif
2890 #else
2891 template<typename F>
2892 struct task_shared_state<F,void>:
2893 task_base_shared_state<void>
2894 #endif
2895 {
2896 private:
2897 task_shared_state(task_shared_state&);
2898 public:
2899 F f;
2900 task_shared_state(F const& f_):
2901 f(f_)
2902 {}
2903 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
2904 f(boost::move(f_))
2905 {}
2906
2907 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2908 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2909 {
2910 try
2911 {
2912 f(boost::forward<ArgTypes>(args)...);
2913 #else
2914 void do_apply()
2915 {
2916 try
2917 {
2918 f();
2919 #endif
2920 this->set_value_at_thread_exit();
2921 }
2922 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2923 catch(thread_interrupted& )
2924 {
2925 this->set_interrupted_at_thread_exit();
2926 }
2927 #endif
2928 catch(...)
2929 {
2930 this->set_exception_at_thread_exit(current_exception());
2931 }
2932 }
2933
2934 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2935 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2936 {
2937 try
2938 {
2939 f(boost::forward<ArgTypes>(args)...);
2940 #else
2941 void do_run()
2942 {
2943 try
2944 {
2945 f();
2946 #endif
2947 this->mark_finished_with_result();
2948 }
2949 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2950 catch(thread_interrupted& )
2951 {
2952 this->mark_interrupted_finish();
2953 }
2954 #endif
2955 catch(...)
2956 {
2957 this->mark_exceptional_finish();
2958 }
2959 }
2960 };
2961
2962 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2963 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2964 template<typename ...ArgTypes>
2965 struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>:
2966 task_base_shared_state<void(ArgTypes...)>
2967 #else
2968 template<>
2969 struct task_shared_state<void (*)(), void()>:
2970 task_base_shared_state<void()>
2971 #endif
2972 #else
2973 template<>
2974 struct task_shared_state<void (*)(),void>:
2975 task_base_shared_state<void>
2976 #endif
2977 {
2978 private:
2979 task_shared_state(task_shared_state&);
2980 public:
2981 void (*f)();
2982 task_shared_state(void (*f_)()):
2983 f(f_)
2984 {}
2985
2986 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2987 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2988 {
2989 try
2990 {
2991 f(boost::forward<ArgTypes>(args)...);
2992 #else
2993 void do_apply()
2994 {
2995 try
2996 {
2997 f();
2998 #endif
2999 this->set_value_at_thread_exit();
3000 }
3001 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
3002 catch(thread_interrupted& )
3003 {
3004 this->set_interrupted_at_thread_exit();
3005 }
3006 #endif
3007 catch(...)
3008 {
3009 this->set_exception_at_thread_exit(current_exception());
3010 }
3011 }
3012
3013 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3014 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
3015 {
3016 try
3017 {
3018 f(boost::forward<ArgTypes>(args)...);
3019 #else
3020 void do_run()
3021 {
3022 try
3023 {
3024 f();
3025 #endif
3026 this->mark_finished_with_result();
3027 }
3028 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
3029 catch(thread_interrupted& )
3030 {
3031 this->mark_interrupted_finish();
3032 }
3033 #endif
3034 catch(...)
3035 {
3036 this->mark_exceptional_finish();
3037 }
3038 }
3039 };
3040 }
3041
3042 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3043 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3044 template<typename R, typename ...ArgTypes>
3045 class packaged_task<R(ArgTypes...)>
3046 {
3047 typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr;
3048 boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task;
3049 #else
3050 template<typename R>
3051 class packaged_task<R()>
3052 {
3053 typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr;
3054 boost::shared_ptr<detail::task_base_shared_state<R()> > task;
3055 #endif
3056 #else
3057 template<typename R>
3058 class packaged_task
3059 {
3060 typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr;
3061 boost::shared_ptr<detail::task_base_shared_state<R> > task;
3062 #endif
3063 bool future_obtained;
3064 struct dummy;
3065
3066 public:
3067 typedef R result_type;
3068 BOOST_THREAD_MOVABLE_ONLY(packaged_task)
3069
3070 packaged_task():
3071 future_obtained(false)
3072 {}
3073
3074 // construction and destruction
3075 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3076
3077 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3078 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3079 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
3080 {
3081 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3082 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3083 task= task_ptr(new task_shared_state_type(f, boost::forward<ArgTypes>(args)...));
3084 future_obtained=false;
3085 }
3086 #else
3087 explicit packaged_task(R(*f)())
3088 {
3089 typedef R(*FR)();
3090 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3091 task= task_ptr(new task_shared_state_type(f));
3092 future_obtained=false;
3093 }
3094 #endif
3095 #else
3096 explicit packaged_task(R(*f)())
3097 {
3098 typedef R(*FR)();
3099 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3100 task= task_ptr(new task_shared_state_type(f));
3101 future_obtained=false;
3102 }
3103 #endif
3104 #endif
3105 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
3106 template <class F>
3107 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
3108 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3109 )
3110 {
3111 typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
3112 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3113 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3114 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3115 #else
3116 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3117 #endif
3118 #else
3119 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3120 #endif
3121 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
3122 future_obtained = false;
3123
3124 }
3125
3126 #else
3127 template <class F>
3128 explicit packaged_task(F const& f
3129 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
3130 )
3131 {
3132 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3133 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3134 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3135 #else
3136 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3137 #endif
3138 #else
3139 typedef detail::task_shared_state<F,R> task_shared_state_type;
3140 #endif
3141 task = task_ptr(new task_shared_state_type(f));
3142 future_obtained=false;
3143 }
3144 template <class F>
3145 explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
3146 {
3147 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3148 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3149 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3150 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
3151 #else
3152 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3153 task = task_ptr(new task_shared_state_type(boost::move(f))); // TODO forward
3154 #endif
3155 #else
3156 typedef detail::task_shared_state<F,R> task_shared_state_type;
3157 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
3158 #endif
3159 future_obtained=false;
3160
3161 }
3162 #endif
3163
3164 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3165 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3166 template <class Allocator>
3167 packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
3168 {
3169 typedef R(*FR)();
3170 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3171 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3172 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3173 #else
3174 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3175 #endif
3176 #else
3177 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3178 #endif
3179 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3180 A2 a2(a);
3181 typedef thread_detail::allocator_destructor<A2> D;
3182
3183 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3184 future_obtained = false;
3185 }
3186 #endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3187
3188 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3189 template <class F, class Allocator>
3190 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
3191 {
3192 typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
3193 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3194 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3195 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
3196 #else
3197 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
3198 #endif
3199 #else
3200 typedef detail::task_shared_state<FR,R> task_shared_state_type;
3201 #endif
3202 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3203 A2 a2(a);
3204 typedef thread_detail::allocator_destructor<A2> D;
3205
3206 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
3207 future_obtained = false;
3208 }
3209 #else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3210 template <class F, class Allocator>
3211 packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
3212 {
3213 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3214 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3215 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3216 #else
3217 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3218 #endif
3219 #else
3220 typedef detail::task_shared_state<F,R> task_shared_state_type;
3221 #endif
3222 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3223 A2 a2(a);
3224 typedef thread_detail::allocator_destructor<A2> D;
3225
3226 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
3227 future_obtained = false;
3228 }
3229 template <class F, class Allocator>
3230 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
3231 {
3232 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3233 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3234 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
3235 #else
3236 typedef detail::task_shared_state<F,R()> task_shared_state_type;
3237 #endif
3238 #else
3239 typedef detail::task_shared_state<F,R> task_shared_state_type;
3240 #endif
3241 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
3242 A2 a2(a);
3243 typedef thread_detail::allocator_destructor<A2> D;
3244
3245 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3246 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
3247 #else
3248 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) ); // TODO forward
3249 #endif
3250 future_obtained = false;
3251 }
3252
3253 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
3254 #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3255
3256 ~packaged_task()
3257 {
3258 if(task)
3259 {
3260 task->owner_destroyed();
3261 }
3262 }
3263
3264 // assignment
3265 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT :
3266 future_obtained(BOOST_THREAD_RV(other).future_obtained)
3267 {
3268 task.swap(BOOST_THREAD_RV(other).task);
3269 BOOST_THREAD_RV(other).future_obtained=false;
3270 }
3271 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
3272 {
3273
3274 // todo use forward
3275 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
3276 packaged_task temp(boost::move(other));
3277 #else
3278 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
3279 #endif
3280 swap(temp);
3281 return *this;
3282 }
3283
3284 void reset()
3285 {
3286 if (!valid())
3287 throw future_error(system::make_error_code(future_errc::no_state));
3288 task->reset();
3289 future_obtained=false;
3290 }
3291
3292 void swap(packaged_task& other) BOOST_NOEXCEPT
3293 {
3294 task.swap(other.task);
3295 std::swap(future_obtained,other.future_obtained);
3296 }
3297 bool valid() const BOOST_NOEXCEPT
3298 {
3299 return task.get()!=0;
3300 }
3301
3302 // result retrieval
3303 BOOST_THREAD_FUTURE<R> get_future()
3304 {
3305 if(!task)
3306 {
3307 boost::throw_exception(task_moved());
3308 }
3309 else if(!future_obtained)
3310 {
3311 future_obtained=true;
3312 return BOOST_THREAD_FUTURE<R>(task);
3313 }
3314 else
3315 {
3316 boost::throw_exception(future_already_retrieved());
3317 }
3318 //return BOOST_THREAD_FUTURE<R>();
3319 }
3320
3321 // execution
3322 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3323 void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args)
3324 {
3325 if(!task)
3326 {
3327 boost::throw_exception(task_moved());
3328 }
3329 task->run(boost::forward<ArgTypes>(args)...);
3330 }
3331 void make_ready_at_thread_exit(ArgTypes... args)
3332 {
3333 if(!task)
3334 {
3335 boost::throw_exception(task_moved());
3336 }
3337 if (task->has_value())
3338 {
3339 boost::throw_exception(promise_already_satisfied());
3340 }
3341 task->apply(boost::forward<ArgTypes>(args)...);
3342 }
3343 #else
3344 void operator()()
3345 {
3346 if(!task)
3347 {
3348 boost::throw_exception(task_moved());
3349 }
3350 task->run();
3351 }
3352 void make_ready_at_thread_exit()
3353 {
3354 if(!task)
3355 {
3356 boost::throw_exception(task_moved());
3357 }
3358 if (task->has_value())
3359 boost::throw_exception(promise_already_satisfied());
3360 task->apply();
3361 }
3362 #endif
3363 template<typename F>
3364 void set_wait_callback(F f)
3365 {
3366 task->set_wait_callback(f,this);
3367 }
3368 };
3369
3370 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
3371 namespace container
3372 {
3373 template <class R, class Alloc>
3374 struct uses_allocator<packaged_task<R>, Alloc>
3375 : public true_type {};
3376 }
3377 #endif
3378
3379 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
3380
3381 namespace detail
3382 {
3383 ////////////////////////////////
3384 // make_future_deferred_shared_state
3385 ////////////////////////////////
3386 template <class Rp, class Fp>
3387 BOOST_THREAD_FUTURE<Rp>
3388 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
3389 {
3390 shared_ptr<future_deferred_shared_state<Rp, Fp> >
3391 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
3392 return BOOST_THREAD_FUTURE<Rp>(h);
3393 }
3394
3395 ////////////////////////////////
3396 // make_future_async_shared_state
3397 ////////////////////////////////
3398 template <class Rp, class Fp>
3399 BOOST_THREAD_FUTURE<Rp>
3400 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
3401 {
3402 shared_ptr<future_async_shared_state<Rp, Fp> >
3403 h(new future_async_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
3404 return BOOST_THREAD_FUTURE<Rp>(h);
3405 }
3406
3407 }
3408
3409 ////////////////////////////////
3410 // template <class F, class... ArgTypes>
3411 // future<R> async(launch policy, F&&, ArgTypes&&...);
3412 ////////////////////////////////
3413
3414 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3415
3416 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3417 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3418 template <class R, class... ArgTypes>
3419 BOOST_THREAD_FUTURE<R>
3420 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
3421 {
3422 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3423 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3424 typedef typename BF::result_type Rp;
3425 #else
3426 template <class R>
3427 BOOST_THREAD_FUTURE<R>
3428 async(launch policy, R(*f)())
3429 {
3430 typedef packaged_task<R()> packaged_task_type;
3431 #endif
3432 #else
3433 template <class R>
3434 BOOST_THREAD_FUTURE<R>
3435 async(launch policy, R(*f)())
3436 {
3437 typedef packaged_task<R> packaged_task_type;
3438 #endif
3439 if (int(policy) & int(launch::async))
3440 {
3441 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3442 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3443 BF(
3444 thread_detail::decay_copy(boost::forward<F>(f))
3445 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3446 )
3447 ));
3448 #else
3449 packaged_task_type pt( f );
3450
3451 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
3452 ret.set_async();
3453 boost::thread( boost::move(pt) ).detach();
3454 return ::boost::move(ret);
3455 #endif
3456 }
3457 else if (int(policy) & int(launch::deferred))
3458 {
3459 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3460 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3461 BF(
3462 thread_detail::decay_copy(boost::forward<F>(f))
3463 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3464 )
3465 ));
3466 #else
3467 std::terminate();
3468 BOOST_THREAD_FUTURE<R> ret;
3469 return ::boost::move(ret);
3470
3471 #endif
3472 } else {
3473 std::terminate();
3474 BOOST_THREAD_FUTURE<R> ret;
3475 return ::boost::move(ret);
3476 }
3477 }
3478
3479 #endif
3480
3481 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3482 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3483
3484 template <class F, class ...ArgTypes>
3485 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3486 typename decay<ArgTypes>::type...
3487 )>::type>
3488 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
3489 {
3490
3491 typedef typename boost::result_of<typename decay<F>::type(
3492 typename decay<ArgTypes>::type...
3493 )>::type R;
3494
3495 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3496 typedef typename BF::result_type Rp;
3497
3498 #else
3499 template <class F>
3500 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3501 async(launch policy, BOOST_THREAD_FWD_REF(F) f)
3502 {
3503 typedef typename boost::result_of<typename decay<F>::type()>::type R;
3504 typedef packaged_task<R()> packaged_task_type;
3505
3506 #endif
3507 #else
3508 template <class F>
3509 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3510 async(launch policy, BOOST_THREAD_FWD_REF(F) f)
3511 {
3512 typedef typename boost::result_of<typename decay<F>::type()>::type R;
3513 typedef packaged_task<R> packaged_task_type;
3514
3515 #endif
3516
3517 if (int(policy) & int(launch::async))
3518 {
3519 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3520 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
3521 BF(
3522 thread_detail::decay_copy(boost::forward<F>(f))
3523 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3524 )
3525 ));
3526 #else
3527 packaged_task_type pt( boost::forward<F>(f) );
3528
3529 BOOST_THREAD_FUTURE<R> ret = pt.get_future();
3530 ret.set_async();
3531 boost::thread( boost::move(pt) ).detach();
3532 return ::boost::move(ret);
3533 #endif
3534 }
3535 else if (int(policy) & int(launch::deferred))
3536 {
3537 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3538 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
3539 BF(
3540 thread_detail::decay_copy(boost::forward<F>(f))
3541 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3542 )
3543 ));
3544 #else
3545 std::terminate();
3546 BOOST_THREAD_FUTURE<R> ret;
3547 return ::boost::move(ret);
3548 // return boost::detail::make_future_deferred_shared_state<Rp>(
3549 // BF(
3550 // thread_detail::decay_copy(boost::forward<F>(f))
3551 // )
3552 // );
3553 #endif
3554
3555 } else {
3556 std::terminate();
3557 BOOST_THREAD_FUTURE<R> ret;
3558 return ::boost::move(ret);
3559 }
3560 }
3561
3562 ////////////////////////////////
3563 // template <class F, class... ArgTypes>
3564 // future<R> async(F&&, ArgTypes&&...);
3565 ////////////////////////////////
3566
3567 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3568
3569 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3570 template <class R, class... ArgTypes>
3571 BOOST_THREAD_FUTURE<R>
3572 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
3573 {
3574 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
3575 }
3576 #else
3577 template <class R>
3578 BOOST_THREAD_FUTURE<R>
3579 async(R(*f)())
3580 {
3581 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
3582 }
3583 #endif
3584 #endif
3585
3586 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3587 template <class F, class ...ArgTypes>
3588 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3589 typename decay<ArgTypes>::type...
3590 )>::type>
3591 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
3592 {
3593 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
3594 }
3595 #else
3596 template <class F>
3597 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
3598 async(BOOST_THREAD_RV_REF(F) f)
3599 {
3600 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
3601 }
3602 #endif
3603
3604
3605 ////////////////////////////////
3606 // make_future deprecated
3607 ////////////////////////////////
3608 template <typename T>
3609 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value)
3610 {
3611 typedef typename decay<T>::type future_value_type;
3612 promise<future_value_type> p;
3613 p.set_value(boost::forward<future_value_type>(value));
3614 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3615 }
3616
3617 #if defined BOOST_THREAD_USES_MOVE
3618 inline BOOST_THREAD_FUTURE<void> make_future()
3619 {
3620 promise<void> p;
3621 p.set_value();
3622 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3623 }
3624 #endif
3625
3626 ////////////////////////////////
3627 // make_ready_future
3628 ////////////////////////////////
3629 template <typename T>
3630 BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value)
3631 {
3632 typedef typename decay<T>::type future_value_type;
3633 promise<future_value_type> p;
3634 p.set_value(boost::forward<future_value_type>(value));
3635 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3636 }
3637
3638 #if defined BOOST_THREAD_USES_MOVE
3639 inline BOOST_THREAD_FUTURE<void> make_ready_future()
3640 {
3641 promise<void> p;
3642 p.set_value();
3643 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3644 }
3645 #endif
3646
3647 template <typename T>
3648 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex)
3649 {
3650 promise<T> p;
3651 p.set_exception(ex);
3652 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3653 }
3654 template <typename T, typename E>
3655 BOOST_THREAD_FUTURE<T> make_ready_future(E ex)
3656 {
3657 promise<T> p;
3658 p.set_exception(boost::copy_exception(ex));
3659 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3660 }
3661
3662 #if 0
3663 template<typename CLOSURE>
3664 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
3665 typedef decltype(closure()) T;
3666 promise<T> p;
3667 try
3668 {
3669 p.set_value(closure());
3670 }
3671 catch(...)
3672 {
3673 p.set_exception(std::current_exception());
3674 }
3675 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3676 }
3677 #endif
3678
3679 ////////////////////////////////
3680 // make_shared_future deprecated
3681 ////////////////////////////////
3682 template <typename T>
3683 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value)
3684 {
3685 typedef typename decay<T>::type future_type;
3686 promise<future_type> p;
3687 p.set_value(boost::forward<T>(value));
3688 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
3689 }
3690
3691
3692 inline shared_future<void> make_shared_future()
3693 {
3694 promise<void> p;
3695 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
3696
3697 }
3698
3699 // ////////////////////////////////
3700 // // make_ready_shared_future
3701 // ////////////////////////////////
3702 // template <typename T>
3703 // shared_future<typename decay<T>::type> make_ready_shared_future(BOOST_THREAD_FWD_REF(T) value)
3704 // {
3705 // typedef typename decay<T>::type future_type;
3706 // promise<future_type> p;
3707 // p.set_value(boost::forward<T>(value));
3708 // return p.get_future().share();
3709 // }
3710 //
3711 //
3712 // inline shared_future<void> make_ready_shared_future()
3713 // {
3714 // promise<void> p;
3715 // return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
3716 //
3717 // }
3718 //
3719 // ////////////////////////////////
3720 // // make_exceptional_shared_future
3721 // ////////////////////////////////
3722 // template <typename T>
3723 // shared_future<T> make_exceptional_shared_future(exception_ptr ex)
3724 // {
3725 // promise<T> p;
3726 // p.set_exception(ex);
3727 // return p.get_future().share();
3728 // }
3729
3730 ////////////////////////////////
3731 // detail::future_async_continuation_shared_state
3732 ////////////////////////////////
3733 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
3734 namespace detail
3735 {
3736
3737 /////////////////////////
3738 /// future_async_continuation_shared_state
3739 /////////////////////////
3740
3741 template<typename F, typename Rp, typename Fp>
3742 struct future_async_continuation_shared_state: future_async_shared_state_base<Rp>
3743 {
3744 F parent;
3745 Fp continuation;
3746
3747 public:
3748 future_async_continuation_shared_state(
3749 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
3750 ) :
3751 parent(boost::move(f)),
3752 continuation(boost::move(c))
3753 {
3754 }
3755
3756 void launch_continuation(boost::unique_lock<boost::mutex>& lock)
3757 {
3758 lock.unlock();
3759 this->thr_ = thread(&future_async_continuation_shared_state::run, this);
3760 }
3761
3762 static void run(future_async_continuation_shared_state* that)
3763 {
3764 try
3765 {
3766 that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
3767 }
3768 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
3769 catch(thread_interrupted& )
3770 {
3771 that->mark_interrupted_finish();
3772 }
3773 #endif
3774 catch(...)
3775 {
3776 that->mark_exceptional_finish();
3777 }
3778 }
3779 ~future_async_continuation_shared_state()
3780 {
3781 this->join();
3782 }
3783 };
3784
3785 template<typename F, typename Fp>
3786 struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void>
3787 {
3788 F parent;
3789 Fp continuation;
3790
3791 public:
3792 future_async_continuation_shared_state(
3793 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
3794 ) :
3795 parent(boost::move(f)),
3796 continuation(boost::move(c))
3797 {
3798 }
3799
3800 void launch_continuation(boost::unique_lock<boost::mutex>& lk)
3801 {
3802 lk.unlock();
3803 this->thr_ = thread(&future_async_continuation_shared_state::run, this);
3804 }
3805
3806 static void run(future_async_continuation_shared_state* that)
3807 {
3808 try
3809 {
3810 that->continuation(boost::move(that->parent));
3811 that->mark_finished_with_result();
3812 }
3813 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
3814 catch(thread_interrupted& )
3815 {
3816 that->mark_interrupted_finish();
3817 }
3818 #endif
3819 catch(...)
3820 {
3821 that->mark_exceptional_finish();
3822 }
3823 }
3824 ~future_async_continuation_shared_state()
3825 {
3826 this->join();
3827 }
3828 };
3829
3830
3831 //////////////////////////
3832 /// future_deferred_continuation_shared_state
3833 //////////////////////////
3834 template<typename F, typename Rp, typename Fp>
3835 struct future_deferred_continuation_shared_state: shared_state<Rp>
3836 {
3837 F parent;
3838 Fp continuation;
3839
3840 public:
3841 future_deferred_continuation_shared_state(
3842 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
3843 ) :
3844 parent(boost::move(f)),
3845 continuation(boost::move(c))
3846 {
3847 this->set_deferred();
3848 }
3849
3850 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
3851 {
3852 execute(lk);
3853 }
3854
3855 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
3856 try
3857 {
3858 Fp local_fuct=boost::move(continuation);
3859 F ftmp = boost::move(parent);
3860 relocker relock(lck);
3861 Rp res = local_fuct(boost::move(ftmp));
3862 relock.lock();
3863 this->mark_finished_with_result_internal(boost::move(res), lck);
3864 }
3865 catch (...)
3866 {
3867 this->mark_exceptional_finish_internal(current_exception(), lck);
3868 }
3869 }
3870 };
3871
3872 template<typename F, typename Fp>
3873 struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void>
3874 {
3875 F parent;
3876 Fp continuation;
3877
3878 public:
3879 future_deferred_continuation_shared_state(
3880 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
3881 ):
3882 parent(boost::move(f)),
3883 continuation(boost::move(c))
3884 {
3885 this->set_deferred();
3886 }
3887
3888 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
3889 {
3890 execute(lk);
3891 }
3892 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
3893 try
3894 {
3895 Fp local_fuct=boost::move(continuation);
3896 F ftmp = boost::move(parent);
3897 relocker relock(lck);
3898 local_fuct(boost::move(ftmp));
3899 relock.lock();
3900 this->mark_finished_with_result_internal(lck);
3901 }
3902 catch (...)
3903 {
3904 this->mark_exceptional_finish_internal(current_exception(), lck);
3905 }
3906 }
3907 };
3908
3909 ////////////////////////////////
3910 // make_future_deferred_continuation_shared_state
3911 ////////////////////////////////
3912 template<typename F, typename Rp, typename Fp>
3913 BOOST_THREAD_FUTURE<Rp>
3914 make_future_deferred_continuation_shared_state(
3915 boost::unique_lock<boost::mutex> &lock,
3916 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
3917 )
3918 {
3919 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> >
3920 h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
3921 h->parent.future_->set_continuation_ptr(h, lock);
3922 return BOOST_THREAD_FUTURE<Rp>(h);
3923 }
3924
3925 ////////////////////////////////
3926 // make_future_async_continuation_shared_state
3927 ////////////////////////////////
3928 template<typename F, typename Rp, typename Fp>
3929 BOOST_THREAD_FUTURE<Rp>
3930 make_future_async_continuation_shared_state(
3931 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
3932 )
3933 {
3934 shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> >
3935 h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
3936 h->parent.future_->set_continuation_ptr(h, lock);
3937
3938 return BOOST_THREAD_FUTURE<Rp>(h);
3939 }
3940
3941 }
3942
3943 ////////////////////////////////
3944 // template<typename F>
3945 // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
3946 ////////////////////////////////
3947
3948 template <typename R>
3949 template <typename F>
3950 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
3951 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func)
3952 {
3953
3954 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
3955 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
3956
3957 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
3958 if (int(policy) & int(launch::async))
3959 {
3960 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
3961 lock, boost::move(*this), boost::forward<F>(func)
3962 )));
3963 }
3964 else if (int(policy) & int(launch::deferred))
3965 {
3966 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
3967 lock, boost::move(*this), boost::forward<F>(func)
3968 )));
3969 }
3970 else
3971 {
3972 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
3973 lock, boost::move(*this), boost::forward<F>(func)
3974 )));
3975
3976 }
3977
3978 }
3979 template <typename R>
3980 template <typename F>
3981 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
3982 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func)
3983 {
3984
3985 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
3986 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
3987
3988 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
3989 if (int(this->launch_policy(lock)) & int(launch::async))
3990 {
3991 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
3992 lock, boost::move(*this), boost::forward<F>(func)
3993 );
3994 }
3995 else if (int(this->launch_policy(lock)) & int(launch::deferred))
3996 {
3997 this->future_->wait_internal(lock);
3998 return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
3999 lock, boost::move(*this), boost::forward<F>(func)
4000 );
4001 }
4002 else
4003 {
4004 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
4005 lock, boost::move(*this), boost::forward<F>(func)
4006 );
4007 }
4008 }
4009
4010
4011 //#if 0 && defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
4012 // template <typename R>
4013 // template<typename RF>
4014 // BOOST_THREAD_FUTURE<RF>
4015 // BOOST_THREAD_FUTURE<R>::then(RF(*func)(BOOST_THREAD_FUTURE<R>&))
4016 // {
4017 //
4018 // typedef RF future_type;
4019 //
4020 // if (this->future_)
4021 // {
4022 // boost::unique_lock<boost::mutex> lock(this->future_->mutex);
4023 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
4024 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func);
4025 // if (ptr==0)
4026 // {
4027 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
4028 // }
4029 // this->future_->set_continuation_ptr(ptr, lock);
4030 // return ptr->get_future();
4031 // } else {
4032 // // fixme what to do when the future has no associated state?
4033 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
4034 // }
4035 //
4036 // }
4037 // template <typename R>
4038 // template<typename RF>
4039 // BOOST_THREAD_FUTURE<RF>
4040 // BOOST_THREAD_FUTURE<R>::then(launch policy, RF(*func)(BOOST_THREAD_FUTURE<R>&))
4041 // {
4042 //
4043 // typedef RF future_type;
4044 //
4045 // if (this->future_)
4046 // {
4047 // boost::unique_lock<boost::mutex> lock(this->future_->mutex);
4048 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
4049 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func, policy);
4050 // if (ptr==0)
4051 // {
4052 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
4053 // }
4054 // this->future_->set_continuation_ptr(ptr, lock);
4055 // return ptr->get_future();
4056 // } else {
4057 // // fixme what to do when the future has no associated state?
4058 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
4059 // }
4060 //
4061 // }
4062 //#endif
4063
4064 template <typename R>
4065 template <typename F>
4066 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
4067 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func)
4068 {
4069
4070 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
4071 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4072
4073 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
4074 if (int(policy) & int(launch::async))
4075 {
4076 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
4077 lock, boost::move(*this), boost::forward<F>(func)
4078 )));
4079 }
4080 else if (int(policy) & int(launch::deferred))
4081 {
4082 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
4083 lock, boost::move(*this), boost::forward<F>(func)
4084 )));
4085 }
4086 else
4087 {
4088 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
4089 lock, boost::move(*this), boost::forward<F>(func)
4090 )));
4091 }
4092
4093 }
4094 template <typename R>
4095 template <typename F>
4096 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
4097 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func)
4098 {
4099
4100 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
4101
4102 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4103
4104 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
4105 if (int(this->launch_policy(lock)) & int(launch::async))
4106 {
4107 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
4108 lock, boost::move(*this), boost::forward<F>(func)
4109 );
4110 }
4111 else if (int(this->launch_policy(lock)) & int(launch::deferred))
4112 {
4113 this->future_->wait_internal(lock);
4114 return boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
4115 lock, boost::move(*this), boost::forward<F>(func)
4116 );
4117 }
4118 else
4119 {
4120 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
4121 lock, boost::move(*this), boost::forward<F>(func)
4122 );
4123 }
4124 }
4125 namespace detail
4126 {
4127 template <typename T>
4128 struct mfallbacker_to
4129 {
4130 T value_;
4131 typedef T result_type;
4132 mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
4133 : value_(boost::move(v))
4134 {}
4135
4136 T operator()(BOOST_THREAD_FUTURE<T> fut)
4137 {
4138 return fut.get_or(boost::move(value_));
4139
4140 }
4141 };
4142 template <typename T>
4143 struct cfallbacker_to
4144 {
4145 T value_;
4146 typedef T result_type;
4147 cfallbacker_to(T const& v)
4148 : value_(v)
4149 {}
4150
4151 T operator()(BOOST_THREAD_FUTURE<T> fut)
4152 {
4153 return fut.get_or(value_);
4154
4155 }
4156 };
4157 }
4158 ////////////////////////////////
4159 // future<R> future<R>::fallback_to(R&& v);
4160 ////////////////////////////////
4161
4162 template <typename R>
4163 template <typename R2>
4164 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
4165 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v)
4166 {
4167 return then(detail::mfallbacker_to<R>(boost::move(v)));
4168 }
4169
4170 template <typename R>
4171 template <typename R2>
4172 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
4173 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v)
4174 {
4175 return then(detail::cfallbacker_to<R>(v));
4176 }
4177
4178 #endif
4179
4180 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
4181 namespace detail
4182 {
4183
4184 /////////////////////////
4185 /// future_unwrap_shared_state
4186 /////////////////////////
4187
4188 template<typename F, typename Rp>
4189 struct future_unwrap_shared_state: shared_state<Rp>
4190 {
4191 F parent;
4192 public:
4193 explicit future_unwrap_shared_state(
4194 BOOST_THREAD_RV_REF(F) f
4195 ) :
4196 parent(boost::move(f))
4197 {
4198 }
4199 virtual void wait(bool ) // todo see if rethrow must be used
4200 {
4201 boost::unique_lock<boost::mutex> lock(mutex);
4202 parent.get().wait();
4203 }
4204 virtual Rp get()
4205 {
4206 boost::unique_lock<boost::mutex> lock(mutex);
4207 return parent.get().get();
4208 }
4209
4210 };
4211
4212 template <class F, class Rp>
4213 BOOST_THREAD_FUTURE<Rp>
4214 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f)
4215 {
4216 shared_ptr<future_unwrap_shared_state<F, Rp> >
4217 h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
4218 h->parent.future_->set_continuation_ptr(h, lock);
4219 return BOOST_THREAD_FUTURE<Rp>(h);
4220 }
4221 }
4222
4223 template <typename R>
4224 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other):
4225 base_type(other.unwrap())
4226 {
4227 }
4228
4229 template <typename R2>
4230 BOOST_THREAD_FUTURE<R2>
4231 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
4232 {
4233 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
4234 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
4235 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
4236 }
4237 #endif
4238 }
4239
4240 #endif // BOOST_NO_EXCEPTION
4241 #endif // header