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