annotate DEPENDENCIES/generic/include/boost/thread/future.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 // (C) Copyright 2008-10 Anthony Williams
Chris@16 2 // (C) Copyright 2011-2013 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@16 18 //#include <boost/thread/detail/log.hpp>
Chris@16 19 #include <boost/detail/scoped_enum_emulation.hpp>
Chris@16 20 #include <stdexcept>
Chris@16 21 #include <boost/thread/detail/move.hpp>
Chris@16 22 #include <boost/thread/detail/async_func.hpp>
Chris@16 23 #include <boost/thread/thread_time.hpp>
Chris@16 24 #include <boost/thread/mutex.hpp>
Chris@16 25 #include <boost/thread/condition_variable.hpp>
Chris@16 26 #include <boost/thread/lock_algorithms.hpp>
Chris@16 27 #include <boost/thread/lock_types.hpp>
Chris@16 28 #include <boost/exception_ptr.hpp>
Chris@16 29 #include <boost/shared_ptr.hpp>
Chris@16 30 #include <boost/scoped_ptr.hpp>
Chris@16 31 #include <boost/type_traits/is_fundamental.hpp>
Chris@16 32 #include <boost/thread/detail/is_convertible.hpp>
Chris@16 33 #include <boost/type_traits/remove_reference.hpp>
Chris@16 34 #include <boost/type_traits/remove_cv.hpp>
Chris@16 35 #include <boost/type_traits/is_void.hpp>
Chris@16 36 #include <boost/mpl/if.hpp>
Chris@16 37 #include <boost/config.hpp>
Chris@16 38 #include <boost/throw_exception.hpp>
Chris@16 39 #include <algorithm>
Chris@16 40 #include <boost/function.hpp>
Chris@16 41 #include <boost/bind.hpp>
Chris@16 42 #include <boost/ref.hpp>
Chris@16 43 #include <boost/scoped_array.hpp>
Chris@16 44 #include <boost/enable_shared_from_this.hpp>
Chris@16 45 #include <boost/utility/enable_if.hpp>
Chris@16 46 #include <list>
Chris@16 47 #include <boost/next_prior.hpp>
Chris@16 48 #include <vector>
Chris@16 49
Chris@16 50 #include <boost/thread/future_error_code.hpp>
Chris@16 51 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 52 #include <boost/chrono/system_clocks.hpp>
Chris@16 53 #endif
Chris@16 54
Chris@16 55 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
Chris@16 56 #include <boost/thread/detail/memory.hpp>
Chris@16 57 #endif
Chris@16 58
Chris@16 59 #include <boost/utility/result_of.hpp>
Chris@16 60 #include <boost/thread/thread_only.hpp>
Chris@16 61
Chris@16 62 #if defined BOOST_THREAD_PROVIDES_FUTURE
Chris@16 63 #define BOOST_THREAD_FUTURE future
Chris@16 64 #else
Chris@16 65 #define BOOST_THREAD_FUTURE unique_future
Chris@16 66 #endif
Chris@16 67
Chris@16 68 namespace boost
Chris@16 69 {
Chris@16 70
Chris@16 71 //enum class launch
Chris@16 72 BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
Chris@16 73 {
Chris@16 74 none = 0,
Chris@16 75 async = 1,
Chris@16 76 deferred = 2,
Chris@16 77 any = async | deferred
Chris@16 78 }
Chris@16 79 BOOST_SCOPED_ENUM_DECLARE_END(launch)
Chris@16 80
Chris@16 81 //enum class future_status
Chris@16 82 BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
Chris@16 83 {
Chris@16 84 ready,
Chris@16 85 timeout,
Chris@16 86 deferred
Chris@16 87 }
Chris@16 88 BOOST_SCOPED_ENUM_DECLARE_END(future_status)
Chris@16 89
Chris@16 90 class BOOST_SYMBOL_VISIBLE future_error
Chris@16 91 : public std::logic_error
Chris@16 92 {
Chris@16 93 system::error_code ec_;
Chris@16 94 public:
Chris@16 95 future_error(system::error_code ec)
Chris@16 96 : logic_error(ec.message()),
Chris@16 97 ec_(ec)
Chris@16 98 {
Chris@16 99 }
Chris@16 100
Chris@16 101 const system::error_code& code() const BOOST_NOEXCEPT
Chris@16 102 {
Chris@16 103 return ec_;
Chris@16 104 }
Chris@16 105 };
Chris@16 106
Chris@16 107 class BOOST_SYMBOL_VISIBLE future_uninitialized:
Chris@16 108 public future_error
Chris@16 109 {
Chris@16 110 public:
Chris@16 111 future_uninitialized() :
Chris@16 112 future_error(system::make_error_code(future_errc::no_state))
Chris@16 113 {}
Chris@16 114 };
Chris@16 115 class BOOST_SYMBOL_VISIBLE broken_promise:
Chris@16 116 public future_error
Chris@16 117 {
Chris@16 118 public:
Chris@16 119 broken_promise():
Chris@16 120 future_error(system::make_error_code(future_errc::broken_promise))
Chris@16 121 {}
Chris@16 122 };
Chris@16 123 class BOOST_SYMBOL_VISIBLE future_already_retrieved:
Chris@16 124 public future_error
Chris@16 125 {
Chris@16 126 public:
Chris@16 127 future_already_retrieved():
Chris@16 128 future_error(system::make_error_code(future_errc::future_already_retrieved))
Chris@16 129 {}
Chris@16 130 };
Chris@16 131 class BOOST_SYMBOL_VISIBLE promise_already_satisfied:
Chris@16 132 public future_error
Chris@16 133 {
Chris@16 134 public:
Chris@16 135 promise_already_satisfied():
Chris@16 136 future_error(system::make_error_code(future_errc::promise_already_satisfied))
Chris@16 137 {}
Chris@16 138 };
Chris@16 139
Chris@16 140 class BOOST_SYMBOL_VISIBLE task_already_started:
Chris@16 141 public future_error
Chris@16 142 {
Chris@16 143 public:
Chris@16 144 task_already_started():
Chris@16 145 future_error(system::make_error_code(future_errc::promise_already_satisfied))
Chris@16 146 {}
Chris@16 147 };
Chris@16 148
Chris@16 149 class BOOST_SYMBOL_VISIBLE task_moved:
Chris@16 150 public future_error
Chris@16 151 {
Chris@16 152 public:
Chris@16 153 task_moved():
Chris@16 154 future_error(system::make_error_code(future_errc::no_state))
Chris@16 155 {}
Chris@16 156 };
Chris@16 157
Chris@16 158 class promise_moved:
Chris@16 159 public future_error
Chris@16 160 {
Chris@16 161 public:
Chris@16 162 promise_moved():
Chris@16 163 future_error(system::make_error_code(future_errc::no_state))
Chris@16 164 {}
Chris@16 165 };
Chris@16 166
Chris@16 167 namespace future_state
Chris@16 168 {
Chris@16 169 enum state { uninitialized, waiting, ready, moved, deferred };
Chris@16 170 }
Chris@16 171
Chris@16 172 namespace detail
Chris@16 173 {
Chris@16 174 struct relocker
Chris@16 175 {
Chris@16 176 boost::unique_lock<boost::mutex>& lock_;
Chris@16 177 bool unlocked_;
Chris@16 178
Chris@16 179 relocker(boost::unique_lock<boost::mutex>& lk):
Chris@16 180 lock_(lk)
Chris@16 181 {
Chris@16 182 lock_.unlock();
Chris@16 183 unlocked_=true;
Chris@16 184 }
Chris@16 185 ~relocker()
Chris@16 186 {
Chris@16 187 if (unlocked_) {
Chris@16 188 lock_.lock();
Chris@16 189 }
Chris@16 190 }
Chris@16 191 void lock() {
Chris@16 192 if (unlocked_) {
Chris@16 193 lock_.lock();
Chris@16 194 unlocked_=false;
Chris@16 195 }
Chris@16 196 }
Chris@16 197 private:
Chris@16 198 relocker& operator=(relocker const&);
Chris@16 199 };
Chris@16 200
Chris@16 201 struct shared_state_base : enable_shared_from_this<shared_state_base>
Chris@16 202 {
Chris@16 203 typedef std::list<boost::condition_variable_any*> waiter_list;
Chris@16 204 // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
Chris@16 205 typedef shared_ptr<shared_state_base> continuation_ptr_type;
Chris@16 206
Chris@16 207 boost::exception_ptr exception;
Chris@16 208 bool done;
Chris@16 209 bool is_deferred_;
Chris@16 210 launch policy_;
Chris@16 211 bool is_constructed;
Chris@16 212 mutable boost::mutex mutex;
Chris@16 213 boost::condition_variable waiters;
Chris@16 214 waiter_list external_waiters;
Chris@16 215 boost::function<void()> callback;
Chris@16 216 // This declaration should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
Chris@16 217 bool thread_was_interrupted;
Chris@16 218 // This declaration should be only included conditionally, but is included to maintain the same layout.
Chris@16 219 continuation_ptr_type continuation_ptr;
Chris@16 220
Chris@16 221 // This declaration should be only included conditionally, but is included to maintain the same layout.
Chris@16 222 virtual void launch_continuation(boost::unique_lock<boost::mutex>&)
Chris@16 223 {
Chris@16 224 }
Chris@16 225
Chris@16 226 shared_state_base():
Chris@16 227 done(false),
Chris@16 228 is_deferred_(false),
Chris@16 229 policy_(launch::none),
Chris@16 230 is_constructed(false),
Chris@16 231 thread_was_interrupted(false),
Chris@16 232 continuation_ptr()
Chris@16 233 {}
Chris@16 234 virtual ~shared_state_base()
Chris@16 235 {}
Chris@16 236
Chris@16 237 void set_deferred()
Chris@16 238 {
Chris@16 239 is_deferred_ = true;
Chris@16 240 policy_ = launch::deferred;
Chris@16 241 }
Chris@16 242 void set_async()
Chris@16 243 {
Chris@16 244 is_deferred_ = false;
Chris@16 245 policy_ = launch::async;
Chris@16 246 }
Chris@16 247
Chris@16 248 waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
Chris@16 249 {
Chris@16 250 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 251 do_callback(lock);
Chris@16 252 return external_waiters.insert(external_waiters.end(),&cv);
Chris@16 253 }
Chris@16 254
Chris@16 255 void remove_external_waiter(waiter_list::iterator it)
Chris@16 256 {
Chris@16 257 boost::lock_guard<boost::mutex> lock(mutex);
Chris@16 258 external_waiters.erase(it);
Chris@16 259 }
Chris@16 260
Chris@16 261 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 262 void do_continuation(boost::unique_lock<boost::mutex>& lock)
Chris@16 263 {
Chris@16 264 if (continuation_ptr) {
Chris@16 265 continuation_ptr->launch_continuation(lock);
Chris@16 266 if (! lock.owns_lock())
Chris@16 267 lock.lock();
Chris@16 268 continuation_ptr.reset();
Chris@16 269 }
Chris@16 270 }
Chris@16 271 #else
Chris@16 272 void do_continuation(boost::unique_lock<boost::mutex>&)
Chris@16 273 {
Chris@16 274 }
Chris@16 275 #endif
Chris@16 276 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 277 void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
Chris@16 278 {
Chris@16 279 continuation_ptr= continuation;
Chris@16 280 if (done) {
Chris@16 281 do_continuation(lock);
Chris@16 282 }
Chris@16 283 }
Chris@16 284 #endif
Chris@16 285 void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
Chris@16 286 {
Chris@16 287 done=true;
Chris@16 288 waiters.notify_all();
Chris@16 289 for(waiter_list::const_iterator it=external_waiters.begin(),
Chris@16 290 end=external_waiters.end();it!=end;++it)
Chris@16 291 {
Chris@16 292 (*it)->notify_all();
Chris@16 293 }
Chris@16 294 do_continuation(lock);
Chris@16 295 }
Chris@16 296 void make_ready()
Chris@16 297 {
Chris@16 298 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 299 mark_finished_internal(lock);
Chris@16 300 }
Chris@16 301
Chris@16 302 void do_callback(boost::unique_lock<boost::mutex>& lock)
Chris@16 303 {
Chris@16 304 if(callback && !done)
Chris@16 305 {
Chris@16 306 boost::function<void()> local_callback=callback;
Chris@16 307 relocker relock(lock);
Chris@16 308 local_callback();
Chris@16 309 }
Chris@16 310 }
Chris@16 311
Chris@16 312 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true)
Chris@16 313 {
Chris@16 314 do_callback(lk);
Chris@16 315 //if (!done) // fixme why this doesn't work?
Chris@16 316 {
Chris@16 317 if (is_deferred_)
Chris@16 318 {
Chris@16 319 is_deferred_=false;
Chris@16 320 execute(lk);
Chris@16 321 //lk.unlock();
Chris@16 322 }
Chris@16 323 else
Chris@16 324 {
Chris@16 325 while(!done)
Chris@16 326 {
Chris@16 327 waiters.wait(lk);
Chris@16 328 }
Chris@16 329 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 330 if(rethrow && thread_was_interrupted)
Chris@16 331 {
Chris@16 332 throw boost::thread_interrupted();
Chris@16 333 }
Chris@16 334 #endif
Chris@16 335 if(rethrow && exception)
Chris@16 336 {
Chris@16 337 boost::rethrow_exception(exception);
Chris@16 338 }
Chris@16 339 }
Chris@16 340 }
Chris@16 341 }
Chris@16 342
Chris@16 343 virtual void wait(bool rethrow=true)
Chris@16 344 {
Chris@16 345 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 346 wait_internal(lock, rethrow);
Chris@16 347 }
Chris@16 348
Chris@16 349 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 350 bool timed_wait_until(boost::system_time const& target_time)
Chris@16 351 {
Chris@16 352 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 353 if (is_deferred_)
Chris@16 354 return false;
Chris@16 355
Chris@16 356 do_callback(lock);
Chris@16 357 while(!done)
Chris@16 358 {
Chris@16 359 bool const success=waiters.timed_wait(lock,target_time);
Chris@16 360 if(!success && !done)
Chris@16 361 {
Chris@16 362 return false;
Chris@16 363 }
Chris@16 364 }
Chris@16 365 return true;
Chris@16 366 }
Chris@16 367 #endif
Chris@16 368 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 369
Chris@16 370 template <class Clock, class Duration>
Chris@16 371 future_status
Chris@16 372 wait_until(const chrono::time_point<Clock, Duration>& abs_time)
Chris@16 373 {
Chris@16 374 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 375 if (is_deferred_)
Chris@16 376 return future_status::deferred;
Chris@16 377 do_callback(lock);
Chris@16 378 while(!done)
Chris@16 379 {
Chris@16 380 cv_status const st=waiters.wait_until(lock,abs_time);
Chris@16 381 if(st==cv_status::timeout && !done)
Chris@16 382 {
Chris@16 383 return future_status::timeout;
Chris@16 384 }
Chris@16 385 }
Chris@16 386 return future_status::ready;
Chris@16 387 }
Chris@16 388 #endif
Chris@16 389 void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
Chris@16 390 {
Chris@16 391 exception=e;
Chris@16 392 mark_finished_internal(lock);
Chris@16 393 }
Chris@16 394
Chris@16 395 void mark_exceptional_finish()
Chris@16 396 {
Chris@16 397 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 398 mark_exceptional_finish_internal(boost::current_exception(), lock);
Chris@16 399 }
Chris@16 400
Chris@16 401 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 402 void mark_interrupted_finish()
Chris@16 403 {
Chris@16 404 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 405 thread_was_interrupted=true;
Chris@16 406 mark_finished_internal(lock);
Chris@16 407 }
Chris@16 408
Chris@16 409 void set_interrupted_at_thread_exit()
Chris@16 410 {
Chris@16 411 unique_lock<boost::mutex> lk(mutex);
Chris@16 412 thread_was_interrupted=true;
Chris@16 413 if (has_value(lk))
Chris@16 414 {
Chris@16 415 throw_exception(promise_already_satisfied());
Chris@16 416 }
Chris@16 417 detail::make_ready_at_thread_exit(shared_from_this());
Chris@16 418 }
Chris@16 419 #endif
Chris@16 420
Chris@16 421 void set_exception_at_thread_exit(exception_ptr e)
Chris@16 422 {
Chris@16 423 unique_lock<boost::mutex> lk(mutex);
Chris@16 424 if (has_value(lk))
Chris@16 425 {
Chris@16 426 throw_exception(promise_already_satisfied());
Chris@16 427 }
Chris@16 428 exception=e;
Chris@16 429 this->is_constructed = true;
Chris@16 430 detail::make_ready_at_thread_exit(shared_from_this());
Chris@16 431
Chris@16 432 }
Chris@16 433
Chris@16 434 bool has_value() const
Chris@16 435 {
Chris@16 436 boost::lock_guard<boost::mutex> lock(mutex);
Chris@16 437 return done && !(exception
Chris@16 438 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 439 || thread_was_interrupted
Chris@16 440 #endif
Chris@16 441 );
Chris@16 442 }
Chris@16 443
Chris@16 444 bool has_value(unique_lock<boost::mutex>& ) const
Chris@16 445 {
Chris@16 446 return done && !(exception
Chris@16 447 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 448 || thread_was_interrupted
Chris@16 449 #endif
Chris@16 450 );
Chris@16 451 }
Chris@16 452
Chris@16 453 bool has_exception() const
Chris@16 454 {
Chris@16 455 boost::lock_guard<boost::mutex> lock(mutex);
Chris@16 456 return done && (exception
Chris@16 457 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 458 || thread_was_interrupted
Chris@16 459 #endif
Chris@16 460 );
Chris@16 461 }
Chris@16 462
Chris@16 463 bool has_exception(unique_lock<boost::mutex>&) const
Chris@16 464 {
Chris@16 465 return done && (exception
Chris@16 466 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 467 || thread_was_interrupted
Chris@16 468 #endif
Chris@16 469 );
Chris@16 470 }
Chris@16 471
Chris@16 472 bool is_deferred(boost::lock_guard<boost::mutex>&) const {
Chris@16 473 return is_deferred_;
Chris@16 474 }
Chris@16 475
Chris@16 476 launch launch_policy(boost::unique_lock<boost::mutex>&) const
Chris@16 477 {
Chris@16 478 return policy_;
Chris@16 479 }
Chris@16 480
Chris@16 481 future_state::state get_state() const
Chris@16 482 {
Chris@16 483 boost::lock_guard<boost::mutex> guard(mutex);
Chris@16 484 if(!done)
Chris@16 485 {
Chris@16 486 return future_state::waiting;
Chris@16 487 }
Chris@16 488 else
Chris@16 489 {
Chris@16 490 return future_state::ready;
Chris@16 491 }
Chris@16 492 }
Chris@16 493
Chris@16 494 exception_ptr get_exception_ptr()
Chris@16 495 {
Chris@16 496 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 497 return get_exception_ptr(lock);
Chris@16 498 }
Chris@16 499 exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock)
Chris@16 500 {
Chris@16 501 wait_internal(lock, false);
Chris@16 502 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 503 if(thread_was_interrupted)
Chris@16 504 {
Chris@16 505 return copy_exception(boost::thread_interrupted());
Chris@16 506 }
Chris@16 507 #endif
Chris@16 508 return exception;
Chris@16 509 }
Chris@16 510
Chris@16 511 template<typename F,typename U>
Chris@16 512 void set_wait_callback(F f,U* u)
Chris@16 513 {
Chris@16 514 boost::lock_guard<boost::mutex> lock(mutex);
Chris@16 515 callback=boost::bind(f,boost::ref(*u));
Chris@16 516 }
Chris@16 517
Chris@16 518 virtual void execute(boost::unique_lock<boost::mutex>&) {}
Chris@16 519
Chris@16 520 private:
Chris@16 521 shared_state_base(shared_state_base const&);
Chris@16 522 shared_state_base& operator=(shared_state_base const&);
Chris@16 523 };
Chris@16 524
Chris@16 525 template<typename T>
Chris@16 526 struct future_traits
Chris@16 527 {
Chris@16 528 typedef boost::scoped_ptr<T> storage_type;
Chris@16 529 struct dummy;
Chris@16 530 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 531 typedef T const& source_reference_type;
Chris@16 532 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
Chris@16 533 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
Chris@16 534 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
Chris@16 535 typedef T move_dest_type;
Chris@16 536 #elif defined BOOST_THREAD_USES_MOVE
Chris@16 537 typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,T&>::type source_reference_type;
Chris@16 538 //typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
Chris@16 539 //typedef typename boost::mpl::if_c<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
Chris@16 540 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
Chris@16 541 typedef T move_dest_type;
Chris@16 542 #else
Chris@16 543 typedef T& source_reference_type;
Chris@16 544 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
Chris@16 545 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
Chris@16 546 #endif
Chris@16 547
Chris@16 548
Chris@16 549 typedef const T& shared_future_get_result_type;
Chris@16 550
Chris@16 551 static void init(storage_type& storage,source_reference_type t)
Chris@16 552 {
Chris@16 553 storage.reset(new T(t));
Chris@16 554 }
Chris@16 555
Chris@16 556 static void init(storage_type& storage,rvalue_source_type t)
Chris@16 557 {
Chris@16 558 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 559 storage.reset(new T(boost::forward<T>(t)));
Chris@16 560 #else
Chris@16 561 storage.reset(new T(static_cast<rvalue_source_type>(t)));
Chris@16 562 #endif
Chris@16 563 }
Chris@16 564
Chris@16 565 static void cleanup(storage_type& storage)
Chris@16 566 {
Chris@16 567 storage.reset();
Chris@16 568 }
Chris@16 569 };
Chris@16 570
Chris@16 571 template<typename T>
Chris@16 572 struct future_traits<T&>
Chris@16 573 {
Chris@16 574 typedef T* storage_type;
Chris@16 575 typedef T& source_reference_type;
Chris@16 576 //struct rvalue_source_type
Chris@16 577 //{};
Chris@16 578 typedef T& move_dest_type;
Chris@16 579 typedef T& shared_future_get_result_type;
Chris@16 580
Chris@16 581 static void init(storage_type& storage,T& t)
Chris@16 582 {
Chris@16 583 storage=&t;
Chris@16 584 }
Chris@16 585
Chris@16 586 static void cleanup(storage_type& storage)
Chris@16 587 {
Chris@16 588 storage=0;
Chris@16 589 }
Chris@16 590 };
Chris@16 591
Chris@16 592 template<>
Chris@16 593 struct future_traits<void>
Chris@16 594 {
Chris@16 595 typedef bool storage_type;
Chris@16 596 typedef void move_dest_type;
Chris@16 597 typedef void shared_future_get_result_type;
Chris@16 598
Chris@16 599 static void init(storage_type& storage)
Chris@16 600 {
Chris@16 601 storage=true;
Chris@16 602 }
Chris@16 603
Chris@16 604 static void cleanup(storage_type& storage)
Chris@16 605 {
Chris@16 606 storage=false;
Chris@16 607 }
Chris@16 608
Chris@16 609 };
Chris@16 610
Chris@16 611 // Used to create stand-alone futures
Chris@16 612 template<typename T>
Chris@16 613 struct shared_state:
Chris@16 614 detail::shared_state_base
Chris@16 615 {
Chris@16 616 typedef typename future_traits<T>::storage_type storage_type;
Chris@16 617 typedef typename future_traits<T>::source_reference_type source_reference_type;
Chris@16 618 typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
Chris@16 619 typedef typename future_traits<T>::move_dest_type move_dest_type;
Chris@16 620 typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type;
Chris@16 621
Chris@16 622 storage_type result;
Chris@16 623
Chris@16 624 shared_state():
Chris@16 625 result(0)
Chris@16 626 {}
Chris@16 627
Chris@16 628 ~shared_state()
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 future_traits<T>::init(result,result_);
Chris@16 634 this->mark_finished_internal(lock);
Chris@16 635 }
Chris@16 636
Chris@16 637 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
Chris@16 638 {
Chris@16 639 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 640 future_traits<T>::init(result,boost::forward<T>(result_));
Chris@16 641 #else
Chris@16 642 future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
Chris@16 643 #endif
Chris@16 644 this->mark_finished_internal(lock);
Chris@16 645 }
Chris@16 646
Chris@16 647 void mark_finished_with_result(source_reference_type result_)
Chris@16 648 {
Chris@16 649 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 650 this->mark_finished_with_result_internal(result_, lock);
Chris@16 651 }
Chris@16 652
Chris@16 653 void mark_finished_with_result(rvalue_source_type result_)
Chris@16 654 {
Chris@16 655 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 656
Chris@16 657 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 658 mark_finished_with_result_internal(boost::forward<T>(result_), lock);
Chris@16 659 #else
Chris@16 660 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
Chris@16 661 #endif
Chris@16 662 }
Chris@16 663
Chris@16 664 virtual move_dest_type get()
Chris@16 665 {
Chris@16 666 wait();
Chris@16 667 return boost::move(*result);
Chris@16 668 }
Chris@16 669
Chris@16 670 virtual shared_future_get_result_type get_sh()
Chris@16 671 {
Chris@16 672 wait();
Chris@16 673 return *result;
Chris@16 674 }
Chris@16 675
Chris@16 676 //void set_value_at_thread_exit(const T & result_)
Chris@16 677 void set_value_at_thread_exit(source_reference_type result_)
Chris@16 678 {
Chris@16 679 unique_lock<boost::mutex> lk(this->mutex);
Chris@16 680 if (this->has_value(lk))
Chris@16 681 {
Chris@16 682 throw_exception(promise_already_satisfied());
Chris@16 683 }
Chris@16 684 //future_traits<T>::init(result,result_);
Chris@16 685 result.reset(new T(result_));
Chris@16 686
Chris@16 687 this->is_constructed = true;
Chris@16 688 detail::make_ready_at_thread_exit(shared_from_this());
Chris@16 689 }
Chris@16 690 //void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_)
Chris@16 691 void set_value_at_thread_exit(rvalue_source_type result_)
Chris@16 692 {
Chris@16 693 unique_lock<boost::mutex> lk(this->mutex);
Chris@16 694 if (this->has_value(lk))
Chris@16 695 throw_exception(promise_already_satisfied());
Chris@16 696 result.reset(new T(boost::move(result_)));
Chris@16 697 //future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
Chris@16 698 this->is_constructed = true;
Chris@16 699 detail::make_ready_at_thread_exit(shared_from_this());
Chris@16 700 }
Chris@16 701
Chris@16 702
Chris@16 703 private:
Chris@16 704 shared_state(shared_state const&);
Chris@16 705 shared_state& operator=(shared_state const&);
Chris@16 706 };
Chris@16 707
Chris@16 708 template<typename T>
Chris@16 709 struct shared_state<T&>:
Chris@16 710 detail::shared_state_base
Chris@16 711 {
Chris@16 712 typedef typename future_traits<T&>::storage_type storage_type;
Chris@16 713 typedef typename future_traits<T&>::source_reference_type source_reference_type;
Chris@16 714 typedef typename future_traits<T&>::move_dest_type move_dest_type;
Chris@16 715 typedef typename future_traits<T&>::shared_future_get_result_type shared_future_get_result_type;
Chris@16 716
Chris@16 717 T* result;
Chris@16 718
Chris@16 719 shared_state():
Chris@16 720 result(0)
Chris@16 721 {}
Chris@16 722
Chris@16 723 ~shared_state()
Chris@16 724 {
Chris@16 725 }
Chris@16 726
Chris@16 727 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
Chris@16 728 {
Chris@16 729 //future_traits<T>::init(result,result_);
Chris@16 730 result= &result_;
Chris@16 731 mark_finished_internal(lock);
Chris@16 732 }
Chris@16 733
Chris@16 734 void mark_finished_with_result(source_reference_type result_)
Chris@16 735 {
Chris@16 736 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 737 mark_finished_with_result_internal(result_, lock);
Chris@16 738 }
Chris@16 739
Chris@16 740 virtual T& get()
Chris@16 741 {
Chris@16 742 wait();
Chris@16 743 return *result;
Chris@16 744 }
Chris@16 745
Chris@16 746 virtual T& get_sh()
Chris@16 747 {
Chris@16 748 wait();
Chris@16 749 return *result;
Chris@16 750 }
Chris@16 751
Chris@16 752 void set_value_at_thread_exit(T& result_)
Chris@16 753 {
Chris@16 754 unique_lock<boost::mutex> lk(this->mutex);
Chris@16 755 if (this->has_value(lk))
Chris@16 756 throw_exception(promise_already_satisfied());
Chris@16 757 //future_traits<T>::init(result,result_);
Chris@16 758 result= &result_;
Chris@16 759 this->is_constructed = true;
Chris@16 760 detail::make_ready_at_thread_exit(shared_from_this());
Chris@16 761 }
Chris@16 762
Chris@16 763 private:
Chris@16 764 shared_state(shared_state const&);
Chris@16 765 shared_state& operator=(shared_state const&);
Chris@16 766 };
Chris@16 767
Chris@16 768 template<>
Chris@16 769 struct shared_state<void>:
Chris@16 770 detail::shared_state_base
Chris@16 771 {
Chris@16 772 typedef void shared_future_get_result_type;
Chris@16 773
Chris@16 774 shared_state()
Chris@16 775 {}
Chris@16 776
Chris@16 777 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
Chris@16 778 {
Chris@16 779 mark_finished_internal(lock);
Chris@16 780 }
Chris@16 781
Chris@16 782 void mark_finished_with_result()
Chris@16 783 {
Chris@16 784 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 785 mark_finished_with_result_internal(lock);
Chris@16 786 }
Chris@16 787
Chris@16 788 virtual void get()
Chris@16 789 {
Chris@16 790 this->wait();
Chris@16 791 }
Chris@16 792
Chris@16 793 virtual void get_sh()
Chris@16 794 {
Chris@16 795 wait();
Chris@16 796 }
Chris@16 797
Chris@16 798 void set_value_at_thread_exit()
Chris@16 799 {
Chris@16 800 unique_lock<boost::mutex> lk(this->mutex);
Chris@16 801 if (this->has_value(lk))
Chris@16 802 {
Chris@16 803 throw_exception(promise_already_satisfied());
Chris@16 804 }
Chris@16 805 this->is_constructed = true;
Chris@16 806 detail::make_ready_at_thread_exit(shared_from_this());
Chris@16 807 }
Chris@16 808 private:
Chris@16 809 shared_state(shared_state const&);
Chris@16 810 shared_state& operator=(shared_state const&);
Chris@16 811 };
Chris@16 812
Chris@16 813 /////////////////////////
Chris@16 814 /// future_async_shared_state_base
Chris@16 815 /////////////////////////
Chris@16 816 template<typename Rp>
Chris@16 817 struct future_async_shared_state_base: shared_state<Rp>
Chris@16 818 {
Chris@16 819 typedef shared_state<Rp> base_type;
Chris@16 820 protected:
Chris@16 821 boost::thread thr_;
Chris@16 822 void join()
Chris@16 823 {
Chris@16 824 if (thr_.joinable()) thr_.join();
Chris@16 825 }
Chris@16 826 public:
Chris@16 827 future_async_shared_state_base()
Chris@16 828 {
Chris@16 829 this->set_async();
Chris@16 830 }
Chris@16 831 explicit future_async_shared_state_base(BOOST_THREAD_RV_REF(boost::thread) th) :
Chris@16 832 thr_(boost::move(th))
Chris@16 833 {
Chris@16 834 this->set_async();
Chris@16 835 }
Chris@16 836
Chris@16 837 ~future_async_shared_state_base()
Chris@16 838 {
Chris@16 839 join();
Chris@16 840 }
Chris@16 841
Chris@16 842 virtual void wait(bool rethrow)
Chris@16 843 {
Chris@16 844 join();
Chris@16 845 this->base_type::wait(rethrow);
Chris@16 846 }
Chris@16 847 };
Chris@16 848
Chris@16 849 /////////////////////////
Chris@16 850 /// future_async_shared_state
Chris@16 851 /////////////////////////
Chris@16 852 template<typename Rp, typename Fp>
Chris@16 853 struct future_async_shared_state: future_async_shared_state_base<Rp>
Chris@16 854 {
Chris@16 855 typedef future_async_shared_state_base<Rp> base_type;
Chris@16 856
Chris@16 857 public:
Chris@16 858 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) :
Chris@16 859 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f)))
Chris@16 860 {
Chris@16 861 }
Chris@16 862
Chris@16 863 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
Chris@16 864 {
Chris@16 865 try
Chris@16 866 {
Chris@16 867 that->mark_finished_with_result(f());
Chris@16 868 }
Chris@16 869 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 870 catch(thread_interrupted& )
Chris@16 871 {
Chris@16 872 that->mark_interrupted_finish();
Chris@16 873 }
Chris@16 874 #endif
Chris@16 875 catch(...)
Chris@16 876 {
Chris@16 877 that->mark_exceptional_finish();
Chris@16 878 }
Chris@16 879 }
Chris@16 880 };
Chris@16 881
Chris@16 882 template<typename Fp>
Chris@16 883 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void>
Chris@16 884 {
Chris@16 885 typedef future_async_shared_state_base<void> base_type;
Chris@16 886
Chris@16 887 public:
Chris@16 888 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) :
Chris@16 889 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f)))
Chris@16 890 {
Chris@16 891 }
Chris@16 892
Chris@16 893 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
Chris@16 894 {
Chris@16 895 try
Chris@16 896 {
Chris@16 897 f();
Chris@16 898 that->mark_finished_with_result();
Chris@16 899 }
Chris@16 900 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 901 catch(thread_interrupted& )
Chris@16 902 {
Chris@16 903 that->mark_interrupted_finish();
Chris@16 904 }
Chris@16 905 #endif
Chris@16 906 catch(...)
Chris@16 907 {
Chris@16 908 that->mark_exceptional_finish();
Chris@16 909 }
Chris@16 910 }
Chris@16 911 };
Chris@16 912
Chris@16 913 template<typename Rp, typename Fp>
Chris@16 914 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&>
Chris@16 915 {
Chris@16 916 typedef future_async_shared_state_base<Rp&> base_type;
Chris@16 917
Chris@16 918 public:
Chris@16 919 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) :
Chris@16 920 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f)))
Chris@16 921 {
Chris@16 922 }
Chris@16 923
Chris@16 924 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
Chris@16 925 {
Chris@16 926 try
Chris@16 927 {
Chris@16 928 that->mark_finished_with_result(f());
Chris@16 929 }
Chris@16 930 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 931 catch(thread_interrupted& )
Chris@16 932 {
Chris@16 933 that->mark_interrupted_finish();
Chris@16 934 }
Chris@16 935 #endif
Chris@16 936 catch(...)
Chris@16 937 {
Chris@16 938 that->mark_exceptional_finish();
Chris@16 939 }
Chris@16 940 }
Chris@16 941 };
Chris@16 942
Chris@16 943 //////////////////////////
Chris@16 944 /// future_deferred_shared_state
Chris@16 945 //////////////////////////
Chris@16 946 template<typename Rp, typename Fp>
Chris@16 947 struct future_deferred_shared_state: shared_state<Rp>
Chris@16 948 {
Chris@16 949 typedef shared_state<Rp> base_type;
Chris@16 950 Fp func_;
Chris@16 951
Chris@16 952 public:
Chris@16 953 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
Chris@16 954 : func_(boost::forward<Fp>(f))
Chris@16 955 {
Chris@16 956 this->set_deferred();
Chris@16 957 }
Chris@16 958
Chris@16 959 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
Chris@16 960 try
Chris@16 961 {
Chris@16 962 Fp local_fuct=boost::move(func_);
Chris@16 963 relocker relock(lck);
Chris@16 964 Rp res = local_fuct();
Chris@16 965 relock.lock();
Chris@16 966 this->mark_finished_with_result_internal(boost::move(res), lck);
Chris@16 967 }
Chris@16 968 catch (...)
Chris@16 969 {
Chris@16 970 this->mark_exceptional_finish_internal(current_exception(), lck);
Chris@16 971 }
Chris@16 972 }
Chris@16 973 };
Chris@16 974 template<typename Rp, typename Fp>
Chris@16 975 struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
Chris@16 976 {
Chris@16 977 typedef shared_state<Rp&> base_type;
Chris@16 978 Fp func_;
Chris@16 979
Chris@16 980 public:
Chris@16 981 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
Chris@16 982 : func_(boost::forward<Fp>(f))
Chris@16 983 {
Chris@16 984 this->set_deferred();
Chris@16 985 }
Chris@16 986
Chris@16 987 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
Chris@16 988 try
Chris@16 989 {
Chris@16 990 this->mark_finished_with_result_internal(func_(), lck);
Chris@16 991 }
Chris@16 992 catch (...)
Chris@16 993 {
Chris@16 994 this->mark_exceptional_finish_internal(current_exception(), lck);
Chris@16 995 }
Chris@16 996 }
Chris@16 997 };
Chris@16 998
Chris@16 999 template<typename Fp>
Chris@16 1000 struct future_deferred_shared_state<void,Fp>: shared_state<void>
Chris@16 1001 {
Chris@16 1002 typedef shared_state<void> base_type;
Chris@16 1003 Fp func_;
Chris@16 1004
Chris@16 1005 public:
Chris@16 1006 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
Chris@16 1007 : func_(boost::forward<Fp>(f))
Chris@16 1008 {
Chris@16 1009 this->set_deferred();
Chris@16 1010 }
Chris@16 1011
Chris@16 1012 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
Chris@16 1013 try
Chris@16 1014 {
Chris@16 1015 Fp local_fuct=boost::move(func_);
Chris@16 1016 relocker relock(lck);
Chris@16 1017 local_fuct();
Chris@16 1018 relock.lock();
Chris@16 1019 this->mark_finished_with_result_internal(lck);
Chris@16 1020 }
Chris@16 1021 catch (...)
Chris@16 1022 {
Chris@16 1023 this->mark_exceptional_finish_internal(current_exception(), lck);
Chris@16 1024 }
Chris@16 1025 }
Chris@16 1026 };
Chris@16 1027
Chris@16 1028 // template<typename T, typename Allocator>
Chris@16 1029 // struct shared_state_alloc: public shared_state<T>
Chris@16 1030 // {
Chris@16 1031 // typedef shared_state<T> base;
Chris@16 1032 // Allocator alloc_;
Chris@16 1033 //
Chris@16 1034 // public:
Chris@16 1035 // explicit shared_state_alloc(const Allocator& a)
Chris@16 1036 // : alloc_(a) {}
Chris@16 1037 //
Chris@16 1038 // };
Chris@16 1039 class future_waiter
Chris@16 1040 {
Chris@16 1041 struct registered_waiter;
Chris@16 1042 typedef std::vector<int>::size_type count_type;
Chris@16 1043
Chris@16 1044 struct registered_waiter
Chris@16 1045 {
Chris@16 1046 boost::shared_ptr<detail::shared_state_base> future_;
Chris@16 1047 detail::shared_state_base::waiter_list::iterator wait_iterator;
Chris@16 1048 count_type index;
Chris@16 1049
Chris@16 1050 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future,
Chris@16 1051 detail::shared_state_base::waiter_list::iterator wait_iterator_,
Chris@16 1052 count_type index_):
Chris@16 1053 future_(a_future),wait_iterator(wait_iterator_),index(index_)
Chris@16 1054 {}
Chris@16 1055 };
Chris@16 1056
Chris@16 1057 struct all_futures_lock
Chris@16 1058 {
Chris@16 1059 #ifdef _MANAGED
Chris@16 1060 typedef std::ptrdiff_t count_type_portable;
Chris@16 1061 #else
Chris@16 1062 typedef count_type count_type_portable;
Chris@16 1063 #endif
Chris@16 1064 count_type_portable count;
Chris@16 1065 boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
Chris@16 1066
Chris@16 1067 all_futures_lock(std::vector<registered_waiter>& futures):
Chris@16 1068 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
Chris@16 1069 {
Chris@16 1070 for(count_type_portable i=0;i<count;++i)
Chris@16 1071 {
Chris@16 1072 #if defined __DECCXX || defined __SUNPRO_CC || defined __hpux
Chris@16 1073 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move();
Chris@16 1074 #else
Chris@16 1075 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex);
Chris@16 1076 #endif
Chris@16 1077 }
Chris@16 1078 }
Chris@16 1079
Chris@16 1080 void lock()
Chris@16 1081 {
Chris@16 1082 boost::lock(locks.get(),locks.get()+count);
Chris@16 1083 }
Chris@16 1084
Chris@16 1085 void unlock()
Chris@16 1086 {
Chris@16 1087 for(count_type_portable i=0;i<count;++i)
Chris@16 1088 {
Chris@16 1089 locks[i].unlock();
Chris@16 1090 }
Chris@16 1091 }
Chris@16 1092 };
Chris@16 1093
Chris@16 1094 boost::condition_variable_any cv;
Chris@16 1095 std::vector<registered_waiter> futures;
Chris@16 1096 count_type future_count;
Chris@16 1097
Chris@16 1098 public:
Chris@16 1099 future_waiter():
Chris@16 1100 future_count(0)
Chris@16 1101 {}
Chris@16 1102
Chris@16 1103 template<typename F>
Chris@16 1104 void add(F& f)
Chris@16 1105 {
Chris@16 1106 if(f.future_)
Chris@16 1107 {
Chris@16 1108 futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count));
Chris@16 1109 }
Chris@16 1110 ++future_count;
Chris@16 1111 }
Chris@16 1112
Chris@16 1113 count_type wait()
Chris@16 1114 {
Chris@16 1115 all_futures_lock lk(futures);
Chris@16 1116 for(;;)
Chris@16 1117 {
Chris@16 1118 for(count_type i=0;i<futures.size();++i)
Chris@16 1119 {
Chris@16 1120 if(futures[i].future_->done)
Chris@16 1121 {
Chris@16 1122 return futures[i].index;
Chris@16 1123 }
Chris@16 1124 }
Chris@16 1125 cv.wait(lk);
Chris@16 1126 }
Chris@16 1127 }
Chris@16 1128
Chris@16 1129 ~future_waiter()
Chris@16 1130 {
Chris@16 1131 for(count_type i=0;i<futures.size();++i)
Chris@16 1132 {
Chris@16 1133 futures[i].future_->remove_external_waiter(futures[i].wait_iterator);
Chris@16 1134 }
Chris@16 1135 }
Chris@16 1136
Chris@16 1137 };
Chris@16 1138
Chris@16 1139 }
Chris@16 1140
Chris@16 1141 template <typename R>
Chris@16 1142 class BOOST_THREAD_FUTURE;
Chris@16 1143
Chris@16 1144 template <typename R>
Chris@16 1145 class shared_future;
Chris@16 1146
Chris@16 1147 template<typename T>
Chris@16 1148 struct is_future_type
Chris@16 1149 {
Chris@16 1150 BOOST_STATIC_CONSTANT(bool, value=false);
Chris@16 1151 typedef void type;
Chris@16 1152 };
Chris@16 1153
Chris@16 1154 template<typename T>
Chris@16 1155 struct is_future_type<BOOST_THREAD_FUTURE<T> >
Chris@16 1156 {
Chris@16 1157 BOOST_STATIC_CONSTANT(bool, value=true);
Chris@16 1158 typedef T type;
Chris@16 1159 };
Chris@16 1160
Chris@16 1161 template<typename T>
Chris@16 1162 struct is_future_type<shared_future<T> >
Chris@16 1163 {
Chris@16 1164 BOOST_STATIC_CONSTANT(bool, value=true);
Chris@16 1165 typedef T type;
Chris@16 1166 };
Chris@16 1167
Chris@16 1168 template<typename Iterator>
Chris@16 1169 typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
Chris@16 1170 {
Chris@16 1171 for(Iterator current=begin;current!=end;++current)
Chris@16 1172 {
Chris@16 1173 current->wait();
Chris@16 1174 }
Chris@16 1175 }
Chris@16 1176
Chris@16 1177 template<typename F1,typename F2>
Chris@16 1178 typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
Chris@16 1179 {
Chris@16 1180 f1.wait();
Chris@16 1181 f2.wait();
Chris@16 1182 }
Chris@16 1183
Chris@16 1184 template<typename F1,typename F2,typename F3>
Chris@16 1185 void wait_for_all(F1& f1,F2& f2,F3& f3)
Chris@16 1186 {
Chris@16 1187 f1.wait();
Chris@16 1188 f2.wait();
Chris@16 1189 f3.wait();
Chris@16 1190 }
Chris@16 1191
Chris@16 1192 template<typename F1,typename F2,typename F3,typename F4>
Chris@16 1193 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
Chris@16 1194 {
Chris@16 1195 f1.wait();
Chris@16 1196 f2.wait();
Chris@16 1197 f3.wait();
Chris@16 1198 f4.wait();
Chris@16 1199 }
Chris@16 1200
Chris@16 1201 template<typename F1,typename F2,typename F3,typename F4,typename F5>
Chris@16 1202 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
Chris@16 1203 {
Chris@16 1204 f1.wait();
Chris@16 1205 f2.wait();
Chris@16 1206 f3.wait();
Chris@16 1207 f4.wait();
Chris@16 1208 f5.wait();
Chris@16 1209 }
Chris@16 1210
Chris@16 1211 template<typename Iterator>
Chris@16 1212 typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
Chris@16 1213 {
Chris@16 1214 if(begin==end)
Chris@16 1215 return end;
Chris@16 1216
Chris@16 1217 detail::future_waiter waiter;
Chris@16 1218 for(Iterator current=begin;current!=end;++current)
Chris@16 1219 {
Chris@16 1220 waiter.add(*current);
Chris@16 1221 }
Chris@16 1222 return boost::next(begin,waiter.wait());
Chris@16 1223 }
Chris@16 1224
Chris@16 1225 template<typename F1,typename F2>
Chris@16 1226 typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2)
Chris@16 1227 {
Chris@16 1228 detail::future_waiter waiter;
Chris@16 1229 waiter.add(f1);
Chris@16 1230 waiter.add(f2);
Chris@16 1231 return waiter.wait();
Chris@16 1232 }
Chris@16 1233
Chris@16 1234 template<typename F1,typename F2,typename F3>
Chris@16 1235 unsigned wait_for_any(F1& f1,F2& f2,F3& f3)
Chris@16 1236 {
Chris@16 1237 detail::future_waiter waiter;
Chris@16 1238 waiter.add(f1);
Chris@16 1239 waiter.add(f2);
Chris@16 1240 waiter.add(f3);
Chris@16 1241 return waiter.wait();
Chris@16 1242 }
Chris@16 1243
Chris@16 1244 template<typename F1,typename F2,typename F3,typename F4>
Chris@16 1245 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
Chris@16 1246 {
Chris@16 1247 detail::future_waiter waiter;
Chris@16 1248 waiter.add(f1);
Chris@16 1249 waiter.add(f2);
Chris@16 1250 waiter.add(f3);
Chris@16 1251 waiter.add(f4);
Chris@16 1252 return waiter.wait();
Chris@16 1253 }
Chris@16 1254
Chris@16 1255 template<typename F1,typename F2,typename F3,typename F4,typename F5>
Chris@16 1256 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
Chris@16 1257 {
Chris@16 1258 detail::future_waiter waiter;
Chris@16 1259 waiter.add(f1);
Chris@16 1260 waiter.add(f2);
Chris@16 1261 waiter.add(f3);
Chris@16 1262 waiter.add(f4);
Chris@16 1263 waiter.add(f5);
Chris@16 1264 return waiter.wait();
Chris@16 1265 }
Chris@16 1266
Chris@16 1267 template <typename R>
Chris@16 1268 class promise;
Chris@16 1269
Chris@16 1270 template <typename R>
Chris@16 1271 class packaged_task;
Chris@16 1272
Chris@16 1273 namespace detail
Chris@16 1274 {
Chris@16 1275 /// Common implementation for all the futures independently of the return type
Chris@16 1276 class base_future
Chris@16 1277 {
Chris@16 1278 //BOOST_THREAD_MOVABLE(base_future)
Chris@16 1279
Chris@16 1280 };
Chris@16 1281 /// Common implementation for future and shared_future.
Chris@16 1282 template <typename R>
Chris@16 1283 class basic_future : public base_future
Chris@16 1284 {
Chris@16 1285 protected:
Chris@16 1286 public:
Chris@16 1287
Chris@16 1288 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
Chris@16 1289
Chris@16 1290 future_ptr future_;
Chris@16 1291
Chris@16 1292 basic_future(future_ptr a_future):
Chris@16 1293 future_(a_future)
Chris@16 1294 {
Chris@16 1295 }
Chris@16 1296 // Copy construction from a shared_future
Chris@16 1297 explicit basic_future(const shared_future<R>&) BOOST_NOEXCEPT;
Chris@16 1298
Chris@16 1299 public:
Chris@16 1300 typedef future_state::state state;
Chris@16 1301
Chris@16 1302 BOOST_THREAD_MOVABLE(basic_future)
Chris@16 1303 basic_future(): future_() {}
Chris@16 1304 ~basic_future() {}
Chris@16 1305
Chris@16 1306 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
Chris@16 1307 future_(BOOST_THREAD_RV(other).future_)
Chris@16 1308 {
Chris@16 1309 BOOST_THREAD_RV(other).future_.reset();
Chris@16 1310 }
Chris@16 1311 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
Chris@16 1312 {
Chris@16 1313 future_=BOOST_THREAD_RV(other).future_;
Chris@16 1314 BOOST_THREAD_RV(other).future_.reset();
Chris@16 1315 return *this;
Chris@16 1316 }
Chris@16 1317 void swap(basic_future& that) BOOST_NOEXCEPT
Chris@16 1318 {
Chris@16 1319 future_.swap(that.future_);
Chris@16 1320 }
Chris@16 1321 // functions to check state, and wait for ready
Chris@16 1322 state get_state() const
Chris@16 1323 {
Chris@16 1324 if(!future_)
Chris@16 1325 {
Chris@16 1326 return future_state::uninitialized;
Chris@16 1327 }
Chris@16 1328 return future_->get_state();
Chris@16 1329 }
Chris@16 1330
Chris@16 1331 bool is_ready() const
Chris@16 1332 {
Chris@16 1333 return get_state()==future_state::ready;
Chris@16 1334 }
Chris@16 1335
Chris@16 1336 bool has_exception() const
Chris@16 1337 {
Chris@16 1338 return future_ && future_->has_exception();
Chris@16 1339 }
Chris@16 1340
Chris@16 1341 bool has_value() const
Chris@16 1342 {
Chris@16 1343 return future_ && future_->has_value();
Chris@16 1344 }
Chris@16 1345
Chris@16 1346 launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
Chris@16 1347 {
Chris@16 1348 if ( future_ ) return future_->launch_policy(lk);
Chris@16 1349 else return launch(launch::none);
Chris@16 1350 }
Chris@16 1351
Chris@16 1352 exception_ptr get_exception_ptr()
Chris@16 1353 {
Chris@16 1354 return future_
Chris@16 1355 ? future_->get_exception_ptr()
Chris@16 1356 : exception_ptr();
Chris@16 1357 }
Chris@16 1358
Chris@16 1359 bool valid() const BOOST_NOEXCEPT
Chris@16 1360 {
Chris@16 1361 return future_ != 0;
Chris@16 1362 }
Chris@16 1363
Chris@16 1364
Chris@16 1365 void wait() const
Chris@16 1366 {
Chris@16 1367 if(!future_)
Chris@16 1368 {
Chris@16 1369 boost::throw_exception(future_uninitialized());
Chris@16 1370 }
Chris@16 1371 future_->wait(false);
Chris@16 1372 }
Chris@16 1373
Chris@16 1374 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 1375 template<typename Duration>
Chris@16 1376 bool timed_wait(Duration const& rel_time) const
Chris@16 1377 {
Chris@16 1378 return timed_wait_until(boost::get_system_time()+rel_time);
Chris@16 1379 }
Chris@16 1380
Chris@16 1381 bool timed_wait_until(boost::system_time const& abs_time) const
Chris@16 1382 {
Chris@16 1383 if(!future_)
Chris@16 1384 {
Chris@16 1385 boost::throw_exception(future_uninitialized());
Chris@16 1386 }
Chris@16 1387 return future_->timed_wait_until(abs_time);
Chris@16 1388 }
Chris@16 1389 #endif
Chris@16 1390 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 1391 template <class Rep, class Period>
Chris@16 1392 future_status
Chris@16 1393 wait_for(const chrono::duration<Rep, Period>& rel_time) const
Chris@16 1394 {
Chris@16 1395 return wait_until(chrono::steady_clock::now() + rel_time);
Chris@16 1396
Chris@16 1397 }
Chris@16 1398 template <class Clock, class Duration>
Chris@16 1399 future_status
Chris@16 1400 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
Chris@16 1401 {
Chris@16 1402 if(!future_)
Chris@16 1403 {
Chris@16 1404 boost::throw_exception(future_uninitialized());
Chris@16 1405 }
Chris@16 1406 return future_->wait_until(abs_time);
Chris@16 1407 }
Chris@16 1408 #endif
Chris@16 1409
Chris@16 1410 };
Chris@16 1411
Chris@16 1412 } // detail
Chris@16 1413 BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
Chris@16 1414
Chris@16 1415 namespace detail
Chris@16 1416 {
Chris@16 1417 #if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
Chris@16 1418 template <class Rp, class Fp>
Chris@16 1419 BOOST_THREAD_FUTURE<Rp>
Chris@16 1420 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
Chris@16 1421
Chris@16 1422 template <class Rp, class Fp>
Chris@16 1423 BOOST_THREAD_FUTURE<Rp>
Chris@16 1424 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
Chris@16 1425 #endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
Chris@16 1426 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 1427 template<typename F, typename Rp, typename Fp>
Chris@16 1428 struct future_deferred_continuation_shared_state;
Chris@16 1429 template<typename F, typename Rp, typename Fp>
Chris@16 1430 struct future_async_continuation_shared_state;
Chris@16 1431
Chris@16 1432 template <class F, class Rp, class Fp>
Chris@16 1433 BOOST_THREAD_FUTURE<Rp>
Chris@16 1434 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 1435
Chris@16 1436 template <class F, class Rp, class Fp>
Chris@16 1437 BOOST_THREAD_FUTURE<Rp>
Chris@16 1438 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 1439 #endif
Chris@16 1440 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
Chris@16 1441 template<typename F, typename Rp>
Chris@16 1442 struct future_unwrap_shared_state;
Chris@16 1443 template <class F, class Rp>
Chris@16 1444 inline BOOST_THREAD_FUTURE<Rp>
Chris@16 1445 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
Chris@16 1446 #endif
Chris@16 1447 }
Chris@16 1448
Chris@16 1449 template <typename R>
Chris@16 1450 class BOOST_THREAD_FUTURE : public detail::basic_future<R>
Chris@16 1451 {
Chris@16 1452 private:
Chris@16 1453 typedef detail::basic_future<R> base_type;
Chris@16 1454 typedef typename base_type::future_ptr future_ptr;
Chris@16 1455
Chris@16 1456 friend class shared_future<R>;
Chris@16 1457 friend class promise<R>;
Chris@16 1458 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 1459 template <typename, typename, typename>
Chris@16 1460 friend struct detail::future_async_continuation_shared_state;
Chris@16 1461 template <typename, typename, typename>
Chris@16 1462 friend struct detail::future_deferred_continuation_shared_state;
Chris@16 1463
Chris@16 1464 template <class F, class Rp, class Fp>
Chris@16 1465 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1466 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 1467
Chris@16 1468 template <class F, class Rp, class Fp>
Chris@16 1469 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1470 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 1471 #endif
Chris@16 1472 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
Chris@16 1473 template<typename F, typename Rp>
Chris@16 1474 friend struct detail::future_unwrap_shared_state;
Chris@16 1475 template <class F, class Rp>
Chris@16 1476 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1477 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
Chris@16 1478 #endif
Chris@16 1479 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 1480 template <class> friend class packaged_task; // todo check if this works in windows
Chris@16 1481 #else
Chris@16 1482 friend class packaged_task<R>;
Chris@16 1483 #endif
Chris@16 1484 friend class detail::future_waiter;
Chris@16 1485
Chris@16 1486 template <class Rp, class Fp>
Chris@16 1487 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1488 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
Chris@16 1489
Chris@16 1490 template <class Rp, class Fp>
Chris@16 1491 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1492 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
Chris@16 1493
Chris@16 1494
Chris@16 1495 typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
Chris@16 1496
Chris@16 1497 BOOST_THREAD_FUTURE(future_ptr a_future):
Chris@16 1498 base_type(a_future)
Chris@16 1499 {
Chris@16 1500 }
Chris@16 1501
Chris@16 1502 public:
Chris@16 1503 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
Chris@16 1504 typedef future_state::state state;
Chris@16 1505 typedef R value_type; // EXTENSION
Chris@16 1506
Chris@16 1507 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
Chris@16 1508
Chris@16 1509 ~BOOST_THREAD_FUTURE() {}
Chris@16 1510
Chris@16 1511 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
Chris@16 1512 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
Chris@16 1513 {
Chris@16 1514 }
Chris@16 1515 inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
Chris@16 1516
Chris@16 1517 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
Chris@16 1518 {
Chris@16 1519 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
Chris@16 1520 return *this;
Chris@16 1521 }
Chris@16 1522
Chris@16 1523 shared_future<R> share()
Chris@16 1524 {
Chris@16 1525 return shared_future<R>(::boost::move(*this));
Chris@16 1526 }
Chris@16 1527
Chris@16 1528 void swap(BOOST_THREAD_FUTURE& other)
Chris@16 1529 {
Chris@16 1530 static_cast<base_type*>(this)->swap(other);
Chris@16 1531 }
Chris@16 1532
Chris@16 1533 // todo this function must be private and friendship provided to the internal users.
Chris@16 1534 void set_async()
Chris@16 1535 {
Chris@16 1536 this->future_->set_async();
Chris@16 1537 }
Chris@16 1538 // todo this function must be private and friendship provided to the internal users.
Chris@16 1539 void set_deferred()
Chris@16 1540 {
Chris@16 1541 this->future_->set_deferred();
Chris@16 1542 }
Chris@16 1543
Chris@16 1544 // retrieving the value
Chris@16 1545 move_dest_type get()
Chris@16 1546 {
Chris@16 1547 if(!this->future_)
Chris@16 1548 {
Chris@16 1549 boost::throw_exception(future_uninitialized());
Chris@16 1550 }
Chris@16 1551 future_ptr fut_=this->future_;
Chris@16 1552 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
Chris@16 1553 this->future_.reset();
Chris@16 1554 #endif
Chris@16 1555 return fut_->get();
Chris@16 1556 }
Chris@16 1557
Chris@16 1558 template <typename R2>
Chris@16 1559 typename boost::disable_if< is_void<R2>, move_dest_type>::type
Chris@16 1560 get_or(BOOST_THREAD_RV_REF(R2) v)
Chris@16 1561 {
Chris@16 1562 if(!this->future_)
Chris@16 1563 {
Chris@16 1564 boost::throw_exception(future_uninitialized());
Chris@16 1565 }
Chris@16 1566 this->future_->wait(false);
Chris@16 1567 future_ptr fut_=this->future_;
Chris@16 1568 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
Chris@16 1569 this->future_.reset();
Chris@16 1570 #endif
Chris@16 1571 if (fut_->has_value()) {
Chris@16 1572 return fut_->get();
Chris@16 1573 }
Chris@16 1574 else {
Chris@16 1575 return boost::move(v);
Chris@16 1576 }
Chris@16 1577 }
Chris@16 1578
Chris@16 1579 template <typename R2>
Chris@16 1580 typename boost::disable_if< is_void<R2>, move_dest_type>::type
Chris@16 1581 get_or(R2 const& v) // EXTENSION
Chris@16 1582 {
Chris@16 1583 if(!this->future_)
Chris@16 1584 {
Chris@16 1585 boost::throw_exception(future_uninitialized());
Chris@16 1586 }
Chris@16 1587 this->future_->wait(false);
Chris@16 1588 future_ptr fut_=this->future_;
Chris@16 1589 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
Chris@16 1590 this->future_.reset();
Chris@16 1591 #endif
Chris@16 1592 if (fut_->has_value()) {
Chris@16 1593 return fut_->get();
Chris@16 1594 }
Chris@16 1595 else {
Chris@16 1596 return v;
Chris@16 1597 }
Chris@16 1598 }
Chris@16 1599
Chris@16 1600
Chris@16 1601 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 1602
Chris@16 1603 // template<typename F>
Chris@16 1604 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
Chris@16 1605
Chris@16 1606 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
Chris@16 1607 // template<typename RF>
Chris@16 1608 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
Chris@16 1609 // template<typename RF>
Chris@16 1610 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&));
Chris@16 1611 //#endif
Chris@16 1612 template<typename F>
Chris@16 1613 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
Chris@16 1614 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
Chris@16 1615 template<typename F>
Chris@16 1616 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
Chris@16 1617 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
Chris@16 1618
Chris@16 1619 template <typename R2>
Chris@16 1620 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
Chris@16 1621 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION
Chris@16 1622 template <typename R2>
Chris@16 1623 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
Chris@16 1624 fallback_to(R2 const& v); // EXTENSION
Chris@16 1625
Chris@16 1626 #endif
Chris@16 1627
Chris@16 1628 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
Chris@16 1629 // inline
Chris@16 1630 // typename boost::enable_if<
Chris@16 1631 // is_future_type<value_type>,
Chris@16 1632 // value_type
Chris@16 1633 // //BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type>
Chris@16 1634 // >::type
Chris@16 1635 // unwrap();
Chris@16 1636 //#endif
Chris@16 1637
Chris@16 1638 };
Chris@16 1639
Chris@16 1640 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
Chris@16 1641
Chris@16 1642 template <typename R2>
Chris@16 1643 class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
Chris@16 1644 {
Chris@16 1645 typedef BOOST_THREAD_FUTURE<R2> R;
Chris@16 1646
Chris@16 1647 private:
Chris@16 1648 typedef detail::basic_future<R> base_type;
Chris@16 1649 typedef typename base_type::future_ptr future_ptr;
Chris@16 1650
Chris@16 1651 friend class shared_future<R>;
Chris@16 1652 friend class promise<R>;
Chris@16 1653 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 1654 template <typename, typename, typename>
Chris@16 1655 friend struct detail::future_async_continuation_shared_state;
Chris@16 1656 template <typename, typename, typename>
Chris@16 1657 friend struct detail::future_deferred_continuation_shared_state;
Chris@16 1658
Chris@16 1659 template <class F, class Rp, class Fp>
Chris@16 1660 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1661 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 1662
Chris@16 1663 template <class F, class Rp, class Fp>
Chris@16 1664 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1665 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 1666 #endif
Chris@16 1667 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
Chris@16 1668 template<typename F, typename Rp>
Chris@16 1669 friend struct detail::future_unwrap_shared_state;
Chris@16 1670 template <class F, class Rp>
Chris@16 1671 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1672 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
Chris@16 1673 #endif
Chris@16 1674 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 1675 template <class> friend class packaged_task; // todo check if this works in windows
Chris@16 1676 #else
Chris@16 1677 friend class packaged_task<R>;
Chris@16 1678 #endif
Chris@16 1679 friend class detail::future_waiter;
Chris@16 1680
Chris@16 1681 template <class Rp, class Fp>
Chris@16 1682 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1683 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
Chris@16 1684
Chris@16 1685 template <class Rp, class Fp>
Chris@16 1686 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1687 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
Chris@16 1688
Chris@16 1689
Chris@16 1690 typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
Chris@16 1691
Chris@16 1692 BOOST_THREAD_FUTURE(future_ptr a_future):
Chris@16 1693 base_type(a_future)
Chris@16 1694 {
Chris@16 1695 }
Chris@16 1696
Chris@16 1697 public:
Chris@16 1698 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
Chris@16 1699 typedef future_state::state state;
Chris@16 1700 typedef R value_type; // EXTENSION
Chris@16 1701
Chris@16 1702 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
Chris@16 1703
Chris@16 1704 ~BOOST_THREAD_FUTURE() {}
Chris@16 1705
Chris@16 1706 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
Chris@16 1707 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
Chris@16 1708 {
Chris@16 1709 }
Chris@16 1710
Chris@16 1711 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
Chris@16 1712 {
Chris@16 1713 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
Chris@16 1714 return *this;
Chris@16 1715 }
Chris@16 1716
Chris@16 1717 shared_future<R> share()
Chris@16 1718 {
Chris@16 1719 return shared_future<R>(::boost::move(*this));
Chris@16 1720 }
Chris@16 1721
Chris@16 1722 void swap(BOOST_THREAD_FUTURE& other)
Chris@16 1723 {
Chris@16 1724 static_cast<base_type*>(this)->swap(other);
Chris@16 1725 }
Chris@16 1726
Chris@16 1727 // todo this function must be private and friendship provided to the internal users.
Chris@16 1728 void set_async()
Chris@16 1729 {
Chris@16 1730 this->future_->set_async();
Chris@16 1731 }
Chris@16 1732 // todo this function must be private and friendship provided to the internal users.
Chris@16 1733 void set_deferred()
Chris@16 1734 {
Chris@16 1735 this->future_->set_deferred();
Chris@16 1736 }
Chris@16 1737
Chris@16 1738 // retrieving the value
Chris@16 1739 move_dest_type get()
Chris@16 1740 {
Chris@16 1741 if(!this->future_)
Chris@16 1742 {
Chris@16 1743 boost::throw_exception(future_uninitialized());
Chris@16 1744 }
Chris@16 1745 future_ptr fut_=this->future_;
Chris@16 1746 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
Chris@16 1747 this->future_.reset();
Chris@16 1748 #endif
Chris@16 1749 return fut_->get();
Chris@16 1750 }
Chris@16 1751 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
Chris@16 1752 {
Chris@16 1753 if(!this->future_)
Chris@16 1754 {
Chris@16 1755 boost::throw_exception(future_uninitialized());
Chris@16 1756 }
Chris@16 1757 this->future_->wait(false);
Chris@16 1758 future_ptr fut_=this->future_;
Chris@16 1759 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
Chris@16 1760 this->future_.reset();
Chris@16 1761 #endif
Chris@16 1762 if (fut_->has_value()) return fut_->get();
Chris@16 1763 else return boost::move(v);
Chris@16 1764 }
Chris@16 1765
Chris@16 1766 move_dest_type get_or(R const& v) // EXTENSION
Chris@16 1767 {
Chris@16 1768 if(!this->future_)
Chris@16 1769 {
Chris@16 1770 boost::throw_exception(future_uninitialized());
Chris@16 1771 }
Chris@16 1772 this->future_->wait(false);
Chris@16 1773 future_ptr fut_=this->future_;
Chris@16 1774 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
Chris@16 1775 this->future_.reset();
Chris@16 1776 #endif
Chris@16 1777 if (fut_->has_value()) return fut_->get();
Chris@16 1778 else return v;
Chris@16 1779 }
Chris@16 1780
Chris@16 1781
Chris@16 1782 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 1783
Chris@16 1784 // template<typename F>
Chris@16 1785 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
Chris@16 1786
Chris@16 1787 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
Chris@16 1788 // template<typename RF>
Chris@16 1789 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
Chris@16 1790 // template<typename RF>
Chris@16 1791 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&));
Chris@16 1792 //#endif
Chris@16 1793 template<typename F>
Chris@16 1794 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
Chris@16 1795 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
Chris@16 1796 template<typename F>
Chris@16 1797 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
Chris@16 1798 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
Chris@16 1799 #endif
Chris@16 1800
Chris@16 1801 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
Chris@16 1802 inline
Chris@16 1803 BOOST_THREAD_FUTURE<R2>
Chris@16 1804 unwrap(); // EXTENSION
Chris@16 1805 #endif
Chris@16 1806
Chris@16 1807 };
Chris@16 1808
Chris@16 1809 template <typename R>
Chris@16 1810 class shared_future : public detail::basic_future<R>
Chris@16 1811 {
Chris@16 1812
Chris@16 1813 typedef detail::basic_future<R> base_type;
Chris@16 1814 typedef typename base_type::future_ptr future_ptr;
Chris@16 1815
Chris@16 1816 friend class detail::future_waiter;
Chris@16 1817 friend class promise<R>;
Chris@16 1818
Chris@16 1819 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 1820 template <typename, typename, typename>
Chris@16 1821 friend struct detail::future_async_continuation_shared_state;
Chris@16 1822 template <typename, typename, typename>
Chris@16 1823 friend struct detail::future_deferred_continuation_shared_state;
Chris@16 1824
Chris@16 1825 template <class F, class Rp, class Fp>
Chris@16 1826 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1827 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 1828
Chris@16 1829 template <class F, class Rp, class Fp>
Chris@16 1830 friend BOOST_THREAD_FUTURE<Rp>
Chris@16 1831 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 1832 #endif
Chris@16 1833 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 1834 template <class> friend class packaged_task;// todo check if this works in windows
Chris@16 1835 #else
Chris@16 1836 friend class packaged_task<R>;
Chris@16 1837 #endif
Chris@16 1838 shared_future(future_ptr a_future):
Chris@16 1839 base_type(a_future)
Chris@16 1840 {}
Chris@16 1841
Chris@16 1842 public:
Chris@16 1843 BOOST_THREAD_MOVABLE(shared_future)
Chris@16 1844 typedef R value_type; // EXTENSION
Chris@16 1845
Chris@16 1846 shared_future(shared_future const& other):
Chris@16 1847 base_type(other)
Chris@16 1848 {}
Chris@16 1849
Chris@16 1850 typedef future_state::state state;
Chris@16 1851
Chris@16 1852 BOOST_CONSTEXPR shared_future()
Chris@16 1853 {}
Chris@16 1854
Chris@16 1855 ~shared_future()
Chris@16 1856 {}
Chris@16 1857
Chris@16 1858 shared_future& operator=(shared_future const& other)
Chris@16 1859 {
Chris@16 1860 shared_future(other).swap(*this);
Chris@16 1861 return *this;
Chris@16 1862 }
Chris@16 1863 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
Chris@16 1864 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
Chris@16 1865 {
Chris@16 1866 BOOST_THREAD_RV(other).future_.reset();
Chris@16 1867 }
Chris@16 1868 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
Chris@16 1869 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
Chris@16 1870 {
Chris@16 1871 }
Chris@16 1872
Chris@16 1873 shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
Chris@16 1874 {
Chris@16 1875 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
Chris@16 1876 return *this;
Chris@16 1877 }
Chris@16 1878 shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
Chris@16 1879 {
Chris@16 1880 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
Chris@16 1881 return *this;
Chris@16 1882 }
Chris@16 1883
Chris@16 1884 void swap(shared_future& other) BOOST_NOEXCEPT
Chris@16 1885 {
Chris@16 1886 static_cast<base_type*>(this)->swap(other);
Chris@16 1887 }
Chris@16 1888
Chris@16 1889 // retrieving the value
Chris@16 1890 typename detail::shared_state<R>::shared_future_get_result_type get()
Chris@16 1891 {
Chris@16 1892 if(!this->future_)
Chris@16 1893 {
Chris@16 1894 boost::throw_exception(future_uninitialized());
Chris@16 1895 }
Chris@16 1896
Chris@16 1897 return this->future_->get_sh();
Chris@16 1898 }
Chris@16 1899
Chris@16 1900 template <typename R2>
Chris@16 1901 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
Chris@16 1902 get_or(BOOST_THREAD_RV_REF(R2) v) // EXTENSION
Chris@16 1903 {
Chris@16 1904 if(!this->future_)
Chris@16 1905 {
Chris@16 1906 boost::throw_exception(future_uninitialized());
Chris@16 1907 }
Chris@16 1908 future_ptr fut_=this->future_;
Chris@16 1909 fut_->wait();
Chris@16 1910 if (fut_->has_value()) return fut_->get_sh();
Chris@16 1911 else return boost::move(v);
Chris@16 1912 }
Chris@16 1913
Chris@16 1914 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 1915
Chris@16 1916 // template<typename F>
Chris@16 1917 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
Chris@16 1918 // template<typename F>
Chris@16 1919 // auto then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
Chris@16 1920
Chris@16 1921 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
Chris@16 1922 // template<typename RF>
Chris@16 1923 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(shared_future&));
Chris@16 1924 // template<typename RF>
Chris@16 1925 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(shared_future&));
Chris@16 1926 //#endif
Chris@16 1927 template<typename F>
Chris@16 1928 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
Chris@16 1929 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
Chris@16 1930 template<typename F>
Chris@16 1931 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
Chris@16 1932 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
Chris@16 1933 #endif
Chris@16 1934 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
Chris@16 1935 // inline
Chris@16 1936 // typename boost::enable_if_c<
Chris@16 1937 // is_future_type<value_type>::value,
Chris@16 1938 // BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type>
Chris@16 1939 // >::type
Chris@16 1940 // unwrap();
Chris@16 1941 //#endif
Chris@16 1942
Chris@16 1943 };
Chris@16 1944
Chris@16 1945 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
Chris@16 1946
Chris@16 1947 namespace detail
Chris@16 1948 {
Chris@16 1949 /// Copy construction from a shared_future
Chris@16 1950 template <typename R>
Chris@16 1951 inline basic_future<R>::basic_future(const shared_future<R>& other) BOOST_NOEXCEPT
Chris@16 1952 : future_(other.future_)
Chris@16 1953 {
Chris@16 1954 }
Chris@16 1955 }
Chris@16 1956
Chris@16 1957 template <typename R>
Chris@16 1958 class promise
Chris@16 1959 {
Chris@16 1960 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
Chris@16 1961
Chris@16 1962 future_ptr future_;
Chris@16 1963 bool future_obtained;
Chris@16 1964
Chris@16 1965 void lazy_init()
Chris@16 1966 {
Chris@16 1967 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
Chris@16 1968 #include <boost/detail/atomic_undef_macros.hpp>
Chris@16 1969 if(!atomic_load(&future_))
Chris@16 1970 {
Chris@16 1971 future_ptr blank;
Chris@16 1972 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
Chris@16 1973 }
Chris@16 1974 #include <boost/detail/atomic_redef_macros.hpp>
Chris@16 1975 #endif
Chris@16 1976 }
Chris@16 1977
Chris@16 1978 public:
Chris@16 1979 BOOST_THREAD_MOVABLE_ONLY(promise)
Chris@16 1980 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
Chris@16 1981 template <class Allocator>
Chris@16 1982 promise(boost::allocator_arg_t, Allocator a)
Chris@16 1983 {
Chris@16 1984 typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2;
Chris@16 1985 A2 a2(a);
Chris@16 1986 typedef thread_detail::allocator_destructor<A2> D;
Chris@16 1987
Chris@16 1988 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) );
Chris@16 1989 future_obtained = false;
Chris@16 1990 }
Chris@16 1991 #endif
Chris@16 1992 promise():
Chris@16 1993 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
Chris@16 1994 future_(),
Chris@16 1995 #else
Chris@16 1996 future_(new detail::shared_state<R>()),
Chris@16 1997 #endif
Chris@16 1998 future_obtained(false)
Chris@16 1999 {}
Chris@16 2000
Chris@16 2001 ~promise()
Chris@16 2002 {
Chris@16 2003 if(future_)
Chris@16 2004 {
Chris@16 2005 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2006
Chris@16 2007 if(!future_->done && !future_->is_constructed)
Chris@16 2008 {
Chris@16 2009 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
Chris@16 2010 }
Chris@16 2011 }
Chris@16 2012 }
Chris@16 2013
Chris@16 2014 // Assignment
Chris@16 2015 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
Chris@16 2016 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
Chris@16 2017 {
Chris@16 2018 BOOST_THREAD_RV(rhs).future_.reset();
Chris@16 2019 BOOST_THREAD_RV(rhs).future_obtained=false;
Chris@16 2020 }
Chris@16 2021 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
Chris@16 2022 {
Chris@16 2023 future_=BOOST_THREAD_RV(rhs).future_;
Chris@16 2024 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
Chris@16 2025 BOOST_THREAD_RV(rhs).future_.reset();
Chris@16 2026 BOOST_THREAD_RV(rhs).future_obtained=false;
Chris@16 2027 return *this;
Chris@16 2028 }
Chris@16 2029
Chris@16 2030 void swap(promise& other)
Chris@16 2031 {
Chris@16 2032 future_.swap(other.future_);
Chris@16 2033 std::swap(future_obtained,other.future_obtained);
Chris@16 2034 }
Chris@16 2035
Chris@16 2036 // Result retrieval
Chris@16 2037 BOOST_THREAD_FUTURE<R> get_future()
Chris@16 2038 {
Chris@16 2039 lazy_init();
Chris@16 2040 if (future_.get()==0)
Chris@16 2041 {
Chris@16 2042 boost::throw_exception(promise_moved());
Chris@16 2043 }
Chris@16 2044 if (future_obtained)
Chris@16 2045 {
Chris@16 2046 boost::throw_exception(future_already_retrieved());
Chris@16 2047 }
Chris@16 2048 future_obtained=true;
Chris@16 2049 return BOOST_THREAD_FUTURE<R>(future_);
Chris@16 2050 }
Chris@16 2051
Chris@16 2052 void set_value(typename detail::future_traits<R>::source_reference_type r)
Chris@16 2053 {
Chris@16 2054 lazy_init();
Chris@16 2055 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2056 if(future_->done)
Chris@16 2057 {
Chris@16 2058 boost::throw_exception(promise_already_satisfied());
Chris@16 2059 }
Chris@16 2060 future_->mark_finished_with_result_internal(r, lock);
Chris@16 2061 }
Chris@16 2062
Chris@16 2063 // void set_value(R && r);
Chris@16 2064 void set_value(typename detail::future_traits<R>::rvalue_source_type r)
Chris@16 2065 {
Chris@16 2066 lazy_init();
Chris@16 2067 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2068 if(future_->done)
Chris@16 2069 {
Chris@16 2070 boost::throw_exception(promise_already_satisfied());
Chris@16 2071 }
Chris@16 2072 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2073 future_->mark_finished_with_result_internal(boost::forward<R>(r), lock);
Chris@16 2074 #else
Chris@16 2075 future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r), lock);
Chris@16 2076 #endif
Chris@16 2077 }
Chris@16 2078
Chris@16 2079 void set_exception(boost::exception_ptr p)
Chris@16 2080 {
Chris@16 2081 lazy_init();
Chris@16 2082 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2083 if(future_->done)
Chris@16 2084 {
Chris@16 2085 boost::throw_exception(promise_already_satisfied());
Chris@16 2086 }
Chris@16 2087 future_->mark_exceptional_finish_internal(p, lock);
Chris@16 2088 }
Chris@16 2089 template <typename E>
Chris@16 2090 void set_exception(E ex)
Chris@16 2091 {
Chris@16 2092 set_exception(copy_exception(ex));
Chris@16 2093 }
Chris@16 2094 // setting the result with deferred notification
Chris@16 2095 void set_value_at_thread_exit(const R& r)
Chris@16 2096 {
Chris@16 2097 if (future_.get()==0)
Chris@16 2098 {
Chris@16 2099 boost::throw_exception(promise_moved());
Chris@16 2100 }
Chris@16 2101 future_->set_value_at_thread_exit(r);
Chris@16 2102 }
Chris@16 2103
Chris@16 2104 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
Chris@16 2105 {
Chris@16 2106 if (future_.get()==0)
Chris@16 2107 {
Chris@16 2108 boost::throw_exception(promise_moved());
Chris@16 2109 }
Chris@16 2110 future_->set_value_at_thread_exit(boost::move(r));
Chris@16 2111 }
Chris@16 2112 void set_exception_at_thread_exit(exception_ptr e)
Chris@16 2113 {
Chris@16 2114 if (future_.get()==0)
Chris@16 2115 {
Chris@16 2116 boost::throw_exception(promise_moved());
Chris@16 2117 }
Chris@16 2118 future_->set_exception_at_thread_exit(e);
Chris@16 2119 }
Chris@16 2120 template <typename E>
Chris@16 2121 void set_exception_at_thread_exit(E ex)
Chris@16 2122 {
Chris@16 2123 set_exception_at_thread_exit(copy_exception(ex));
Chris@16 2124 }
Chris@16 2125
Chris@16 2126 template<typename F>
Chris@16 2127 void set_wait_callback(F f)
Chris@16 2128 {
Chris@16 2129 lazy_init();
Chris@16 2130 future_->set_wait_callback(f,this);
Chris@16 2131 }
Chris@16 2132
Chris@16 2133 };
Chris@16 2134
Chris@16 2135 template <typename R>
Chris@16 2136 class promise<R&>
Chris@16 2137 {
Chris@16 2138 typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr;
Chris@16 2139
Chris@16 2140 future_ptr future_;
Chris@16 2141 bool future_obtained;
Chris@16 2142
Chris@16 2143 void lazy_init()
Chris@16 2144 {
Chris@16 2145 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
Chris@16 2146 #include <boost/detail/atomic_undef_macros.hpp>
Chris@16 2147 if(!atomic_load(&future_))
Chris@16 2148 {
Chris@16 2149 future_ptr blank;
Chris@16 2150 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
Chris@16 2151 }
Chris@16 2152 #include <boost/detail/atomic_redef_macros.hpp>
Chris@16 2153 #endif
Chris@16 2154 }
Chris@16 2155
Chris@16 2156 public:
Chris@16 2157 BOOST_THREAD_MOVABLE_ONLY(promise)
Chris@16 2158 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
Chris@16 2159 template <class Allocator>
Chris@16 2160 promise(boost::allocator_arg_t, Allocator a)
Chris@16 2161 {
Chris@16 2162 typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2;
Chris@16 2163 A2 a2(a);
Chris@16 2164 typedef thread_detail::allocator_destructor<A2> D;
Chris@16 2165
Chris@16 2166 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
Chris@16 2167 future_obtained = false;
Chris@16 2168 }
Chris@16 2169 #endif
Chris@16 2170 promise():
Chris@16 2171 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
Chris@16 2172 future_(),
Chris@16 2173 #else
Chris@16 2174 future_(new detail::shared_state<R&>()),
Chris@16 2175 #endif
Chris@16 2176 future_obtained(false)
Chris@16 2177 {}
Chris@16 2178
Chris@16 2179 ~promise()
Chris@16 2180 {
Chris@16 2181 if(future_)
Chris@16 2182 {
Chris@16 2183 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2184
Chris@16 2185 if(!future_->done && !future_->is_constructed)
Chris@16 2186 {
Chris@16 2187 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
Chris@16 2188 }
Chris@16 2189 }
Chris@16 2190 }
Chris@16 2191
Chris@16 2192 // Assignment
Chris@16 2193 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
Chris@16 2194 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
Chris@16 2195 {
Chris@16 2196 BOOST_THREAD_RV(rhs).future_.reset();
Chris@16 2197 BOOST_THREAD_RV(rhs).future_obtained=false;
Chris@16 2198 }
Chris@16 2199 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
Chris@16 2200 {
Chris@16 2201 future_=BOOST_THREAD_RV(rhs).future_;
Chris@16 2202 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
Chris@16 2203 BOOST_THREAD_RV(rhs).future_.reset();
Chris@16 2204 BOOST_THREAD_RV(rhs).future_obtained=false;
Chris@16 2205 return *this;
Chris@16 2206 }
Chris@16 2207
Chris@16 2208 void swap(promise& other)
Chris@16 2209 {
Chris@16 2210 future_.swap(other.future_);
Chris@16 2211 std::swap(future_obtained,other.future_obtained);
Chris@16 2212 }
Chris@16 2213
Chris@16 2214 // Result retrieval
Chris@16 2215 BOOST_THREAD_FUTURE<R&> get_future()
Chris@16 2216 {
Chris@16 2217 lazy_init();
Chris@16 2218 if (future_.get()==0)
Chris@16 2219 {
Chris@16 2220 boost::throw_exception(promise_moved());
Chris@16 2221 }
Chris@16 2222 if (future_obtained)
Chris@16 2223 {
Chris@16 2224 boost::throw_exception(future_already_retrieved());
Chris@16 2225 }
Chris@16 2226 future_obtained=true;
Chris@16 2227 return BOOST_THREAD_FUTURE<R&>(future_);
Chris@16 2228 }
Chris@16 2229
Chris@16 2230 void set_value(R& r)
Chris@16 2231 {
Chris@16 2232 lazy_init();
Chris@16 2233 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2234 if(future_->done)
Chris@16 2235 {
Chris@16 2236 boost::throw_exception(promise_already_satisfied());
Chris@16 2237 }
Chris@16 2238 future_->mark_finished_with_result_internal(r, lock);
Chris@16 2239 }
Chris@16 2240
Chris@16 2241 void set_exception(boost::exception_ptr p)
Chris@16 2242 {
Chris@16 2243 lazy_init();
Chris@16 2244 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2245 if(future_->done)
Chris@16 2246 {
Chris@16 2247 boost::throw_exception(promise_already_satisfied());
Chris@16 2248 }
Chris@16 2249 future_->mark_exceptional_finish_internal(p, lock);
Chris@16 2250 }
Chris@16 2251 template <typename E>
Chris@16 2252 void set_exception(E ex)
Chris@16 2253 {
Chris@16 2254 set_exception(copy_exception(ex));
Chris@16 2255 }
Chris@16 2256
Chris@16 2257 // setting the result with deferred notification
Chris@16 2258 void set_value_at_thread_exit(R& r)
Chris@16 2259 {
Chris@16 2260 if (future_.get()==0)
Chris@16 2261 {
Chris@16 2262 boost::throw_exception(promise_moved());
Chris@16 2263 }
Chris@16 2264 future_->set_value_at_thread_exit(r);
Chris@16 2265 }
Chris@16 2266
Chris@16 2267 void set_exception_at_thread_exit(exception_ptr e)
Chris@16 2268 {
Chris@16 2269 if (future_.get()==0)
Chris@16 2270 {
Chris@16 2271 boost::throw_exception(promise_moved());
Chris@16 2272 }
Chris@16 2273 future_->set_exception_at_thread_exit(e);
Chris@16 2274 }
Chris@16 2275 template <typename E>
Chris@16 2276 void set_exception_at_thread_exit(E ex)
Chris@16 2277 {
Chris@16 2278 set_exception_at_thread_exit(copy_exception(ex));
Chris@16 2279 }
Chris@16 2280
Chris@16 2281 template<typename F>
Chris@16 2282 void set_wait_callback(F f)
Chris@16 2283 {
Chris@16 2284 lazy_init();
Chris@16 2285 future_->set_wait_callback(f,this);
Chris@16 2286 }
Chris@16 2287
Chris@16 2288 };
Chris@16 2289 template <>
Chris@16 2290 class promise<void>
Chris@16 2291 {
Chris@16 2292 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr;
Chris@16 2293
Chris@16 2294 future_ptr future_;
Chris@16 2295 bool future_obtained;
Chris@16 2296
Chris@16 2297 void lazy_init()
Chris@16 2298 {
Chris@16 2299 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
Chris@16 2300 if(!atomic_load(&future_))
Chris@16 2301 {
Chris@16 2302 future_ptr blank;
Chris@16 2303 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>));
Chris@16 2304 }
Chris@16 2305 #endif
Chris@16 2306 }
Chris@16 2307 public:
Chris@16 2308 BOOST_THREAD_MOVABLE_ONLY(promise)
Chris@16 2309
Chris@16 2310 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
Chris@16 2311 template <class Allocator>
Chris@16 2312 promise(boost::allocator_arg_t, Allocator a)
Chris@16 2313 {
Chris@16 2314 typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2;
Chris@16 2315 A2 a2(a);
Chris@16 2316 typedef thread_detail::allocator_destructor<A2> D;
Chris@16 2317
Chris@16 2318 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
Chris@16 2319 future_obtained = false;
Chris@16 2320 }
Chris@16 2321 #endif
Chris@16 2322 promise():
Chris@16 2323 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
Chris@16 2324 future_(),
Chris@16 2325 #else
Chris@16 2326 future_(new detail::shared_state<void>),
Chris@16 2327 #endif
Chris@16 2328 future_obtained(false)
Chris@16 2329 {}
Chris@16 2330
Chris@16 2331 ~promise()
Chris@16 2332 {
Chris@16 2333 if(future_)
Chris@16 2334 {
Chris@16 2335 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2336
Chris@16 2337 if(!future_->done && !future_->is_constructed)
Chris@16 2338 {
Chris@16 2339 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
Chris@16 2340 }
Chris@16 2341 }
Chris@16 2342 }
Chris@16 2343
Chris@16 2344 // Assignment
Chris@16 2345 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
Chris@16 2346 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
Chris@16 2347 {
Chris@16 2348 // we need to release the future as shared_ptr doesn't implements move semantics
Chris@16 2349 BOOST_THREAD_RV(rhs).future_.reset();
Chris@16 2350 BOOST_THREAD_RV(rhs).future_obtained=false;
Chris@16 2351 }
Chris@16 2352
Chris@16 2353 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
Chris@16 2354 {
Chris@16 2355 future_=BOOST_THREAD_RV(rhs).future_;
Chris@16 2356 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
Chris@16 2357 BOOST_THREAD_RV(rhs).future_.reset();
Chris@16 2358 BOOST_THREAD_RV(rhs).future_obtained=false;
Chris@16 2359 return *this;
Chris@16 2360 }
Chris@16 2361
Chris@16 2362 void swap(promise& other)
Chris@16 2363 {
Chris@16 2364 future_.swap(other.future_);
Chris@16 2365 std::swap(future_obtained,other.future_obtained);
Chris@16 2366 }
Chris@16 2367
Chris@16 2368 // Result retrieval
Chris@16 2369 BOOST_THREAD_FUTURE<void> get_future()
Chris@16 2370 {
Chris@16 2371 lazy_init();
Chris@16 2372
Chris@16 2373 if (future_.get()==0)
Chris@16 2374 {
Chris@16 2375 boost::throw_exception(promise_moved());
Chris@16 2376 }
Chris@16 2377 if(future_obtained)
Chris@16 2378 {
Chris@16 2379 boost::throw_exception(future_already_retrieved());
Chris@16 2380 }
Chris@16 2381 future_obtained=true;
Chris@16 2382 return BOOST_THREAD_FUTURE<void>(future_);
Chris@16 2383 }
Chris@16 2384
Chris@16 2385 void set_value()
Chris@16 2386 {
Chris@16 2387 lazy_init();
Chris@16 2388 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2389 if(future_->done)
Chris@16 2390 {
Chris@16 2391 boost::throw_exception(promise_already_satisfied());
Chris@16 2392 }
Chris@16 2393 future_->mark_finished_with_result_internal(lock);
Chris@16 2394 }
Chris@16 2395
Chris@16 2396 void set_exception(boost::exception_ptr p)
Chris@16 2397 {
Chris@16 2398 lazy_init();
Chris@16 2399 boost::unique_lock<boost::mutex> lock(future_->mutex);
Chris@16 2400 if(future_->done)
Chris@16 2401 {
Chris@16 2402 boost::throw_exception(promise_already_satisfied());
Chris@16 2403 }
Chris@16 2404 future_->mark_exceptional_finish_internal(p,lock);
Chris@16 2405 }
Chris@16 2406 template <typename E>
Chris@16 2407 void set_exception(E ex)
Chris@16 2408 {
Chris@16 2409 set_exception(copy_exception(ex));
Chris@16 2410 }
Chris@16 2411
Chris@16 2412 // setting the result with deferred notification
Chris@16 2413 void set_value_at_thread_exit()
Chris@16 2414 {
Chris@16 2415 if (future_.get()==0)
Chris@16 2416 {
Chris@16 2417 boost::throw_exception(promise_moved());
Chris@16 2418 }
Chris@16 2419 future_->set_value_at_thread_exit();
Chris@16 2420 }
Chris@16 2421
Chris@16 2422 void set_exception_at_thread_exit(exception_ptr e)
Chris@16 2423 {
Chris@16 2424 if (future_.get()==0)
Chris@16 2425 {
Chris@16 2426 boost::throw_exception(promise_moved());
Chris@16 2427 }
Chris@16 2428 future_->set_exception_at_thread_exit(e);
Chris@16 2429 }
Chris@16 2430 template <typename E>
Chris@16 2431 void set_exception_at_thread_exit(E ex)
Chris@16 2432 {
Chris@16 2433 set_exception_at_thread_exit(copy_exception(ex));
Chris@16 2434 }
Chris@16 2435
Chris@16 2436 template<typename F>
Chris@16 2437 void set_wait_callback(F f)
Chris@16 2438 {
Chris@16 2439 lazy_init();
Chris@16 2440 future_->set_wait_callback(f,this);
Chris@16 2441 }
Chris@16 2442
Chris@16 2443 };
Chris@16 2444
Chris@16 2445 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
Chris@16 2446 namespace container
Chris@16 2447 {
Chris@16 2448 template <class R, class Alloc>
Chris@16 2449 struct uses_allocator<promise<R> , Alloc> : true_type
Chris@16 2450 {
Chris@16 2451 };
Chris@16 2452 }
Chris@16 2453 #endif
Chris@16 2454
Chris@16 2455 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
Chris@16 2456
Chris@16 2457 namespace detail
Chris@16 2458 {
Chris@16 2459 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 2460 template<typename R>
Chris@16 2461 struct task_base_shared_state;
Chris@16 2462 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2463 template<typename R, typename ...ArgTypes>
Chris@16 2464 struct task_base_shared_state<R(ArgTypes...)>:
Chris@16 2465 #else
Chris@16 2466 template<typename R>
Chris@16 2467 struct task_base_shared_state<R()>:
Chris@16 2468 #endif
Chris@16 2469 #else
Chris@16 2470 template<typename R>
Chris@16 2471 struct task_base_shared_state:
Chris@16 2472 #endif
Chris@16 2473 detail::shared_state<R>
Chris@16 2474 {
Chris@16 2475 bool started;
Chris@16 2476
Chris@16 2477 task_base_shared_state():
Chris@16 2478 started(false)
Chris@16 2479 {}
Chris@16 2480
Chris@16 2481 void reset()
Chris@16 2482 {
Chris@16 2483 started=false;
Chris@16 2484 }
Chris@16 2485 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2486 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
Chris@16 2487 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2488 #else
Chris@16 2489 virtual void do_run()=0;
Chris@16 2490 void run()
Chris@16 2491 #endif
Chris@16 2492 {
Chris@16 2493 {
Chris@16 2494 boost::lock_guard<boost::mutex> lk(this->mutex);
Chris@16 2495 if(started)
Chris@16 2496 {
Chris@16 2497 boost::throw_exception(task_already_started());
Chris@16 2498 }
Chris@16 2499 started=true;
Chris@16 2500 }
Chris@16 2501 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2502 do_run(boost::forward<ArgTypes>(args)...);
Chris@16 2503 #else
Chris@16 2504 do_run();
Chris@16 2505 #endif
Chris@16 2506 }
Chris@16 2507
Chris@16 2508 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2509 virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
Chris@16 2510 void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2511 #else
Chris@16 2512 virtual void do_apply()=0;
Chris@16 2513 void apply()
Chris@16 2514 #endif
Chris@16 2515 {
Chris@16 2516 {
Chris@16 2517 boost::lock_guard<boost::mutex> lk(this->mutex);
Chris@16 2518 if(started)
Chris@16 2519 {
Chris@16 2520 boost::throw_exception(task_already_started());
Chris@16 2521 }
Chris@16 2522 started=true;
Chris@16 2523 }
Chris@16 2524 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2525 do_apply(boost::forward<ArgTypes>(args)...);
Chris@16 2526 #else
Chris@16 2527 do_apply();
Chris@16 2528 #endif
Chris@16 2529 }
Chris@16 2530
Chris@16 2531 void owner_destroyed()
Chris@16 2532 {
Chris@16 2533 boost::unique_lock<boost::mutex> lk(this->mutex);
Chris@16 2534 if(!started)
Chris@16 2535 {
Chris@16 2536 started=true;
Chris@16 2537 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
Chris@16 2538 }
Chris@16 2539 }
Chris@16 2540
Chris@16 2541 };
Chris@16 2542
Chris@16 2543 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 2544 template<typename F, typename R>
Chris@16 2545 struct task_shared_state;
Chris@16 2546 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2547 template<typename F, typename R, typename ...ArgTypes>
Chris@16 2548 struct task_shared_state<F, R(ArgTypes...)>:
Chris@16 2549 task_base_shared_state<R(ArgTypes...)>
Chris@16 2550 #else
Chris@16 2551 template<typename F, typename R>
Chris@16 2552 struct task_shared_state<F, R()>:
Chris@16 2553 task_base_shared_state<R()>
Chris@16 2554 #endif
Chris@16 2555 #else
Chris@16 2556 template<typename F, typename R>
Chris@16 2557 struct task_shared_state:
Chris@16 2558 task_base_shared_state<R>
Chris@16 2559 #endif
Chris@16 2560 {
Chris@16 2561 private:
Chris@16 2562 task_shared_state(task_shared_state&);
Chris@16 2563 public:
Chris@16 2564 F f;
Chris@16 2565 task_shared_state(F const& f_):
Chris@16 2566 f(f_)
Chris@16 2567 {}
Chris@16 2568 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
Chris@16 2569 f(boost::move(f_))
Chris@16 2570 {}
Chris@16 2571
Chris@16 2572 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2573 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2574 {
Chris@16 2575 try
Chris@16 2576 {
Chris@16 2577 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
Chris@16 2578 }
Chris@16 2579 #else
Chris@16 2580 void do_apply()
Chris@16 2581 {
Chris@16 2582 try
Chris@16 2583 {
Chris@16 2584 this->set_value_at_thread_exit(f());
Chris@16 2585 }
Chris@16 2586 #endif
Chris@16 2587 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2588 catch(thread_interrupted& )
Chris@16 2589 {
Chris@16 2590 this->set_interrupted_at_thread_exit();
Chris@16 2591 }
Chris@16 2592 #endif
Chris@16 2593 catch(...)
Chris@16 2594 {
Chris@16 2595 this->set_exception_at_thread_exit(current_exception());
Chris@16 2596 }
Chris@16 2597 }
Chris@16 2598
Chris@16 2599 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2600 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2601 {
Chris@16 2602 try
Chris@16 2603 {
Chris@16 2604 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
Chris@16 2605 }
Chris@16 2606 #else
Chris@16 2607 void do_run()
Chris@16 2608 {
Chris@16 2609 try
Chris@16 2610 {
Chris@16 2611 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2612 R res((f()));
Chris@16 2613 this->mark_finished_with_result(boost::move(res));
Chris@16 2614 #else
Chris@16 2615 this->mark_finished_with_result(f());
Chris@16 2616 #endif
Chris@16 2617 }
Chris@16 2618 #endif
Chris@16 2619 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2620 catch(thread_interrupted& )
Chris@16 2621 {
Chris@16 2622 this->mark_interrupted_finish();
Chris@16 2623 }
Chris@16 2624 #endif
Chris@16 2625 catch(...)
Chris@16 2626 {
Chris@16 2627 this->mark_exceptional_finish();
Chris@16 2628 }
Chris@16 2629 }
Chris@16 2630 };
Chris@16 2631
Chris@16 2632 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 2633 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2634 template<typename F, typename R, typename ...ArgTypes>
Chris@16 2635 struct task_shared_state<F, R&(ArgTypes...)>:
Chris@16 2636 task_base_shared_state<R&(ArgTypes...)>
Chris@16 2637 #else
Chris@16 2638 template<typename F, typename R>
Chris@16 2639 struct task_shared_state<F, R&()>:
Chris@16 2640 task_base_shared_state<R&()>
Chris@16 2641 #endif
Chris@16 2642 #else
Chris@16 2643 template<typename F, typename R>
Chris@16 2644 struct task_shared_state<F,R&>:
Chris@16 2645 task_base_shared_state<R&>
Chris@16 2646 #endif
Chris@16 2647 {
Chris@16 2648 private:
Chris@16 2649 task_shared_state(task_shared_state&);
Chris@16 2650 public:
Chris@16 2651 F f;
Chris@16 2652 task_shared_state(F const& f_):
Chris@16 2653 f(f_)
Chris@16 2654 {}
Chris@16 2655 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
Chris@16 2656 f(boost::move(f_))
Chris@16 2657 {}
Chris@16 2658
Chris@16 2659 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2660 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2661 {
Chris@16 2662 try
Chris@16 2663 {
Chris@16 2664 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
Chris@16 2665 }
Chris@16 2666 #else
Chris@16 2667 void do_apply()
Chris@16 2668 {
Chris@16 2669 try
Chris@16 2670 {
Chris@16 2671 this->set_value_at_thread_exit(f());
Chris@16 2672 }
Chris@16 2673 #endif
Chris@16 2674 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2675 catch(thread_interrupted& )
Chris@16 2676 {
Chris@16 2677 this->set_interrupted_at_thread_exit();
Chris@16 2678 }
Chris@16 2679 #endif
Chris@16 2680 catch(...)
Chris@16 2681 {
Chris@16 2682 this->set_exception_at_thread_exit(current_exception());
Chris@16 2683 }
Chris@16 2684 }
Chris@16 2685
Chris@16 2686 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2687 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2688 {
Chris@16 2689 try
Chris@16 2690 {
Chris@16 2691 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
Chris@16 2692 }
Chris@16 2693 #else
Chris@16 2694 void do_run()
Chris@16 2695 {
Chris@16 2696 try
Chris@16 2697 {
Chris@16 2698 R& res((f()));
Chris@16 2699 this->mark_finished_with_result(res);
Chris@16 2700 }
Chris@16 2701 #endif
Chris@16 2702 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2703 catch(thread_interrupted& )
Chris@16 2704 {
Chris@16 2705 this->mark_interrupted_finish();
Chris@16 2706 }
Chris@16 2707 #endif
Chris@16 2708 catch(...)
Chris@16 2709 {
Chris@16 2710 this->mark_exceptional_finish();
Chris@16 2711 }
Chris@16 2712 }
Chris@16 2713 };
Chris@16 2714
Chris@16 2715 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
Chris@16 2716
Chris@16 2717 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 2718 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2719 template<typename R, typename ...ArgTypes>
Chris@16 2720 struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>:
Chris@16 2721 task_base_shared_state<R(ArgTypes...)>
Chris@16 2722 #else
Chris@16 2723 template<typename R>
Chris@16 2724 struct task_shared_state<R (*)(), R()>:
Chris@16 2725 task_base_shared_state<R()>
Chris@16 2726 #endif
Chris@16 2727 #else
Chris@16 2728 template<typename R>
Chris@16 2729 struct task_shared_state<R (*)(), R> :
Chris@16 2730 task_base_shared_state<R>
Chris@16 2731 #endif
Chris@16 2732 {
Chris@16 2733 private:
Chris@16 2734 task_shared_state(task_shared_state&);
Chris@16 2735 public:
Chris@16 2736 R (*f)();
Chris@16 2737 task_shared_state(R (*f_)()):
Chris@16 2738 f(f_)
Chris@16 2739 {}
Chris@16 2740
Chris@16 2741
Chris@16 2742 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2743 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2744 {
Chris@16 2745 try
Chris@16 2746 {
Chris@16 2747 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
Chris@16 2748 }
Chris@16 2749 #else
Chris@16 2750 void do_apply()
Chris@16 2751 {
Chris@16 2752 try
Chris@16 2753 {
Chris@16 2754 R r((f()));
Chris@16 2755 this->set_value_at_thread_exit(boost::move(r));
Chris@16 2756 }
Chris@16 2757 #endif
Chris@16 2758 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2759 catch(thread_interrupted& )
Chris@16 2760 {
Chris@16 2761 this->set_interrupted_at_thread_exit();
Chris@16 2762 }
Chris@16 2763 #endif
Chris@16 2764 catch(...)
Chris@16 2765 {
Chris@16 2766 this->set_exception_at_thread_exit(current_exception());
Chris@16 2767 }
Chris@16 2768 }
Chris@16 2769
Chris@16 2770
Chris@16 2771 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2772 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2773 {
Chris@16 2774 try
Chris@16 2775 {
Chris@16 2776 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
Chris@16 2777 }
Chris@16 2778 #else
Chris@16 2779 void do_run()
Chris@16 2780 {
Chris@16 2781 try
Chris@16 2782 {
Chris@16 2783 R res((f()));
Chris@16 2784 this->mark_finished_with_result(boost::move(res));
Chris@16 2785 }
Chris@16 2786 #endif
Chris@16 2787 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2788 catch(thread_interrupted& )
Chris@16 2789 {
Chris@16 2790 this->mark_interrupted_finish();
Chris@16 2791 }
Chris@16 2792 #endif
Chris@16 2793 catch(...)
Chris@16 2794 {
Chris@16 2795 this->mark_exceptional_finish();
Chris@16 2796 }
Chris@16 2797 }
Chris@16 2798 };
Chris@16 2799 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 2800 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2801 template<typename R, typename ...ArgTypes>
Chris@16 2802 struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>:
Chris@16 2803 task_base_shared_state<R&(ArgTypes...)>
Chris@16 2804 #else
Chris@16 2805 template<typename R>
Chris@16 2806 struct task_shared_state<R& (*)(), R&()>:
Chris@16 2807 task_base_shared_state<R&()>
Chris@16 2808 #endif
Chris@16 2809 #else
Chris@16 2810 template<typename R>
Chris@16 2811 struct task_shared_state<R& (*)(), R&> :
Chris@16 2812 task_base_shared_state<R&>
Chris@16 2813 #endif
Chris@16 2814 {
Chris@16 2815 private:
Chris@16 2816 task_shared_state(task_shared_state&);
Chris@16 2817 public:
Chris@16 2818 R& (*f)();
Chris@16 2819 task_shared_state(R& (*f_)()):
Chris@16 2820 f(f_)
Chris@16 2821 {}
Chris@16 2822
Chris@16 2823
Chris@16 2824 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2825 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2826 {
Chris@16 2827 try
Chris@16 2828 {
Chris@16 2829 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
Chris@16 2830 }
Chris@16 2831 #else
Chris@16 2832 void do_apply()
Chris@16 2833 {
Chris@16 2834 try
Chris@16 2835 {
Chris@16 2836 this->set_value_at_thread_exit(f());
Chris@16 2837 }
Chris@16 2838 #endif
Chris@16 2839 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2840 catch(thread_interrupted& )
Chris@16 2841 {
Chris@16 2842 this->set_interrupted_at_thread_exit();
Chris@16 2843 }
Chris@16 2844 #endif
Chris@16 2845 catch(...)
Chris@16 2846 {
Chris@16 2847 this->set_exception_at_thread_exit(current_exception());
Chris@16 2848 }
Chris@16 2849 }
Chris@16 2850
Chris@16 2851
Chris@16 2852 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2853 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2854 {
Chris@16 2855 try
Chris@16 2856 {
Chris@16 2857 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
Chris@16 2858 }
Chris@16 2859 #else
Chris@16 2860 void do_run()
Chris@16 2861 {
Chris@16 2862 try
Chris@16 2863 {
Chris@16 2864 this->mark_finished_with_result(f());
Chris@16 2865 }
Chris@16 2866 #endif
Chris@16 2867 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2868 catch(thread_interrupted& )
Chris@16 2869 {
Chris@16 2870 this->mark_interrupted_finish();
Chris@16 2871 }
Chris@16 2872 #endif
Chris@16 2873 catch(...)
Chris@16 2874 {
Chris@16 2875 this->mark_exceptional_finish();
Chris@16 2876 }
Chris@16 2877 }
Chris@16 2878 };
Chris@16 2879 #endif
Chris@16 2880 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 2881 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2882 template<typename F, typename ...ArgTypes>
Chris@16 2883 struct task_shared_state<F, void(ArgTypes...)>:
Chris@16 2884 task_base_shared_state<void(ArgTypes...)>
Chris@16 2885 #else
Chris@16 2886 template<typename F>
Chris@16 2887 struct task_shared_state<F, void()>:
Chris@16 2888 task_base_shared_state<void()>
Chris@16 2889 #endif
Chris@16 2890 #else
Chris@16 2891 template<typename F>
Chris@16 2892 struct task_shared_state<F,void>:
Chris@16 2893 task_base_shared_state<void>
Chris@16 2894 #endif
Chris@16 2895 {
Chris@16 2896 private:
Chris@16 2897 task_shared_state(task_shared_state&);
Chris@16 2898 public:
Chris@16 2899 F f;
Chris@16 2900 task_shared_state(F const& f_):
Chris@16 2901 f(f_)
Chris@16 2902 {}
Chris@16 2903 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
Chris@16 2904 f(boost::move(f_))
Chris@16 2905 {}
Chris@16 2906
Chris@16 2907 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2908 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2909 {
Chris@16 2910 try
Chris@16 2911 {
Chris@16 2912 f(boost::forward<ArgTypes>(args)...);
Chris@16 2913 #else
Chris@16 2914 void do_apply()
Chris@16 2915 {
Chris@16 2916 try
Chris@16 2917 {
Chris@16 2918 f();
Chris@16 2919 #endif
Chris@16 2920 this->set_value_at_thread_exit();
Chris@16 2921 }
Chris@16 2922 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2923 catch(thread_interrupted& )
Chris@16 2924 {
Chris@16 2925 this->set_interrupted_at_thread_exit();
Chris@16 2926 }
Chris@16 2927 #endif
Chris@16 2928 catch(...)
Chris@16 2929 {
Chris@16 2930 this->set_exception_at_thread_exit(current_exception());
Chris@16 2931 }
Chris@16 2932 }
Chris@16 2933
Chris@16 2934 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2935 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2936 {
Chris@16 2937 try
Chris@16 2938 {
Chris@16 2939 f(boost::forward<ArgTypes>(args)...);
Chris@16 2940 #else
Chris@16 2941 void do_run()
Chris@16 2942 {
Chris@16 2943 try
Chris@16 2944 {
Chris@16 2945 f();
Chris@16 2946 #endif
Chris@16 2947 this->mark_finished_with_result();
Chris@16 2948 }
Chris@16 2949 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 2950 catch(thread_interrupted& )
Chris@16 2951 {
Chris@16 2952 this->mark_interrupted_finish();
Chris@16 2953 }
Chris@16 2954 #endif
Chris@16 2955 catch(...)
Chris@16 2956 {
Chris@16 2957 this->mark_exceptional_finish();
Chris@16 2958 }
Chris@16 2959 }
Chris@16 2960 };
Chris@16 2961
Chris@16 2962 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 2963 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2964 template<typename ...ArgTypes>
Chris@16 2965 struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>:
Chris@16 2966 task_base_shared_state<void(ArgTypes...)>
Chris@16 2967 #else
Chris@16 2968 template<>
Chris@16 2969 struct task_shared_state<void (*)(), void()>:
Chris@16 2970 task_base_shared_state<void()>
Chris@16 2971 #endif
Chris@16 2972 #else
Chris@16 2973 template<>
Chris@16 2974 struct task_shared_state<void (*)(),void>:
Chris@16 2975 task_base_shared_state<void>
Chris@16 2976 #endif
Chris@16 2977 {
Chris@16 2978 private:
Chris@16 2979 task_shared_state(task_shared_state&);
Chris@16 2980 public:
Chris@16 2981 void (*f)();
Chris@16 2982 task_shared_state(void (*f_)()):
Chris@16 2983 f(f_)
Chris@16 2984 {}
Chris@16 2985
Chris@16 2986 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 2987 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 2988 {
Chris@16 2989 try
Chris@16 2990 {
Chris@16 2991 f(boost::forward<ArgTypes>(args)...);
Chris@16 2992 #else
Chris@16 2993 void do_apply()
Chris@16 2994 {
Chris@16 2995 try
Chris@16 2996 {
Chris@16 2997 f();
Chris@16 2998 #endif
Chris@16 2999 this->set_value_at_thread_exit();
Chris@16 3000 }
Chris@16 3001 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 3002 catch(thread_interrupted& )
Chris@16 3003 {
Chris@16 3004 this->set_interrupted_at_thread_exit();
Chris@16 3005 }
Chris@16 3006 #endif
Chris@16 3007 catch(...)
Chris@16 3008 {
Chris@16 3009 this->set_exception_at_thread_exit(current_exception());
Chris@16 3010 }
Chris@16 3011 }
Chris@16 3012
Chris@16 3013 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3014 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
Chris@16 3015 {
Chris@16 3016 try
Chris@16 3017 {
Chris@16 3018 f(boost::forward<ArgTypes>(args)...);
Chris@16 3019 #else
Chris@16 3020 void do_run()
Chris@16 3021 {
Chris@16 3022 try
Chris@16 3023 {
Chris@16 3024 f();
Chris@16 3025 #endif
Chris@16 3026 this->mark_finished_with_result();
Chris@16 3027 }
Chris@16 3028 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 3029 catch(thread_interrupted& )
Chris@16 3030 {
Chris@16 3031 this->mark_interrupted_finish();
Chris@16 3032 }
Chris@16 3033 #endif
Chris@16 3034 catch(...)
Chris@16 3035 {
Chris@16 3036 this->mark_exceptional_finish();
Chris@16 3037 }
Chris@16 3038 }
Chris@16 3039 };
Chris@16 3040 }
Chris@16 3041
Chris@16 3042 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3043 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3044 template<typename R, typename ...ArgTypes>
Chris@16 3045 class packaged_task<R(ArgTypes...)>
Chris@16 3046 {
Chris@16 3047 typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr;
Chris@16 3048 boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task;
Chris@16 3049 #else
Chris@16 3050 template<typename R>
Chris@16 3051 class packaged_task<R()>
Chris@16 3052 {
Chris@16 3053 typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr;
Chris@16 3054 boost::shared_ptr<detail::task_base_shared_state<R()> > task;
Chris@16 3055 #endif
Chris@16 3056 #else
Chris@16 3057 template<typename R>
Chris@16 3058 class packaged_task
Chris@16 3059 {
Chris@16 3060 typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr;
Chris@16 3061 boost::shared_ptr<detail::task_base_shared_state<R> > task;
Chris@16 3062 #endif
Chris@16 3063 bool future_obtained;
Chris@16 3064 struct dummy;
Chris@16 3065
Chris@16 3066 public:
Chris@16 3067 typedef R result_type;
Chris@16 3068 BOOST_THREAD_MOVABLE_ONLY(packaged_task)
Chris@16 3069
Chris@16 3070 packaged_task():
Chris@16 3071 future_obtained(false)
Chris@16 3072 {}
Chris@16 3073
Chris@16 3074 // construction and destruction
Chris@16 3075 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
Chris@16 3076
Chris@16 3077 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3078 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3079 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
Chris@16 3080 {
Chris@16 3081 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
Chris@16 3082 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
Chris@16 3083 task= task_ptr(new task_shared_state_type(f, boost::forward<ArgTypes>(args)...));
Chris@16 3084 future_obtained=false;
Chris@16 3085 }
Chris@16 3086 #else
Chris@16 3087 explicit packaged_task(R(*f)())
Chris@16 3088 {
Chris@16 3089 typedef R(*FR)();
Chris@16 3090 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
Chris@16 3091 task= task_ptr(new task_shared_state_type(f));
Chris@16 3092 future_obtained=false;
Chris@16 3093 }
Chris@16 3094 #endif
Chris@16 3095 #else
Chris@16 3096 explicit packaged_task(R(*f)())
Chris@16 3097 {
Chris@16 3098 typedef R(*FR)();
Chris@16 3099 typedef detail::task_shared_state<FR,R> task_shared_state_type;
Chris@16 3100 task= task_ptr(new task_shared_state_type(f));
Chris@16 3101 future_obtained=false;
Chris@16 3102 }
Chris@16 3103 #endif
Chris@16 3104 #endif
Chris@16 3105 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 3106 template <class F>
Chris@16 3107 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
Chris@16 3108 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
Chris@16 3109 )
Chris@16 3110 {
Chris@16 3111 typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
Chris@16 3112 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3113 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3114 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
Chris@16 3115 #else
Chris@16 3116 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
Chris@16 3117 #endif
Chris@16 3118 #else
Chris@16 3119 typedef detail::task_shared_state<FR,R> task_shared_state_type;
Chris@16 3120 #endif
Chris@16 3121 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
Chris@16 3122 future_obtained = false;
Chris@16 3123
Chris@16 3124 }
Chris@16 3125
Chris@16 3126 #else
Chris@16 3127 template <class F>
Chris@16 3128 explicit packaged_task(F const& f
Chris@16 3129 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
Chris@16 3130 )
Chris@16 3131 {
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<F,R(ArgTypes...)> task_shared_state_type;
Chris@16 3135 #else
Chris@16 3136 typedef detail::task_shared_state<F,R()> task_shared_state_type;
Chris@16 3137 #endif
Chris@16 3138 #else
Chris@16 3139 typedef detail::task_shared_state<F,R> task_shared_state_type;
Chris@16 3140 #endif
Chris@16 3141 task = task_ptr(new task_shared_state_type(f));
Chris@16 3142 future_obtained=false;
Chris@16 3143 }
Chris@16 3144 template <class F>
Chris@16 3145 explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
Chris@16 3146 {
Chris@16 3147 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3148 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3149 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
Chris@16 3150 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
Chris@16 3151 #else
Chris@16 3152 typedef detail::task_shared_state<F,R()> task_shared_state_type;
Chris@16 3153 task = task_ptr(new task_shared_state_type(boost::move(f))); // TODO forward
Chris@16 3154 #endif
Chris@16 3155 #else
Chris@16 3156 typedef detail::task_shared_state<F,R> task_shared_state_type;
Chris@16 3157 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
Chris@16 3158 #endif
Chris@16 3159 future_obtained=false;
Chris@16 3160
Chris@16 3161 }
Chris@16 3162 #endif
Chris@16 3163
Chris@16 3164 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
Chris@16 3165 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
Chris@16 3166 template <class Allocator>
Chris@16 3167 packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
Chris@16 3168 {
Chris@16 3169 typedef R(*FR)();
Chris@16 3170 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3171 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3172 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
Chris@16 3173 #else
Chris@16 3174 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
Chris@16 3175 #endif
Chris@16 3176 #else
Chris@16 3177 typedef detail::task_shared_state<FR,R> task_shared_state_type;
Chris@16 3178 #endif
Chris@16 3179 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
Chris@16 3180 A2 a2(a);
Chris@16 3181 typedef thread_detail::allocator_destructor<A2> D;
Chris@16 3182
Chris@16 3183 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
Chris@16 3184 future_obtained = false;
Chris@16 3185 }
Chris@16 3186 #endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
Chris@16 3187
Chris@16 3188 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 3189 template <class F, class Allocator>
Chris@16 3190 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
Chris@16 3191 {
Chris@16 3192 typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
Chris@16 3193 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3194 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3195 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
Chris@16 3196 #else
Chris@16 3197 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
Chris@16 3198 #endif
Chris@16 3199 #else
Chris@16 3200 typedef detail::task_shared_state<FR,R> task_shared_state_type;
Chris@16 3201 #endif
Chris@16 3202 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
Chris@16 3203 A2 a2(a);
Chris@16 3204 typedef thread_detail::allocator_destructor<A2> D;
Chris@16 3205
Chris@16 3206 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
Chris@16 3207 future_obtained = false;
Chris@16 3208 }
Chris@16 3209 #else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 3210 template <class F, class Allocator>
Chris@16 3211 packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
Chris@16 3212 {
Chris@16 3213 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3214 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3215 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
Chris@16 3216 #else
Chris@16 3217 typedef detail::task_shared_state<F,R()> task_shared_state_type;
Chris@16 3218 #endif
Chris@16 3219 #else
Chris@16 3220 typedef detail::task_shared_state<F,R> task_shared_state_type;
Chris@16 3221 #endif
Chris@16 3222 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
Chris@16 3223 A2 a2(a);
Chris@16 3224 typedef thread_detail::allocator_destructor<A2> D;
Chris@16 3225
Chris@16 3226 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
Chris@16 3227 future_obtained = false;
Chris@16 3228 }
Chris@16 3229 template <class F, class Allocator>
Chris@16 3230 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
Chris@16 3231 {
Chris@16 3232 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3233 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3234 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
Chris@16 3235 #else
Chris@16 3236 typedef detail::task_shared_state<F,R()> task_shared_state_type;
Chris@16 3237 #endif
Chris@16 3238 #else
Chris@16 3239 typedef detail::task_shared_state<F,R> task_shared_state_type;
Chris@16 3240 #endif
Chris@16 3241 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
Chris@16 3242 A2 a2(a);
Chris@16 3243 typedef thread_detail::allocator_destructor<A2> D;
Chris@16 3244
Chris@16 3245 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3246 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
Chris@16 3247 #else
Chris@16 3248 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) ); // TODO forward
Chris@16 3249 #endif
Chris@16 3250 future_obtained = false;
Chris@16 3251 }
Chris@16 3252
Chris@16 3253 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 3254 #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
Chris@16 3255
Chris@16 3256 ~packaged_task()
Chris@16 3257 {
Chris@16 3258 if(task)
Chris@16 3259 {
Chris@16 3260 task->owner_destroyed();
Chris@16 3261 }
Chris@16 3262 }
Chris@16 3263
Chris@16 3264 // assignment
Chris@16 3265 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT :
Chris@16 3266 future_obtained(BOOST_THREAD_RV(other).future_obtained)
Chris@16 3267 {
Chris@16 3268 task.swap(BOOST_THREAD_RV(other).task);
Chris@16 3269 BOOST_THREAD_RV(other).future_obtained=false;
Chris@16 3270 }
Chris@16 3271 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
Chris@16 3272 {
Chris@16 3273
Chris@16 3274 // todo use forward
Chris@16 3275 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 3276 packaged_task temp(boost::move(other));
Chris@16 3277 #else
Chris@16 3278 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
Chris@16 3279 #endif
Chris@16 3280 swap(temp);
Chris@16 3281 return *this;
Chris@16 3282 }
Chris@16 3283
Chris@16 3284 void reset()
Chris@16 3285 {
Chris@16 3286 if (!valid())
Chris@16 3287 throw future_error(system::make_error_code(future_errc::no_state));
Chris@16 3288 task->reset();
Chris@16 3289 future_obtained=false;
Chris@16 3290 }
Chris@16 3291
Chris@16 3292 void swap(packaged_task& other) BOOST_NOEXCEPT
Chris@16 3293 {
Chris@16 3294 task.swap(other.task);
Chris@16 3295 std::swap(future_obtained,other.future_obtained);
Chris@16 3296 }
Chris@16 3297 bool valid() const BOOST_NOEXCEPT
Chris@16 3298 {
Chris@16 3299 return task.get()!=0;
Chris@16 3300 }
Chris@16 3301
Chris@16 3302 // result retrieval
Chris@16 3303 BOOST_THREAD_FUTURE<R> get_future()
Chris@16 3304 {
Chris@16 3305 if(!task)
Chris@16 3306 {
Chris@16 3307 boost::throw_exception(task_moved());
Chris@16 3308 }
Chris@16 3309 else if(!future_obtained)
Chris@16 3310 {
Chris@16 3311 future_obtained=true;
Chris@16 3312 return BOOST_THREAD_FUTURE<R>(task);
Chris@16 3313 }
Chris@16 3314 else
Chris@16 3315 {
Chris@16 3316 boost::throw_exception(future_already_retrieved());
Chris@16 3317 }
Chris@16 3318 //return BOOST_THREAD_FUTURE<R>();
Chris@16 3319 }
Chris@16 3320
Chris@16 3321 // execution
Chris@16 3322 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3323 void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args)
Chris@16 3324 {
Chris@16 3325 if(!task)
Chris@16 3326 {
Chris@16 3327 boost::throw_exception(task_moved());
Chris@16 3328 }
Chris@16 3329 task->run(boost::forward<ArgTypes>(args)...);
Chris@16 3330 }
Chris@16 3331 void make_ready_at_thread_exit(ArgTypes... args)
Chris@16 3332 {
Chris@16 3333 if(!task)
Chris@16 3334 {
Chris@16 3335 boost::throw_exception(task_moved());
Chris@16 3336 }
Chris@16 3337 if (task->has_value())
Chris@16 3338 {
Chris@16 3339 boost::throw_exception(promise_already_satisfied());
Chris@16 3340 }
Chris@16 3341 task->apply(boost::forward<ArgTypes>(args)...);
Chris@16 3342 }
Chris@16 3343 #else
Chris@16 3344 void operator()()
Chris@16 3345 {
Chris@16 3346 if(!task)
Chris@16 3347 {
Chris@16 3348 boost::throw_exception(task_moved());
Chris@16 3349 }
Chris@16 3350 task->run();
Chris@16 3351 }
Chris@16 3352 void make_ready_at_thread_exit()
Chris@16 3353 {
Chris@16 3354 if(!task)
Chris@16 3355 {
Chris@16 3356 boost::throw_exception(task_moved());
Chris@16 3357 }
Chris@16 3358 if (task->has_value())
Chris@16 3359 boost::throw_exception(promise_already_satisfied());
Chris@16 3360 task->apply();
Chris@16 3361 }
Chris@16 3362 #endif
Chris@16 3363 template<typename F>
Chris@16 3364 void set_wait_callback(F f)
Chris@16 3365 {
Chris@16 3366 task->set_wait_callback(f,this);
Chris@16 3367 }
Chris@16 3368 };
Chris@16 3369
Chris@16 3370 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
Chris@16 3371 namespace container
Chris@16 3372 {
Chris@16 3373 template <class R, class Alloc>
Chris@16 3374 struct uses_allocator<packaged_task<R>, Alloc>
Chris@16 3375 : public true_type {};
Chris@16 3376 }
Chris@16 3377 #endif
Chris@16 3378
Chris@16 3379 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
Chris@16 3380
Chris@16 3381 namespace detail
Chris@16 3382 {
Chris@16 3383 ////////////////////////////////
Chris@16 3384 // make_future_deferred_shared_state
Chris@16 3385 ////////////////////////////////
Chris@16 3386 template <class Rp, class Fp>
Chris@16 3387 BOOST_THREAD_FUTURE<Rp>
Chris@16 3388 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
Chris@16 3389 {
Chris@16 3390 shared_ptr<future_deferred_shared_state<Rp, Fp> >
Chris@16 3391 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
Chris@16 3392 return BOOST_THREAD_FUTURE<Rp>(h);
Chris@16 3393 }
Chris@16 3394
Chris@16 3395 ////////////////////////////////
Chris@16 3396 // make_future_async_shared_state
Chris@16 3397 ////////////////////////////////
Chris@16 3398 template <class Rp, class Fp>
Chris@16 3399 BOOST_THREAD_FUTURE<Rp>
Chris@16 3400 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
Chris@16 3401 {
Chris@16 3402 shared_ptr<future_async_shared_state<Rp, Fp> >
Chris@16 3403 h(new future_async_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
Chris@16 3404 return BOOST_THREAD_FUTURE<Rp>(h);
Chris@16 3405 }
Chris@16 3406
Chris@16 3407 }
Chris@16 3408
Chris@16 3409 ////////////////////////////////
Chris@16 3410 // template <class F, class... ArgTypes>
Chris@16 3411 // future<R> async(launch policy, F&&, ArgTypes&&...);
Chris@16 3412 ////////////////////////////////
Chris@16 3413
Chris@16 3414 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
Chris@16 3415
Chris@16 3416 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3417 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3418 template <class R, class... ArgTypes>
Chris@16 3419 BOOST_THREAD_FUTURE<R>
Chris@16 3420 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
Chris@16 3421 {
Chris@16 3422 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
Chris@16 3423 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
Chris@16 3424 typedef typename BF::result_type Rp;
Chris@16 3425 #else
Chris@16 3426 template <class R>
Chris@16 3427 BOOST_THREAD_FUTURE<R>
Chris@16 3428 async(launch policy, R(*f)())
Chris@16 3429 {
Chris@16 3430 typedef packaged_task<R()> packaged_task_type;
Chris@16 3431 #endif
Chris@16 3432 #else
Chris@16 3433 template <class R>
Chris@16 3434 BOOST_THREAD_FUTURE<R>
Chris@16 3435 async(launch policy, R(*f)())
Chris@16 3436 {
Chris@16 3437 typedef packaged_task<R> packaged_task_type;
Chris@16 3438 #endif
Chris@16 3439 if (int(policy) & int(launch::async))
Chris@16 3440 {
Chris@16 3441 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3442 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
Chris@16 3443 BF(
Chris@16 3444 thread_detail::decay_copy(boost::forward<F>(f))
Chris@16 3445 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
Chris@16 3446 )
Chris@16 3447 ));
Chris@16 3448 #else
Chris@16 3449 packaged_task_type pt( f );
Chris@16 3450
Chris@16 3451 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
Chris@16 3452 ret.set_async();
Chris@16 3453 boost::thread( boost::move(pt) ).detach();
Chris@16 3454 return ::boost::move(ret);
Chris@16 3455 #endif
Chris@16 3456 }
Chris@16 3457 else if (int(policy) & int(launch::deferred))
Chris@16 3458 {
Chris@16 3459 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3460 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
Chris@16 3461 BF(
Chris@16 3462 thread_detail::decay_copy(boost::forward<F>(f))
Chris@16 3463 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
Chris@16 3464 )
Chris@16 3465 ));
Chris@16 3466 #else
Chris@16 3467 std::terminate();
Chris@16 3468 BOOST_THREAD_FUTURE<R> ret;
Chris@16 3469 return ::boost::move(ret);
Chris@16 3470
Chris@16 3471 #endif
Chris@16 3472 } else {
Chris@16 3473 std::terminate();
Chris@16 3474 BOOST_THREAD_FUTURE<R> ret;
Chris@16 3475 return ::boost::move(ret);
Chris@16 3476 }
Chris@16 3477 }
Chris@16 3478
Chris@16 3479 #endif
Chris@16 3480
Chris@16 3481 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
Chris@16 3482 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3483
Chris@16 3484 template <class F, class ...ArgTypes>
Chris@16 3485 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
Chris@16 3486 typename decay<ArgTypes>::type...
Chris@16 3487 )>::type>
Chris@16 3488 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
Chris@16 3489 {
Chris@16 3490
Chris@16 3491 typedef typename boost::result_of<typename decay<F>::type(
Chris@16 3492 typename decay<ArgTypes>::type...
Chris@16 3493 )>::type R;
Chris@16 3494
Chris@16 3495 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
Chris@16 3496 typedef typename BF::result_type Rp;
Chris@16 3497
Chris@16 3498 #else
Chris@16 3499 template <class F>
Chris@16 3500 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
Chris@16 3501 async(launch policy, BOOST_THREAD_FWD_REF(F) f)
Chris@16 3502 {
Chris@16 3503 typedef typename boost::result_of<typename decay<F>::type()>::type R;
Chris@16 3504 typedef packaged_task<R()> packaged_task_type;
Chris@16 3505
Chris@16 3506 #endif
Chris@16 3507 #else
Chris@16 3508 template <class F>
Chris@16 3509 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
Chris@16 3510 async(launch policy, BOOST_THREAD_FWD_REF(F) f)
Chris@16 3511 {
Chris@16 3512 typedef typename boost::result_of<typename decay<F>::type()>::type R;
Chris@16 3513 typedef packaged_task<R> packaged_task_type;
Chris@16 3514
Chris@16 3515 #endif
Chris@16 3516
Chris@16 3517 if (int(policy) & int(launch::async))
Chris@16 3518 {
Chris@16 3519 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3520 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
Chris@16 3521 BF(
Chris@16 3522 thread_detail::decay_copy(boost::forward<F>(f))
Chris@16 3523 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
Chris@16 3524 )
Chris@16 3525 ));
Chris@16 3526 #else
Chris@16 3527 packaged_task_type pt( boost::forward<F>(f) );
Chris@16 3528
Chris@16 3529 BOOST_THREAD_FUTURE<R> ret = pt.get_future();
Chris@16 3530 ret.set_async();
Chris@16 3531 boost::thread( boost::move(pt) ).detach();
Chris@16 3532 return ::boost::move(ret);
Chris@16 3533 #endif
Chris@16 3534 }
Chris@16 3535 else if (int(policy) & int(launch::deferred))
Chris@16 3536 {
Chris@16 3537 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3538 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
Chris@16 3539 BF(
Chris@16 3540 thread_detail::decay_copy(boost::forward<F>(f))
Chris@16 3541 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
Chris@16 3542 )
Chris@16 3543 ));
Chris@16 3544 #else
Chris@16 3545 std::terminate();
Chris@16 3546 BOOST_THREAD_FUTURE<R> ret;
Chris@16 3547 return ::boost::move(ret);
Chris@16 3548 // return boost::detail::make_future_deferred_shared_state<Rp>(
Chris@16 3549 // BF(
Chris@16 3550 // thread_detail::decay_copy(boost::forward<F>(f))
Chris@16 3551 // )
Chris@16 3552 // );
Chris@16 3553 #endif
Chris@16 3554
Chris@16 3555 } else {
Chris@16 3556 std::terminate();
Chris@16 3557 BOOST_THREAD_FUTURE<R> ret;
Chris@16 3558 return ::boost::move(ret);
Chris@16 3559 }
Chris@16 3560 }
Chris@16 3561
Chris@16 3562 ////////////////////////////////
Chris@16 3563 // template <class F, class... ArgTypes>
Chris@16 3564 // future<R> async(F&&, ArgTypes&&...);
Chris@16 3565 ////////////////////////////////
Chris@16 3566
Chris@16 3567 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
Chris@16 3568
Chris@16 3569 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3570 template <class R, class... ArgTypes>
Chris@16 3571 BOOST_THREAD_FUTURE<R>
Chris@16 3572 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
Chris@16 3573 {
Chris@16 3574 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
Chris@16 3575 }
Chris@16 3576 #else
Chris@16 3577 template <class R>
Chris@16 3578 BOOST_THREAD_FUTURE<R>
Chris@16 3579 async(R(*f)())
Chris@16 3580 {
Chris@16 3581 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
Chris@16 3582 }
Chris@16 3583 #endif
Chris@16 3584 #endif
Chris@16 3585
Chris@16 3586 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
Chris@16 3587 template <class F, class ...ArgTypes>
Chris@16 3588 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
Chris@16 3589 typename decay<ArgTypes>::type...
Chris@16 3590 )>::type>
Chris@16 3591 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
Chris@16 3592 {
Chris@16 3593 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
Chris@16 3594 }
Chris@16 3595 #else
Chris@16 3596 template <class F>
Chris@16 3597 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
Chris@16 3598 async(BOOST_THREAD_RV_REF(F) f)
Chris@16 3599 {
Chris@16 3600 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
Chris@16 3601 }
Chris@16 3602 #endif
Chris@16 3603
Chris@16 3604
Chris@16 3605 ////////////////////////////////
Chris@16 3606 // make_future deprecated
Chris@16 3607 ////////////////////////////////
Chris@16 3608 template <typename T>
Chris@16 3609 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value)
Chris@16 3610 {
Chris@16 3611 typedef typename decay<T>::type future_value_type;
Chris@16 3612 promise<future_value_type> p;
Chris@16 3613 p.set_value(boost::forward<future_value_type>(value));
Chris@16 3614 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
Chris@16 3615 }
Chris@16 3616
Chris@16 3617 #if defined BOOST_THREAD_USES_MOVE
Chris@16 3618 inline BOOST_THREAD_FUTURE<void> make_future()
Chris@16 3619 {
Chris@16 3620 promise<void> p;
Chris@16 3621 p.set_value();
Chris@16 3622 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
Chris@16 3623 }
Chris@16 3624 #endif
Chris@16 3625
Chris@16 3626 ////////////////////////////////
Chris@16 3627 // make_ready_future
Chris@16 3628 ////////////////////////////////
Chris@16 3629 template <typename T>
Chris@16 3630 BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value)
Chris@16 3631 {
Chris@16 3632 typedef typename decay<T>::type future_value_type;
Chris@16 3633 promise<future_value_type> p;
Chris@16 3634 p.set_value(boost::forward<future_value_type>(value));
Chris@16 3635 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
Chris@16 3636 }
Chris@16 3637
Chris@16 3638 #if defined BOOST_THREAD_USES_MOVE
Chris@16 3639 inline BOOST_THREAD_FUTURE<void> make_ready_future()
Chris@16 3640 {
Chris@16 3641 promise<void> p;
Chris@16 3642 p.set_value();
Chris@16 3643 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
Chris@16 3644 }
Chris@16 3645 #endif
Chris@16 3646
Chris@16 3647 template <typename T>
Chris@16 3648 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex)
Chris@16 3649 {
Chris@16 3650 promise<T> p;
Chris@16 3651 p.set_exception(ex);
Chris@16 3652 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
Chris@16 3653 }
Chris@16 3654 template <typename T, typename E>
Chris@16 3655 BOOST_THREAD_FUTURE<T> make_ready_future(E ex)
Chris@16 3656 {
Chris@16 3657 promise<T> p;
Chris@16 3658 p.set_exception(boost::copy_exception(ex));
Chris@16 3659 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
Chris@16 3660 }
Chris@16 3661
Chris@16 3662 #if 0
Chris@16 3663 template<typename CLOSURE>
Chris@16 3664 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
Chris@16 3665 typedef decltype(closure()) T;
Chris@16 3666 promise<T> p;
Chris@16 3667 try
Chris@16 3668 {
Chris@16 3669 p.set_value(closure());
Chris@16 3670 }
Chris@16 3671 catch(...)
Chris@16 3672 {
Chris@16 3673 p.set_exception(std::current_exception());
Chris@16 3674 }
Chris@16 3675 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
Chris@16 3676 }
Chris@16 3677 #endif
Chris@16 3678
Chris@16 3679 ////////////////////////////////
Chris@16 3680 // make_shared_future deprecated
Chris@16 3681 ////////////////////////////////
Chris@16 3682 template <typename T>
Chris@16 3683 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value)
Chris@16 3684 {
Chris@16 3685 typedef typename decay<T>::type future_type;
Chris@16 3686 promise<future_type> p;
Chris@16 3687 p.set_value(boost::forward<T>(value));
Chris@16 3688 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
Chris@16 3689 }
Chris@16 3690
Chris@16 3691
Chris@16 3692 inline shared_future<void> make_shared_future()
Chris@16 3693 {
Chris@16 3694 promise<void> p;
Chris@16 3695 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
Chris@16 3696
Chris@16 3697 }
Chris@16 3698
Chris@16 3699 // ////////////////////////////////
Chris@16 3700 // // make_ready_shared_future
Chris@16 3701 // ////////////////////////////////
Chris@16 3702 // template <typename T>
Chris@16 3703 // shared_future<typename decay<T>::type> make_ready_shared_future(BOOST_THREAD_FWD_REF(T) value)
Chris@16 3704 // {
Chris@16 3705 // typedef typename decay<T>::type future_type;
Chris@16 3706 // promise<future_type> p;
Chris@16 3707 // p.set_value(boost::forward<T>(value));
Chris@16 3708 // return p.get_future().share();
Chris@16 3709 // }
Chris@16 3710 //
Chris@16 3711 //
Chris@16 3712 // inline shared_future<void> make_ready_shared_future()
Chris@16 3713 // {
Chris@16 3714 // promise<void> p;
Chris@16 3715 // return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
Chris@16 3716 //
Chris@16 3717 // }
Chris@16 3718 //
Chris@16 3719 // ////////////////////////////////
Chris@16 3720 // // make_exceptional_shared_future
Chris@16 3721 // ////////////////////////////////
Chris@16 3722 // template <typename T>
Chris@16 3723 // shared_future<T> make_exceptional_shared_future(exception_ptr ex)
Chris@16 3724 // {
Chris@16 3725 // promise<T> p;
Chris@16 3726 // p.set_exception(ex);
Chris@16 3727 // return p.get_future().share();
Chris@16 3728 // }
Chris@16 3729
Chris@16 3730 ////////////////////////////////
Chris@16 3731 // detail::future_async_continuation_shared_state
Chris@16 3732 ////////////////////////////////
Chris@16 3733 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
Chris@16 3734 namespace detail
Chris@16 3735 {
Chris@16 3736
Chris@16 3737 /////////////////////////
Chris@16 3738 /// future_async_continuation_shared_state
Chris@16 3739 /////////////////////////
Chris@16 3740
Chris@16 3741 template<typename F, typename Rp, typename Fp>
Chris@16 3742 struct future_async_continuation_shared_state: future_async_shared_state_base<Rp>
Chris@16 3743 {
Chris@16 3744 F parent;
Chris@16 3745 Fp continuation;
Chris@16 3746
Chris@16 3747 public:
Chris@16 3748 future_async_continuation_shared_state(
Chris@16 3749 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
Chris@16 3750 ) :
Chris@16 3751 parent(boost::move(f)),
Chris@16 3752 continuation(boost::move(c))
Chris@16 3753 {
Chris@16 3754 }
Chris@16 3755
Chris@16 3756 void launch_continuation(boost::unique_lock<boost::mutex>& lock)
Chris@16 3757 {
Chris@16 3758 lock.unlock();
Chris@16 3759 this->thr_ = thread(&future_async_continuation_shared_state::run, this);
Chris@16 3760 }
Chris@16 3761
Chris@16 3762 static void run(future_async_continuation_shared_state* that)
Chris@16 3763 {
Chris@16 3764 try
Chris@16 3765 {
Chris@16 3766 that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
Chris@16 3767 }
Chris@16 3768 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 3769 catch(thread_interrupted& )
Chris@16 3770 {
Chris@16 3771 that->mark_interrupted_finish();
Chris@16 3772 }
Chris@16 3773 #endif
Chris@16 3774 catch(...)
Chris@16 3775 {
Chris@16 3776 that->mark_exceptional_finish();
Chris@16 3777 }
Chris@16 3778 }
Chris@16 3779 ~future_async_continuation_shared_state()
Chris@16 3780 {
Chris@16 3781 this->join();
Chris@16 3782 }
Chris@16 3783 };
Chris@16 3784
Chris@16 3785 template<typename F, typename Fp>
Chris@16 3786 struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void>
Chris@16 3787 {
Chris@16 3788 F parent;
Chris@16 3789 Fp continuation;
Chris@16 3790
Chris@16 3791 public:
Chris@16 3792 future_async_continuation_shared_state(
Chris@16 3793 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
Chris@16 3794 ) :
Chris@16 3795 parent(boost::move(f)),
Chris@16 3796 continuation(boost::move(c))
Chris@16 3797 {
Chris@16 3798 }
Chris@16 3799
Chris@16 3800 void launch_continuation(boost::unique_lock<boost::mutex>& lk)
Chris@16 3801 {
Chris@16 3802 lk.unlock();
Chris@16 3803 this->thr_ = thread(&future_async_continuation_shared_state::run, this);
Chris@16 3804 }
Chris@16 3805
Chris@16 3806 static void run(future_async_continuation_shared_state* that)
Chris@16 3807 {
Chris@16 3808 try
Chris@16 3809 {
Chris@16 3810 that->continuation(boost::move(that->parent));
Chris@16 3811 that->mark_finished_with_result();
Chris@16 3812 }
Chris@16 3813 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 3814 catch(thread_interrupted& )
Chris@16 3815 {
Chris@16 3816 that->mark_interrupted_finish();
Chris@16 3817 }
Chris@16 3818 #endif
Chris@16 3819 catch(...)
Chris@16 3820 {
Chris@16 3821 that->mark_exceptional_finish();
Chris@16 3822 }
Chris@16 3823 }
Chris@16 3824 ~future_async_continuation_shared_state()
Chris@16 3825 {
Chris@16 3826 this->join();
Chris@16 3827 }
Chris@16 3828 };
Chris@16 3829
Chris@16 3830
Chris@16 3831 //////////////////////////
Chris@16 3832 /// future_deferred_continuation_shared_state
Chris@16 3833 //////////////////////////
Chris@16 3834 template<typename F, typename Rp, typename Fp>
Chris@16 3835 struct future_deferred_continuation_shared_state: shared_state<Rp>
Chris@16 3836 {
Chris@16 3837 F parent;
Chris@16 3838 Fp continuation;
Chris@16 3839
Chris@16 3840 public:
Chris@16 3841 future_deferred_continuation_shared_state(
Chris@16 3842 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
Chris@16 3843 ) :
Chris@16 3844 parent(boost::move(f)),
Chris@16 3845 continuation(boost::move(c))
Chris@16 3846 {
Chris@16 3847 this->set_deferred();
Chris@16 3848 }
Chris@16 3849
Chris@16 3850 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
Chris@16 3851 {
Chris@16 3852 execute(lk);
Chris@16 3853 }
Chris@16 3854
Chris@16 3855 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
Chris@16 3856 try
Chris@16 3857 {
Chris@16 3858 Fp local_fuct=boost::move(continuation);
Chris@16 3859 F ftmp = boost::move(parent);
Chris@16 3860 relocker relock(lck);
Chris@16 3861 Rp res = local_fuct(boost::move(ftmp));
Chris@16 3862 relock.lock();
Chris@16 3863 this->mark_finished_with_result_internal(boost::move(res), lck);
Chris@16 3864 }
Chris@16 3865 catch (...)
Chris@16 3866 {
Chris@16 3867 this->mark_exceptional_finish_internal(current_exception(), lck);
Chris@16 3868 }
Chris@16 3869 }
Chris@16 3870 };
Chris@16 3871
Chris@16 3872 template<typename F, typename Fp>
Chris@16 3873 struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void>
Chris@16 3874 {
Chris@16 3875 F parent;
Chris@16 3876 Fp continuation;
Chris@16 3877
Chris@16 3878 public:
Chris@16 3879 future_deferred_continuation_shared_state(
Chris@16 3880 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
Chris@16 3881 ):
Chris@16 3882 parent(boost::move(f)),
Chris@16 3883 continuation(boost::move(c))
Chris@16 3884 {
Chris@16 3885 this->set_deferred();
Chris@16 3886 }
Chris@16 3887
Chris@16 3888 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
Chris@16 3889 {
Chris@16 3890 execute(lk);
Chris@16 3891 }
Chris@16 3892 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
Chris@16 3893 try
Chris@16 3894 {
Chris@16 3895 Fp local_fuct=boost::move(continuation);
Chris@16 3896 F ftmp = boost::move(parent);
Chris@16 3897 relocker relock(lck);
Chris@16 3898 local_fuct(boost::move(ftmp));
Chris@16 3899 relock.lock();
Chris@16 3900 this->mark_finished_with_result_internal(lck);
Chris@16 3901 }
Chris@16 3902 catch (...)
Chris@16 3903 {
Chris@16 3904 this->mark_exceptional_finish_internal(current_exception(), lck);
Chris@16 3905 }
Chris@16 3906 }
Chris@16 3907 };
Chris@16 3908
Chris@16 3909 ////////////////////////////////
Chris@16 3910 // make_future_deferred_continuation_shared_state
Chris@16 3911 ////////////////////////////////
Chris@16 3912 template<typename F, typename Rp, typename Fp>
Chris@16 3913 BOOST_THREAD_FUTURE<Rp>
Chris@16 3914 make_future_deferred_continuation_shared_state(
Chris@16 3915 boost::unique_lock<boost::mutex> &lock,
Chris@16 3916 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
Chris@16 3917 )
Chris@16 3918 {
Chris@16 3919 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> >
Chris@16 3920 h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
Chris@16 3921 h->parent.future_->set_continuation_ptr(h, lock);
Chris@16 3922 return BOOST_THREAD_FUTURE<Rp>(h);
Chris@16 3923 }
Chris@16 3924
Chris@16 3925 ////////////////////////////////
Chris@16 3926 // make_future_async_continuation_shared_state
Chris@16 3927 ////////////////////////////////
Chris@16 3928 template<typename F, typename Rp, typename Fp>
Chris@16 3929 BOOST_THREAD_FUTURE<Rp>
Chris@16 3930 make_future_async_continuation_shared_state(
Chris@16 3931 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
Chris@16 3932 )
Chris@16 3933 {
Chris@16 3934 shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> >
Chris@16 3935 h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
Chris@16 3936 h->parent.future_->set_continuation_ptr(h, lock);
Chris@16 3937
Chris@16 3938 return BOOST_THREAD_FUTURE<Rp>(h);
Chris@16 3939 }
Chris@16 3940
Chris@16 3941 }
Chris@16 3942
Chris@16 3943 ////////////////////////////////
Chris@16 3944 // template<typename F>
Chris@16 3945 // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
Chris@16 3946 ////////////////////////////////
Chris@16 3947
Chris@16 3948 template <typename R>
Chris@16 3949 template <typename F>
Chris@16 3950 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
Chris@16 3951 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func)
Chris@16 3952 {
Chris@16 3953
Chris@16 3954 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
Chris@16 3955 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
Chris@16 3956
Chris@16 3957 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
Chris@16 3958 if (int(policy) & int(launch::async))
Chris@16 3959 {
Chris@16 3960 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
Chris@16 3961 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 3962 )));
Chris@16 3963 }
Chris@16 3964 else if (int(policy) & int(launch::deferred))
Chris@16 3965 {
Chris@16 3966 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
Chris@16 3967 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 3968 )));
Chris@16 3969 }
Chris@16 3970 else
Chris@16 3971 {
Chris@16 3972 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
Chris@16 3973 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 3974 )));
Chris@16 3975
Chris@16 3976 }
Chris@16 3977
Chris@16 3978 }
Chris@16 3979 template <typename R>
Chris@16 3980 template <typename F>
Chris@16 3981 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
Chris@16 3982 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func)
Chris@16 3983 {
Chris@16 3984
Chris@16 3985 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
Chris@16 3986 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
Chris@16 3987
Chris@16 3988 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
Chris@16 3989 if (int(this->launch_policy(lock)) & int(launch::async))
Chris@16 3990 {
Chris@16 3991 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
Chris@16 3992 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 3993 );
Chris@16 3994 }
Chris@16 3995 else if (int(this->launch_policy(lock)) & int(launch::deferred))
Chris@16 3996 {
Chris@16 3997 this->future_->wait_internal(lock);
Chris@16 3998 return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
Chris@16 3999 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 4000 );
Chris@16 4001 }
Chris@16 4002 else
Chris@16 4003 {
Chris@16 4004 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
Chris@16 4005 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 4006 );
Chris@16 4007 }
Chris@16 4008 }
Chris@16 4009
Chris@16 4010
Chris@16 4011 //#if 0 && defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
Chris@16 4012 // template <typename R>
Chris@16 4013 // template<typename RF>
Chris@16 4014 // BOOST_THREAD_FUTURE<RF>
Chris@16 4015 // BOOST_THREAD_FUTURE<R>::then(RF(*func)(BOOST_THREAD_FUTURE<R>&))
Chris@16 4016 // {
Chris@16 4017 //
Chris@16 4018 // typedef RF future_type;
Chris@16 4019 //
Chris@16 4020 // if (this->future_)
Chris@16 4021 // {
Chris@16 4022 // boost::unique_lock<boost::mutex> lock(this->future_->mutex);
Chris@16 4023 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
Chris@16 4024 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func);
Chris@16 4025 // if (ptr==0)
Chris@16 4026 // {
Chris@16 4027 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
Chris@16 4028 // }
Chris@16 4029 // this->future_->set_continuation_ptr(ptr, lock);
Chris@16 4030 // return ptr->get_future();
Chris@16 4031 // } else {
Chris@16 4032 // // fixme what to do when the future has no associated state?
Chris@16 4033 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
Chris@16 4034 // }
Chris@16 4035 //
Chris@16 4036 // }
Chris@16 4037 // template <typename R>
Chris@16 4038 // template<typename RF>
Chris@16 4039 // BOOST_THREAD_FUTURE<RF>
Chris@16 4040 // BOOST_THREAD_FUTURE<R>::then(launch policy, RF(*func)(BOOST_THREAD_FUTURE<R>&))
Chris@16 4041 // {
Chris@16 4042 //
Chris@16 4043 // typedef RF future_type;
Chris@16 4044 //
Chris@16 4045 // if (this->future_)
Chris@16 4046 // {
Chris@16 4047 // boost::unique_lock<boost::mutex> lock(this->future_->mutex);
Chris@16 4048 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
Chris@16 4049 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func, policy);
Chris@16 4050 // if (ptr==0)
Chris@16 4051 // {
Chris@16 4052 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
Chris@16 4053 // }
Chris@16 4054 // this->future_->set_continuation_ptr(ptr, lock);
Chris@16 4055 // return ptr->get_future();
Chris@16 4056 // } else {
Chris@16 4057 // // fixme what to do when the future has no associated state?
Chris@16 4058 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
Chris@16 4059 // }
Chris@16 4060 //
Chris@16 4061 // }
Chris@16 4062 //#endif
Chris@16 4063
Chris@16 4064 template <typename R>
Chris@16 4065 template <typename F>
Chris@16 4066 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
Chris@16 4067 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func)
Chris@16 4068 {
Chris@16 4069
Chris@16 4070 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
Chris@16 4071 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
Chris@16 4072
Chris@16 4073 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
Chris@16 4074 if (int(policy) & int(launch::async))
Chris@16 4075 {
Chris@16 4076 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
Chris@16 4077 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 4078 )));
Chris@16 4079 }
Chris@16 4080 else if (int(policy) & int(launch::deferred))
Chris@16 4081 {
Chris@16 4082 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
Chris@16 4083 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 4084 )));
Chris@16 4085 }
Chris@16 4086 else
Chris@16 4087 {
Chris@16 4088 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
Chris@16 4089 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 4090 )));
Chris@16 4091 }
Chris@16 4092
Chris@16 4093 }
Chris@16 4094 template <typename R>
Chris@16 4095 template <typename F>
Chris@16 4096 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
Chris@16 4097 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func)
Chris@16 4098 {
Chris@16 4099
Chris@16 4100 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
Chris@16 4101
Chris@16 4102 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
Chris@16 4103
Chris@16 4104 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
Chris@16 4105 if (int(this->launch_policy(lock)) & int(launch::async))
Chris@16 4106 {
Chris@16 4107 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
Chris@16 4108 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 4109 );
Chris@16 4110 }
Chris@16 4111 else if (int(this->launch_policy(lock)) & int(launch::deferred))
Chris@16 4112 {
Chris@16 4113 this->future_->wait_internal(lock);
Chris@16 4114 return boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
Chris@16 4115 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 4116 );
Chris@16 4117 }
Chris@16 4118 else
Chris@16 4119 {
Chris@16 4120 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
Chris@16 4121 lock, boost::move(*this), boost::forward<F>(func)
Chris@16 4122 );
Chris@16 4123 }
Chris@16 4124 }
Chris@16 4125 namespace detail
Chris@16 4126 {
Chris@16 4127 template <typename T>
Chris@16 4128 struct mfallbacker_to
Chris@16 4129 {
Chris@16 4130 T value_;
Chris@16 4131 typedef T result_type;
Chris@16 4132 mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
Chris@16 4133 : value_(boost::move(v))
Chris@16 4134 {}
Chris@16 4135
Chris@16 4136 T operator()(BOOST_THREAD_FUTURE<T> fut)
Chris@16 4137 {
Chris@16 4138 return fut.get_or(boost::move(value_));
Chris@16 4139
Chris@16 4140 }
Chris@16 4141 };
Chris@16 4142 template <typename T>
Chris@16 4143 struct cfallbacker_to
Chris@16 4144 {
Chris@16 4145 T value_;
Chris@16 4146 typedef T result_type;
Chris@16 4147 cfallbacker_to(T const& v)
Chris@16 4148 : value_(v)
Chris@16 4149 {}
Chris@16 4150
Chris@16 4151 T operator()(BOOST_THREAD_FUTURE<T> fut)
Chris@16 4152 {
Chris@16 4153 return fut.get_or(value_);
Chris@16 4154
Chris@16 4155 }
Chris@16 4156 };
Chris@16 4157 }
Chris@16 4158 ////////////////////////////////
Chris@16 4159 // future<R> future<R>::fallback_to(R&& v);
Chris@16 4160 ////////////////////////////////
Chris@16 4161
Chris@16 4162 template <typename R>
Chris@16 4163 template <typename R2>
Chris@16 4164 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
Chris@16 4165 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v)
Chris@16 4166 {
Chris@16 4167 return then(detail::mfallbacker_to<R>(boost::move(v)));
Chris@16 4168 }
Chris@16 4169
Chris@16 4170 template <typename R>
Chris@16 4171 template <typename R2>
Chris@16 4172 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
Chris@16 4173 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v)
Chris@16 4174 {
Chris@16 4175 return then(detail::cfallbacker_to<R>(v));
Chris@16 4176 }
Chris@16 4177
Chris@16 4178 #endif
Chris@16 4179
Chris@16 4180 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
Chris@16 4181 namespace detail
Chris@16 4182 {
Chris@16 4183
Chris@16 4184 /////////////////////////
Chris@16 4185 /// future_unwrap_shared_state
Chris@16 4186 /////////////////////////
Chris@16 4187
Chris@16 4188 template<typename F, typename Rp>
Chris@16 4189 struct future_unwrap_shared_state: shared_state<Rp>
Chris@16 4190 {
Chris@16 4191 F parent;
Chris@16 4192 public:
Chris@16 4193 explicit future_unwrap_shared_state(
Chris@16 4194 BOOST_THREAD_RV_REF(F) f
Chris@16 4195 ) :
Chris@16 4196 parent(boost::move(f))
Chris@16 4197 {
Chris@16 4198 }
Chris@16 4199 virtual void wait(bool ) // todo see if rethrow must be used
Chris@16 4200 {
Chris@16 4201 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 4202 parent.get().wait();
Chris@16 4203 }
Chris@16 4204 virtual Rp get()
Chris@16 4205 {
Chris@16 4206 boost::unique_lock<boost::mutex> lock(mutex);
Chris@16 4207 return parent.get().get();
Chris@16 4208 }
Chris@16 4209
Chris@16 4210 };
Chris@16 4211
Chris@16 4212 template <class F, class Rp>
Chris@16 4213 BOOST_THREAD_FUTURE<Rp>
Chris@16 4214 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f)
Chris@16 4215 {
Chris@16 4216 shared_ptr<future_unwrap_shared_state<F, Rp> >
Chris@16 4217 h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
Chris@16 4218 h->parent.future_->set_continuation_ptr(h, lock);
Chris@16 4219 return BOOST_THREAD_FUTURE<Rp>(h);
Chris@16 4220 }
Chris@16 4221 }
Chris@16 4222
Chris@16 4223 template <typename R>
Chris@16 4224 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other):
Chris@16 4225 base_type(other.unwrap())
Chris@16 4226 {
Chris@16 4227 }
Chris@16 4228
Chris@16 4229 template <typename R2>
Chris@16 4230 BOOST_THREAD_FUTURE<R2>
Chris@16 4231 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
Chris@16 4232 {
Chris@16 4233 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
Chris@16 4234 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
Chris@16 4235 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
Chris@16 4236 }
Chris@16 4237 #endif
Chris@16 4238 }
Chris@16 4239
Chris@16 4240 #endif // BOOST_NO_EXCEPTION
Chris@16 4241 #endif // header