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