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