/Src/Dependencies/Boost/boost/thread/future.hpp

http://hadesmem.googlecode.com/ · C++ Header · 1383 lines · 1166 code · 190 blank · 27 comment · 63 complexity · f96b20aff35d05ba065aca7abae43f40 MD5 · raw file

  1. // (C) Copyright 2008-10 Anthony Williams
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_THREAD_FUTURE_HPP
  7. #define BOOST_THREAD_FUTURE_HPP
  8. #include <stdexcept>
  9. #include <boost/thread/detail/move.hpp>
  10. #include <boost/thread/thread_time.hpp>
  11. #include <boost/thread/mutex.hpp>
  12. #include <boost/thread/condition_variable.hpp>
  13. #include <boost/exception_ptr.hpp>
  14. #include <boost/shared_ptr.hpp>
  15. #include <boost/scoped_ptr.hpp>
  16. #include <boost/type_traits/is_fundamental.hpp>
  17. #include <boost/type_traits/is_convertible.hpp>
  18. #include <boost/mpl/if.hpp>
  19. #include <boost/config.hpp>
  20. #include <boost/throw_exception.hpp>
  21. #include <algorithm>
  22. #include <boost/function.hpp>
  23. #include <boost/bind.hpp>
  24. #include <boost/ref.hpp>
  25. #include <boost/scoped_array.hpp>
  26. #include <boost/utility/enable_if.hpp>
  27. #include <list>
  28. #include <boost/next_prior.hpp>
  29. #include <vector>
  30. namespace boost
  31. {
  32. class future_uninitialized:
  33. public std::logic_error
  34. {
  35. public:
  36. future_uninitialized():
  37. std::logic_error("Future Uninitialized")
  38. {}
  39. };
  40. class broken_promise:
  41. public std::logic_error
  42. {
  43. public:
  44. broken_promise():
  45. std::logic_error("Broken promise")
  46. {}
  47. };
  48. class future_already_retrieved:
  49. public std::logic_error
  50. {
  51. public:
  52. future_already_retrieved():
  53. std::logic_error("Future already retrieved")
  54. {}
  55. };
  56. class promise_already_satisfied:
  57. public std::logic_error
  58. {
  59. public:
  60. promise_already_satisfied():
  61. std::logic_error("Promise already satisfied")
  62. {}
  63. };
  64. class task_already_started:
  65. public std::logic_error
  66. {
  67. public:
  68. task_already_started():
  69. std::logic_error("Task already started")
  70. {}
  71. };
  72. class task_moved:
  73. public std::logic_error
  74. {
  75. public:
  76. task_moved():
  77. std::logic_error("Task moved")
  78. {}
  79. };
  80. namespace future_state
  81. {
  82. enum state { uninitialized, waiting, ready, moved };
  83. }
  84. namespace detail
  85. {
  86. struct future_object_base
  87. {
  88. boost::exception_ptr exception;
  89. bool done;
  90. boost::mutex mutex;
  91. boost::condition_variable waiters;
  92. typedef std::list<boost::condition_variable_any*> waiter_list;
  93. waiter_list external_waiters;
  94. boost::function<void()> callback;
  95. future_object_base():
  96. done(false)
  97. {}
  98. virtual ~future_object_base()
  99. {}
  100. waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
  101. {
  102. boost::unique_lock<boost::mutex> lock(mutex);
  103. do_callback(lock);
  104. return external_waiters.insert(external_waiters.end(),&cv);
  105. }
  106. void remove_external_waiter(waiter_list::iterator it)
  107. {
  108. boost::lock_guard<boost::mutex> lock(mutex);
  109. external_waiters.erase(it);
  110. }
  111. void mark_finished_internal()
  112. {
  113. done=true;
  114. waiters.notify_all();
  115. for(waiter_list::const_iterator it=external_waiters.begin(),
  116. end=external_waiters.end();it!=end;++it)
  117. {
  118. (*it)->notify_all();
  119. }
  120. }
  121. struct relocker
  122. {
  123. boost::unique_lock<boost::mutex>& lock;
  124. relocker(boost::unique_lock<boost::mutex>& lock_):
  125. lock(lock_)
  126. {
  127. lock.unlock();
  128. }
  129. ~relocker()
  130. {
  131. lock.lock();
  132. }
  133. private:
  134. relocker& operator=(relocker const&);
  135. };
  136. void do_callback(boost::unique_lock<boost::mutex>& lock)
  137. {
  138. if(callback && !done)
  139. {
  140. boost::function<void()> local_callback=callback;
  141. relocker relock(lock);
  142. local_callback();
  143. }
  144. }
  145. void wait(bool rethrow=true)
  146. {
  147. boost::unique_lock<boost::mutex> lock(mutex);
  148. do_callback(lock);
  149. while(!done)
  150. {
  151. waiters.wait(lock);
  152. }
  153. if(rethrow && exception)
  154. {
  155. boost::rethrow_exception(exception);
  156. }
  157. }
  158. bool timed_wait_until(boost::system_time const& target_time)
  159. {
  160. boost::unique_lock<boost::mutex> lock(mutex);
  161. do_callback(lock);
  162. while(!done)
  163. {
  164. bool const success=waiters.timed_wait(lock,target_time);
  165. if(!success && !done)
  166. {
  167. return false;
  168. }
  169. }
  170. return true;
  171. }
  172. void mark_exceptional_finish_internal(boost::exception_ptr const& e)
  173. {
  174. exception=e;
  175. mark_finished_internal();
  176. }
  177. void mark_exceptional_finish()
  178. {
  179. boost::lock_guard<boost::mutex> lock(mutex);
  180. mark_exceptional_finish_internal(boost::current_exception());
  181. }
  182. bool has_value()
  183. {
  184. boost::lock_guard<boost::mutex> lock(mutex);
  185. return done && !exception;
  186. }
  187. bool has_exception()
  188. {
  189. boost::lock_guard<boost::mutex> lock(mutex);
  190. return done && exception;
  191. }
  192. template<typename F,typename U>
  193. void set_wait_callback(F f,U* u)
  194. {
  195. callback=boost::bind(f,boost::ref(*u));
  196. }
  197. private:
  198. future_object_base(future_object_base const&);
  199. future_object_base& operator=(future_object_base const&);
  200. };
  201. template<typename T>
  202. struct future_traits
  203. {
  204. typedef boost::scoped_ptr<T> storage_type;
  205. #ifndef BOOST_NO_RVALUE_REFERENCES
  206. typedef T const& source_reference_type;
  207. struct dummy;
  208. typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type;
  209. typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,T&&>::type move_dest_type;
  210. #else
  211. typedef T& source_reference_type;
  212. typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T const&>::type rvalue_source_type;
  213. typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T>::type move_dest_type;
  214. #endif
  215. static void init(storage_type& storage,source_reference_type t)
  216. {
  217. storage.reset(new T(t));
  218. }
  219. static void init(storage_type& storage,rvalue_source_type t)
  220. {
  221. storage.reset(new T(static_cast<rvalue_source_type>(t)));
  222. }
  223. static void cleanup(storage_type& storage)
  224. {
  225. storage.reset();
  226. }
  227. };
  228. template<typename T>
  229. struct future_traits<T&>
  230. {
  231. typedef T* storage_type;
  232. typedef T& source_reference_type;
  233. struct rvalue_source_type
  234. {};
  235. typedef T& move_dest_type;
  236. static void init(storage_type& storage,T& t)
  237. {
  238. storage=&t;
  239. }
  240. static void cleanup(storage_type& storage)
  241. {
  242. storage=0;
  243. }
  244. };
  245. template<>
  246. struct future_traits<void>
  247. {
  248. typedef bool storage_type;
  249. typedef void move_dest_type;
  250. static void init(storage_type& storage)
  251. {
  252. storage=true;
  253. }
  254. static void cleanup(storage_type& storage)
  255. {
  256. storage=false;
  257. }
  258. };
  259. template<typename T>
  260. struct future_object:
  261. detail::future_object_base
  262. {
  263. typedef typename future_traits<T>::storage_type storage_type;
  264. typedef typename future_traits<T>::source_reference_type source_reference_type;
  265. typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
  266. typedef typename future_traits<T>::move_dest_type move_dest_type;
  267. storage_type result;
  268. future_object():
  269. result(0)
  270. {}
  271. void mark_finished_with_result_internal(source_reference_type result_)
  272. {
  273. future_traits<T>::init(result,result_);
  274. mark_finished_internal();
  275. }
  276. void mark_finished_with_result_internal(rvalue_source_type result_)
  277. {
  278. future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
  279. mark_finished_internal();
  280. }
  281. void mark_finished_with_result(source_reference_type result_)
  282. {
  283. boost::lock_guard<boost::mutex> lock(mutex);
  284. mark_finished_with_result_internal(result_);
  285. }
  286. void mark_finished_with_result(rvalue_source_type result_)
  287. {
  288. boost::lock_guard<boost::mutex> lock(mutex);
  289. mark_finished_with_result_internal(result_);
  290. }
  291. move_dest_type get()
  292. {
  293. wait();
  294. return static_cast<move_dest_type>(*result);
  295. }
  296. future_state::state get_state()
  297. {
  298. boost::lock_guard<boost::mutex> guard(mutex);
  299. if(!done)
  300. {
  301. return future_state::waiting;
  302. }
  303. else
  304. {
  305. return future_state::ready;
  306. }
  307. }
  308. private:
  309. future_object(future_object const&);
  310. future_object& operator=(future_object const&);
  311. };
  312. template<>
  313. struct future_object<void>:
  314. detail::future_object_base
  315. {
  316. future_object()
  317. {}
  318. void mark_finished_with_result_internal()
  319. {
  320. mark_finished_internal();
  321. }
  322. void mark_finished_with_result()
  323. {
  324. boost::lock_guard<boost::mutex> lock(mutex);
  325. mark_finished_with_result_internal();
  326. }
  327. void get()
  328. {
  329. wait();
  330. }
  331. future_state::state get_state()
  332. {
  333. boost::lock_guard<boost::mutex> guard(mutex);
  334. if(!done)
  335. {
  336. return future_state::waiting;
  337. }
  338. else
  339. {
  340. return future_state::ready;
  341. }
  342. }
  343. private:
  344. future_object(future_object const&);
  345. future_object& operator=(future_object const&);
  346. };
  347. class future_waiter
  348. {
  349. struct registered_waiter;
  350. typedef std::vector<registered_waiter>::size_type count_type;
  351. struct registered_waiter
  352. {
  353. boost::shared_ptr<detail::future_object_base> future;
  354. detail::future_object_base::waiter_list::iterator wait_iterator;
  355. count_type index;
  356. registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_,
  357. detail::future_object_base::waiter_list::iterator wait_iterator_,
  358. count_type index_):
  359. future(future_),wait_iterator(wait_iterator_),index(index_)
  360. {}
  361. };
  362. struct all_futures_lock
  363. {
  364. count_type count;
  365. boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
  366. all_futures_lock(std::vector<registered_waiter>& futures):
  367. count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
  368. {
  369. for(count_type i=0;i<count;++i)
  370. {
  371. locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex);
  372. }
  373. }
  374. void lock()
  375. {
  376. boost::lock(locks.get(),locks.get()+count);
  377. }
  378. void unlock()
  379. {
  380. for(count_type i=0;i<count;++i)
  381. {
  382. locks[i].unlock();
  383. }
  384. }
  385. };
  386. boost::condition_variable_any cv;
  387. std::vector<registered_waiter> futures;
  388. count_type future_count;
  389. public:
  390. future_waiter():
  391. future_count(0)
  392. {}
  393. template<typename F>
  394. void add(F& f)
  395. {
  396. if(f.future)
  397. {
  398. futures.push_back(registered_waiter(f.future,f.future->register_external_waiter(cv),future_count));
  399. }
  400. ++future_count;
  401. }
  402. count_type wait()
  403. {
  404. all_futures_lock lk(futures);
  405. for(;;)
  406. {
  407. for(count_type i=0;i<futures.size();++i)
  408. {
  409. if(futures[i].future->done)
  410. {
  411. return futures[i].index;
  412. }
  413. }
  414. cv.wait(lk);
  415. }
  416. }
  417. ~future_waiter()
  418. {
  419. for(count_type i=0;i<futures.size();++i)
  420. {
  421. futures[i].future->remove_external_waiter(futures[i].wait_iterator);
  422. }
  423. }
  424. };
  425. }
  426. template <typename R>
  427. class unique_future;
  428. template <typename R>
  429. class shared_future;
  430. template<typename T>
  431. struct is_future_type
  432. {
  433. BOOST_STATIC_CONSTANT(bool, value=false);
  434. };
  435. template<typename T>
  436. struct is_future_type<unique_future<T> >
  437. {
  438. BOOST_STATIC_CONSTANT(bool, value=true);
  439. };
  440. template<typename T>
  441. struct is_future_type<shared_future<T> >
  442. {
  443. BOOST_STATIC_CONSTANT(bool, value=true);
  444. };
  445. template<typename Iterator>
  446. typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
  447. {
  448. for(Iterator current=begin;current!=end;++current)
  449. {
  450. current->wait();
  451. }
  452. }
  453. template<typename F1,typename F2>
  454. typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
  455. {
  456. f1.wait();
  457. f2.wait();
  458. }
  459. template<typename F1,typename F2,typename F3>
  460. void wait_for_all(F1& f1,F2& f2,F3& f3)
  461. {
  462. f1.wait();
  463. f2.wait();
  464. f3.wait();
  465. }
  466. template<typename F1,typename F2,typename F3,typename F4>
  467. void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
  468. {
  469. f1.wait();
  470. f2.wait();
  471. f3.wait();
  472. f4.wait();
  473. }
  474. template<typename F1,typename F2,typename F3,typename F4,typename F5>
  475. void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
  476. {
  477. f1.wait();
  478. f2.wait();
  479. f3.wait();
  480. f4.wait();
  481. f5.wait();
  482. }
  483. template<typename Iterator>
  484. typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
  485. {
  486. if(begin==end)
  487. return end;
  488. detail::future_waiter waiter;
  489. for(Iterator current=begin;current!=end;++current)
  490. {
  491. waiter.add(*current);
  492. }
  493. return boost::next(begin,waiter.wait());
  494. }
  495. template<typename F1,typename F2>
  496. typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2)
  497. {
  498. detail::future_waiter waiter;
  499. waiter.add(f1);
  500. waiter.add(f2);
  501. return waiter.wait();
  502. }
  503. template<typename F1,typename F2,typename F3>
  504. unsigned wait_for_any(F1& f1,F2& f2,F3& f3)
  505. {
  506. detail::future_waiter waiter;
  507. waiter.add(f1);
  508. waiter.add(f2);
  509. waiter.add(f3);
  510. return waiter.wait();
  511. }
  512. template<typename F1,typename F2,typename F3,typename F4>
  513. unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
  514. {
  515. detail::future_waiter waiter;
  516. waiter.add(f1);
  517. waiter.add(f2);
  518. waiter.add(f3);
  519. waiter.add(f4);
  520. return waiter.wait();
  521. }
  522. template<typename F1,typename F2,typename F3,typename F4,typename F5>
  523. unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
  524. {
  525. detail::future_waiter waiter;
  526. waiter.add(f1);
  527. waiter.add(f2);
  528. waiter.add(f3);
  529. waiter.add(f4);
  530. waiter.add(f5);
  531. return waiter.wait();
  532. }
  533. template <typename R>
  534. class promise;
  535. template <typename R>
  536. class packaged_task;
  537. template <typename R>
  538. class unique_future
  539. {
  540. unique_future(unique_future & rhs);// = delete;
  541. unique_future& operator=(unique_future& rhs);// = delete;
  542. typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
  543. future_ptr future;
  544. friend class shared_future<R>;
  545. friend class promise<R>;
  546. friend class packaged_task<R>;
  547. friend class detail::future_waiter;
  548. typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
  549. unique_future(future_ptr future_):
  550. future(future_)
  551. {}
  552. public:
  553. typedef future_state::state state;
  554. unique_future()
  555. {}
  556. ~unique_future()
  557. {}
  558. #ifndef BOOST_NO_RVALUE_REFERENCES
  559. unique_future(unique_future && other)
  560. {
  561. future.swap(other.future);
  562. }
  563. unique_future& operator=(unique_future && other)
  564. {
  565. future=other.future;
  566. other.future.reset();
  567. return *this;
  568. }
  569. #else
  570. unique_future(boost::detail::thread_move_t<unique_future> other):
  571. future(other->future)
  572. {
  573. other->future.reset();
  574. }
  575. unique_future& operator=(boost::detail::thread_move_t<unique_future> other)
  576. {
  577. future=other->future;
  578. other->future.reset();
  579. return *this;
  580. }
  581. operator boost::detail::thread_move_t<unique_future>()
  582. {
  583. return boost::detail::thread_move_t<unique_future>(*this);
  584. }
  585. #endif
  586. void swap(unique_future& other)
  587. {
  588. future.swap(other.future);
  589. }
  590. // retrieving the value
  591. move_dest_type get()
  592. {
  593. if(!future)
  594. {
  595. boost::throw_exception(future_uninitialized());
  596. }
  597. return future->get();
  598. }
  599. // functions to check state, and wait for ready
  600. state get_state() const
  601. {
  602. if(!future)
  603. {
  604. return future_state::uninitialized;
  605. }
  606. return future->get_state();
  607. }
  608. bool is_ready() const
  609. {
  610. return get_state()==future_state::ready;
  611. }
  612. bool has_exception() const
  613. {
  614. return future && future->has_exception();
  615. }
  616. bool has_value() const
  617. {
  618. return future && future->has_value();
  619. }
  620. void wait() const
  621. {
  622. if(!future)
  623. {
  624. boost::throw_exception(future_uninitialized());
  625. }
  626. future->wait(false);
  627. }
  628. template<typename Duration>
  629. bool timed_wait(Duration const& rel_time) const
  630. {
  631. return timed_wait_until(boost::get_system_time()+rel_time);
  632. }
  633. bool timed_wait_until(boost::system_time const& abs_time) const
  634. {
  635. if(!future)
  636. {
  637. boost::throw_exception(future_uninitialized());
  638. }
  639. return future->timed_wait_until(abs_time);
  640. }
  641. };
  642. template <typename R>
  643. class shared_future
  644. {
  645. typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
  646. future_ptr future;
  647. // shared_future(const unique_future<R>& other);
  648. // shared_future& operator=(const unique_future<R>& other);
  649. friend class detail::future_waiter;
  650. friend class promise<R>;
  651. friend class packaged_task<R>;
  652. shared_future(future_ptr future_):
  653. future(future_)
  654. {}
  655. public:
  656. shared_future(shared_future const& other):
  657. future(other.future)
  658. {}
  659. typedef future_state::state state;
  660. shared_future()
  661. {}
  662. ~shared_future()
  663. {}
  664. shared_future& operator=(shared_future const& other)
  665. {
  666. future=other.future;
  667. return *this;
  668. }
  669. #ifndef BOOST_NO_RVALUE_REFERENCES
  670. shared_future(shared_future && other)
  671. {
  672. future.swap(other.future);
  673. }
  674. shared_future(unique_future<R> && other)
  675. {
  676. future.swap(other.future);
  677. }
  678. shared_future& operator=(shared_future && other)
  679. {
  680. future.swap(other.future);
  681. other.future.reset();
  682. return *this;
  683. }
  684. shared_future& operator=(unique_future<R> && other)
  685. {
  686. future.swap(other.future);
  687. other.future.reset();
  688. return *this;
  689. }
  690. #else
  691. shared_future(boost::detail::thread_move_t<shared_future> other):
  692. future(other->future)
  693. {
  694. other->future.reset();
  695. }
  696. // shared_future(const unique_future<R> &) = delete;
  697. shared_future(boost::detail::thread_move_t<unique_future<R> > other):
  698. future(other->future)
  699. {
  700. other->future.reset();
  701. }
  702. shared_future& operator=(boost::detail::thread_move_t<shared_future> other)
  703. {
  704. future.swap(other->future);
  705. other->future.reset();
  706. return *this;
  707. }
  708. shared_future& operator=(boost::detail::thread_move_t<unique_future<R> > other)
  709. {
  710. future.swap(other->future);
  711. other->future.reset();
  712. return *this;
  713. }
  714. operator boost::detail::thread_move_t<shared_future>()
  715. {
  716. return boost::detail::thread_move_t<shared_future>(*this);
  717. }
  718. #endif
  719. void swap(shared_future& other)
  720. {
  721. future.swap(other.future);
  722. }
  723. // retrieving the value
  724. R get()
  725. {
  726. if(!future)
  727. {
  728. boost::throw_exception(future_uninitialized());
  729. }
  730. return future->get();
  731. }
  732. // functions to check state, and wait for ready
  733. state get_state() const
  734. {
  735. if(!future)
  736. {
  737. return future_state::uninitialized;
  738. }
  739. return future->get_state();
  740. }
  741. bool is_ready() const
  742. {
  743. return get_state()==future_state::ready;
  744. }
  745. bool has_exception() const
  746. {
  747. return future && future->has_exception();
  748. }
  749. bool has_value() const
  750. {
  751. return future && future->has_value();
  752. }
  753. void wait() const
  754. {
  755. if(!future)
  756. {
  757. boost::throw_exception(future_uninitialized());
  758. }
  759. future->wait(false);
  760. }
  761. template<typename Duration>
  762. bool timed_wait(Duration const& rel_time) const
  763. {
  764. return timed_wait_until(boost::get_system_time()+rel_time);
  765. }
  766. bool timed_wait_until(boost::system_time const& abs_time) const
  767. {
  768. if(!future)
  769. {
  770. boost::throw_exception(future_uninitialized());
  771. }
  772. return future->timed_wait_until(abs_time);
  773. }
  774. };
  775. template <typename R>
  776. class promise
  777. {
  778. typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
  779. future_ptr future;
  780. bool future_obtained;
  781. promise(promise & rhs);// = delete;
  782. promise & operator=(promise & rhs);// = delete;
  783. void lazy_init()
  784. {
  785. if(!atomic_load(&future))
  786. {
  787. future_ptr blank;
  788. atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<R>));
  789. }
  790. }
  791. public:
  792. // template <class Allocator> explicit promise(Allocator a);
  793. promise():
  794. future(),future_obtained(false)
  795. {}
  796. ~promise()
  797. {
  798. if(future)
  799. {
  800. boost::lock_guard<boost::mutex> lock(future->mutex);
  801. if(!future->done)
  802. {
  803. future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
  804. }
  805. }
  806. }
  807. // Assignment
  808. #ifndef BOOST_NO_RVALUE_REFERENCES
  809. promise(promise && rhs):
  810. future_obtained(rhs.future_obtained)
  811. {
  812. future.swap(rhs.future);
  813. rhs.future_obtained=false;
  814. }
  815. promise & operator=(promise&& rhs)
  816. {
  817. future.swap(rhs.future);
  818. future_obtained=rhs.future_obtained;
  819. rhs.future.reset();
  820. rhs.future_obtained=false;
  821. return *this;
  822. }
  823. #else
  824. promise(boost::detail::thread_move_t<promise> rhs):
  825. future(rhs->future),future_obtained(rhs->future_obtained)
  826. {
  827. rhs->future.reset();
  828. rhs->future_obtained=false;
  829. }
  830. promise & operator=(boost::detail::thread_move_t<promise> rhs)
  831. {
  832. future=rhs->future;
  833. future_obtained=rhs->future_obtained;
  834. rhs->future.reset();
  835. rhs->future_obtained=false;
  836. return *this;
  837. }
  838. operator boost::detail::thread_move_t<promise>()
  839. {
  840. return boost::detail::thread_move_t<promise>(*this);
  841. }
  842. #endif
  843. void swap(promise& other)
  844. {
  845. future.swap(other.future);
  846. std::swap(future_obtained,other.future_obtained);
  847. }
  848. // Result retrieval
  849. unique_future<R> get_future()
  850. {
  851. lazy_init();
  852. if(future_obtained)
  853. {
  854. boost::throw_exception(future_already_retrieved());
  855. }
  856. future_obtained=true;
  857. return unique_future<R>(future);
  858. }
  859. void set_value(typename detail::future_traits<R>::source_reference_type r)
  860. {
  861. lazy_init();
  862. boost::lock_guard<boost::mutex> lock(future->mutex);
  863. if(future->done)
  864. {
  865. boost::throw_exception(promise_already_satisfied());
  866. }
  867. future->mark_finished_with_result_internal(r);
  868. }
  869. // void set_value(R && r);
  870. void set_value(typename detail::future_traits<R>::rvalue_source_type r)
  871. {
  872. lazy_init();
  873. boost::lock_guard<boost::mutex> lock(future->mutex);
  874. if(future->done)
  875. {
  876. boost::throw_exception(promise_already_satisfied());
  877. }
  878. future->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));
  879. }
  880. void set_exception(boost::exception_ptr p)
  881. {
  882. lazy_init();
  883. boost::lock_guard<boost::mutex> lock(future->mutex);
  884. if(future->done)
  885. {
  886. boost::throw_exception(promise_already_satisfied());
  887. }
  888. future->mark_exceptional_finish_internal(p);
  889. }
  890. template<typename F>
  891. void set_wait_callback(F f)
  892. {
  893. lazy_init();
  894. future->set_wait_callback(f,this);
  895. }
  896. };
  897. template <>
  898. class promise<void>
  899. {
  900. typedef boost::shared_ptr<detail::future_object<void> > future_ptr;
  901. future_ptr future;
  902. bool future_obtained;
  903. promise(promise & rhs);// = delete;
  904. promise & operator=(promise & rhs);// = delete;
  905. void lazy_init()
  906. {
  907. if(!atomic_load(&future))
  908. {
  909. future_ptr blank;
  910. atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<void>));
  911. }
  912. }
  913. public:
  914. // template <class Allocator> explicit promise(Allocator a);
  915. promise():
  916. future(),future_obtained(false)
  917. {}
  918. ~promise()
  919. {
  920. if(future)
  921. {
  922. boost::lock_guard<boost::mutex> lock(future->mutex);
  923. if(!future->done)
  924. {
  925. future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
  926. }
  927. }
  928. }
  929. // Assignment
  930. #ifndef BOOST_NO_RVALUE_REFERENCES
  931. promise(promise && rhs):
  932. future_obtained(rhs.future_obtained)
  933. {
  934. future.swap(rhs.future);
  935. rhs.future_obtained=false;
  936. }
  937. promise & operator=(promise&& rhs)
  938. {
  939. future.swap(rhs.future);
  940. future_obtained=rhs.future_obtained;
  941. rhs.future.reset();
  942. rhs.future_obtained=false;
  943. return *this;
  944. }
  945. #else
  946. promise(boost::detail::thread_move_t<promise> rhs):
  947. future(rhs->future),future_obtained(rhs->future_obtained)
  948. {
  949. rhs->future.reset();
  950. rhs->future_obtained=false;
  951. }
  952. promise & operator=(boost::detail::thread_move_t<promise> rhs)
  953. {
  954. future=rhs->future;
  955. future_obtained=rhs->future_obtained;
  956. rhs->future.reset();
  957. rhs->future_obtained=false;
  958. return *this;
  959. }
  960. operator boost::detail::thread_move_t<promise>()
  961. {
  962. return boost::detail::thread_move_t<promise>(*this);
  963. }
  964. #endif
  965. void swap(promise& other)
  966. {
  967. future.swap(other.future);
  968. std::swap(future_obtained,other.future_obtained);
  969. }
  970. // Result retrieval
  971. unique_future<void> get_future()
  972. {
  973. lazy_init();
  974. if(future_obtained)
  975. {
  976. boost::throw_exception(future_already_retrieved());
  977. }
  978. future_obtained=true;
  979. return unique_future<void>(future);
  980. }
  981. void set_value()
  982. {
  983. lazy_init();
  984. boost::lock_guard<boost::mutex> lock(future->mutex);
  985. if(future->done)
  986. {
  987. boost::throw_exception(promise_already_satisfied());
  988. }
  989. future->mark_finished_with_result_internal();
  990. }
  991. void set_exception(boost::exception_ptr p)
  992. {
  993. lazy_init();
  994. boost::lock_guard<boost::mutex> lock(future->mutex);
  995. if(future->done)
  996. {
  997. boost::throw_exception(promise_already_satisfied());
  998. }
  999. future->mark_exceptional_finish_internal(p);
  1000. }
  1001. template<typename F>
  1002. void set_wait_callback(F f)
  1003. {
  1004. lazy_init();
  1005. future->set_wait_callback(f,this);
  1006. }
  1007. };
  1008. namespace detail
  1009. {
  1010. template<typename R>
  1011. struct task_base:
  1012. detail::future_object<R>
  1013. {
  1014. bool started;
  1015. task_base():
  1016. started(false)
  1017. {}
  1018. void run()
  1019. {
  1020. {
  1021. boost::lock_guard<boost::mutex> lk(this->mutex);
  1022. if(started)
  1023. {
  1024. boost::throw_exception(task_already_started());
  1025. }
  1026. started=true;
  1027. }
  1028. do_run();
  1029. }
  1030. void owner_destroyed()
  1031. {
  1032. boost::lock_guard<boost::mutex> lk(this->mutex);
  1033. if(!started)
  1034. {
  1035. started=true;
  1036. this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()));
  1037. }
  1038. }
  1039. virtual void do_run()=0;
  1040. };
  1041. template<typename R,typename F>
  1042. struct task_object:
  1043. task_base<R>
  1044. {
  1045. F f;
  1046. task_object(F const& f_):
  1047. f(f_)
  1048. {}
  1049. task_object(boost::detail::thread_move_t<F> f_):
  1050. f(f_)
  1051. {}
  1052. void do_run()
  1053. {
  1054. try
  1055. {
  1056. this->mark_finished_with_result(f());
  1057. }
  1058. catch(...)
  1059. {
  1060. this->mark_exceptional_finish();
  1061. }
  1062. }
  1063. };
  1064. template<typename F>
  1065. struct task_object<void,F>:
  1066. task_base<void>
  1067. {
  1068. F f;
  1069. task_object(F const& f_):
  1070. f(f_)
  1071. {}
  1072. task_object(boost::detail::thread_move_t<F> f_):
  1073. f(f_)
  1074. {}
  1075. void do_run()
  1076. {
  1077. try
  1078. {
  1079. f();
  1080. this->mark_finished_with_result();
  1081. }
  1082. catch(...)
  1083. {
  1084. this->mark_exceptional_finish();
  1085. }
  1086. }
  1087. };
  1088. }
  1089. template<typename R>
  1090. class packaged_task
  1091. {
  1092. boost::shared_ptr<detail::task_base<R> > task;
  1093. bool future_obtained;
  1094. packaged_task(packaged_task&);// = delete;
  1095. packaged_task& operator=(packaged_task&);// = delete;
  1096. public:
  1097. packaged_task():
  1098. future_obtained(false)
  1099. {}
  1100. // construction and destruction
  1101. template <class F>
  1102. explicit packaged_task(F const& f):
  1103. task(new detail::task_object<R,F>(f)),future_obtained(false)
  1104. {}
  1105. explicit packaged_task(R(*f)()):
  1106. task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
  1107. {}
  1108. template <class F>
  1109. explicit packaged_task(boost::detail::thread_move_t<F> f):
  1110. task(new detail::task_object<R,F>(f)),future_obtained(false)
  1111. {}
  1112. // template <class F, class Allocator>
  1113. // explicit packaged_task(F const& f, Allocator a);
  1114. // template <class F, class Allocator>
  1115. // explicit packaged_task(F&& f, Allocator a);
  1116. ~packaged_task()
  1117. {
  1118. if(task)
  1119. {
  1120. task->owner_destroyed();
  1121. }
  1122. }
  1123. // assignment
  1124. #ifndef BOOST_NO_RVALUE_REFERENCES
  1125. packaged_task(packaged_task&& other):
  1126. future_obtained(other.future_obtained)
  1127. {
  1128. task.swap(other.task);
  1129. other.future_obtained=false;
  1130. }
  1131. packaged_task& operator=(packaged_task&& other)
  1132. {
  1133. packaged_task temp(static_cast<packaged_task&&>(other));
  1134. swap(temp);
  1135. return *this;
  1136. }
  1137. #else
  1138. packaged_task(boost::detail::thread_move_t<packaged_task> other):
  1139. future_obtained(other->future_obtained)
  1140. {
  1141. task.swap(other->task);
  1142. other->future_obtained=false;
  1143. }
  1144. packaged_task& operator=(boost::detail::thread_move_t<packaged_task> other)
  1145. {
  1146. packaged_task temp(other);
  1147. swap(temp);
  1148. return *this;
  1149. }
  1150. operator boost::detail::thread_move_t<packaged_task>()
  1151. {
  1152. return boost::detail::thread_move_t<packaged_task>(*this);
  1153. }
  1154. #endif
  1155. void swap(packaged_task& other)
  1156. {
  1157. task.swap(other.task);
  1158. std::swap(future_obtained,other.future_obtained);
  1159. }
  1160. // result retrieval
  1161. unique_future<R> get_future()
  1162. {
  1163. if(!task)
  1164. {
  1165. boost::throw_exception(task_moved());
  1166. }
  1167. else if(!future_obtained)
  1168. {
  1169. future_obtained=true;
  1170. return unique_future<R>(task);
  1171. }
  1172. else
  1173. {
  1174. boost::throw_exception(future_already_retrieved());
  1175. }
  1176. }
  1177. // execution
  1178. void operator()()
  1179. {
  1180. if(!task)
  1181. {
  1182. boost::throw_exception(task_moved());
  1183. }
  1184. task->run();
  1185. }
  1186. template<typename F>
  1187. void set_wait_callback(F f)
  1188. {
  1189. task->set_wait_callback(f,this);
  1190. }
  1191. };
  1192. }
  1193. #endif