annotate DEPENDENCIES/generic/include/boost/thread/future.hpp @ 125:34e428693f5d vext

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