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