future.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. // Copyright Oliver Kowalke 2013.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_FIBERS_FUTURE_HPP
  6. #define BOOST_FIBERS_FUTURE_HPP
  7. #include <algorithm>
  8. #include <chrono>
  9. #include <exception>
  10. #include <boost/config.hpp>
  11. #include <boost/fiber/detail/config.hpp>
  12. #include <boost/fiber/exceptions.hpp>
  13. #include <boost/fiber/future/detail/shared_state.hpp>
  14. #include <boost/fiber/future/future_status.hpp>
  15. namespace boost {
  16. namespace fibers {
  17. namespace detail {
  18. template< typename R >
  19. struct future_base {
  20. typedef typename shared_state< R >::ptr_type ptr_type;
  21. ptr_type state_{};
  22. future_base() = default;
  23. explicit future_base( ptr_type const& p) noexcept :
  24. state_{ p } {
  25. }
  26. ~future_base() = default;
  27. future_base( future_base const& other) :
  28. state_{ other.state_ } {
  29. }
  30. future_base( future_base && other) noexcept :
  31. state_{ other.state_ } {
  32. other.state_.reset();
  33. }
  34. future_base & operator=( future_base const& other) noexcept {
  35. if ( BOOST_LIKELY( this != & other) ) {
  36. state_ = other.state_;
  37. }
  38. return * this;
  39. }
  40. future_base & operator=( future_base && other) noexcept {
  41. if ( BOOST_LIKELY( this != & other) ) {
  42. state_ = other.state_;
  43. other.state_.reset();
  44. }
  45. return * this;
  46. }
  47. bool valid() const noexcept {
  48. return nullptr != state_.get();
  49. }
  50. std::exception_ptr get_exception_ptr() {
  51. if ( BOOST_UNLIKELY( ! valid() ) ) {
  52. throw future_uninitialized{};
  53. }
  54. return state_->get_exception_ptr();
  55. }
  56. void wait() const {
  57. if ( BOOST_UNLIKELY( ! valid() ) ) {
  58. throw future_uninitialized{};
  59. }
  60. state_->wait();
  61. }
  62. template< typename Rep, typename Period >
  63. future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
  64. if ( BOOST_UNLIKELY( ! valid() ) ) {
  65. throw future_uninitialized{};
  66. }
  67. return state_->wait_for( timeout_duration);
  68. }
  69. template< typename Clock, typename Duration >
  70. future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
  71. if ( BOOST_UNLIKELY( ! valid() ) ) {
  72. throw future_uninitialized{};
  73. }
  74. return state_->wait_until( timeout_time);
  75. }
  76. };
  77. template< typename R >
  78. struct promise_base;
  79. }
  80. template< typename R >
  81. class shared_future;
  82. template< typename Signature >
  83. class packaged_task;
  84. template< typename R >
  85. class future : private detail::future_base< R > {
  86. private:
  87. typedef detail::future_base< R > base_type;
  88. friend struct detail::promise_base< R >;
  89. friend class shared_future< R >;
  90. template< typename Signature >
  91. friend class packaged_task;
  92. explicit future( typename base_type::ptr_type const& p) noexcept :
  93. base_type{ p } {
  94. }
  95. public:
  96. future() = default;
  97. future( future const&) = delete;
  98. future & operator=( future const&) = delete;
  99. future( future && other) noexcept :
  100. base_type{ std::move( other) } {
  101. }
  102. future & operator=( future && other) noexcept {
  103. if ( BOOST_LIKELY( this != & other) ) {
  104. base_type::operator=( std::move( other) );
  105. }
  106. return * this;
  107. }
  108. shared_future< R > share();
  109. R get() {
  110. if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
  111. throw future_uninitialized{};
  112. }
  113. typename base_type::ptr_type tmp{};
  114. tmp.swap( base_type::state_);
  115. return std::move( tmp->get() );
  116. }
  117. using base_type::valid;
  118. using base_type::get_exception_ptr;
  119. using base_type::wait;
  120. using base_type::wait_for;
  121. using base_type::wait_until;
  122. };
  123. template< typename R >
  124. class future< R & > : private detail::future_base< R & > {
  125. private:
  126. typedef detail::future_base< R & > base_type;
  127. friend struct detail::promise_base< R & >;
  128. friend class shared_future< R & >;
  129. template< typename Signature >
  130. friend class packaged_task;
  131. explicit future( typename base_type::ptr_type const& p) noexcept :
  132. base_type{ p } {
  133. }
  134. public:
  135. future() = default;
  136. future( future const&) = delete;
  137. future & operator=( future const&) = delete;
  138. future( future && other) noexcept :
  139. base_type{ std::move( other) } {
  140. }
  141. future & operator=( future && other) noexcept {
  142. if ( BOOST_LIKELY( this != & other) ) {
  143. base_type::operator=( std::move( other) );
  144. }
  145. return * this;
  146. }
  147. shared_future< R & > share();
  148. R & get() {
  149. if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
  150. throw future_uninitialized{};
  151. }
  152. typename base_type::ptr_type tmp{};
  153. tmp.swap( base_type::state_);
  154. return tmp->get();
  155. }
  156. using base_type::valid;
  157. using base_type::get_exception_ptr;
  158. using base_type::wait;
  159. using base_type::wait_for;
  160. using base_type::wait_until;
  161. };
  162. template<>
  163. class future< void > : private detail::future_base< void > {
  164. private:
  165. typedef detail::future_base< void > base_type;
  166. friend struct detail::promise_base< void >;
  167. friend class shared_future< void >;
  168. template< typename Signature >
  169. friend class packaged_task;
  170. explicit future( base_type::ptr_type const& p) noexcept :
  171. base_type{ p } {
  172. }
  173. public:
  174. future() = default;
  175. future( future const&) = delete;
  176. future & operator=( future const&) = delete;
  177. inline
  178. future( future && other) noexcept :
  179. base_type{ std::move( other) } {
  180. }
  181. inline
  182. future & operator=( future && other) noexcept {
  183. if ( BOOST_LIKELY( this != & other) ) {
  184. base_type::operator=( std::move( other) );
  185. }
  186. return * this;
  187. }
  188. shared_future< void > share();
  189. inline
  190. void get() {
  191. if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
  192. throw future_uninitialized{};
  193. }
  194. base_type::ptr_type tmp{};
  195. tmp.swap( base_type::state_);
  196. tmp->get();
  197. }
  198. using base_type::valid;
  199. using base_type::get_exception_ptr;
  200. using base_type::wait;
  201. using base_type::wait_for;
  202. using base_type::wait_until;
  203. };
  204. template< typename R >
  205. class shared_future : private detail::future_base< R > {
  206. private:
  207. typedef detail::future_base< R > base_type;
  208. explicit shared_future( typename base_type::ptr_type const& p) noexcept :
  209. base_type{ p } {
  210. }
  211. public:
  212. shared_future() = default;
  213. ~shared_future() = default;
  214. shared_future( shared_future const& other) :
  215. base_type{ other } {
  216. }
  217. shared_future( shared_future && other) noexcept :
  218. base_type{ std::move( other) } {
  219. }
  220. shared_future( future< R > && other) noexcept :
  221. base_type{ std::move( other) } {
  222. }
  223. shared_future & operator=( shared_future const& other) noexcept {
  224. if ( BOOST_LIKELY( this != & other) ) {
  225. base_type::operator=( other);
  226. }
  227. return * this;
  228. }
  229. shared_future & operator=( shared_future && other) noexcept {
  230. if ( BOOST_LIKELY( this != & other) ) {
  231. base_type::operator=( std::move( other) );
  232. }
  233. return * this;
  234. }
  235. shared_future & operator=( future< R > && other) noexcept {
  236. base_type::operator=( std::move( other) );
  237. return * this;
  238. }
  239. R const& get() const {
  240. if ( BOOST_UNLIKELY( ! valid() ) ) {
  241. throw future_uninitialized{};
  242. }
  243. return base_type::state_->get();
  244. }
  245. using base_type::valid;
  246. using base_type::get_exception_ptr;
  247. using base_type::wait;
  248. using base_type::wait_for;
  249. using base_type::wait_until;
  250. };
  251. template< typename R >
  252. class shared_future< R & > : private detail::future_base< R & > {
  253. private:
  254. typedef detail::future_base< R & > base_type;
  255. explicit shared_future( typename base_type::ptr_type const& p) noexcept :
  256. base_type{ p } {
  257. }
  258. public:
  259. shared_future() = default;
  260. ~shared_future() = default;
  261. shared_future( shared_future const& other) :
  262. base_type{ other } {
  263. }
  264. shared_future( shared_future && other) noexcept :
  265. base_type{ std::move( other) } {
  266. }
  267. shared_future( future< R & > && other) noexcept :
  268. base_type{ std::move( other) } {
  269. }
  270. shared_future & operator=( shared_future const& other) noexcept {
  271. if ( BOOST_LIKELY( this != & other) ) {
  272. base_type::operator=( other);
  273. }
  274. return * this;
  275. }
  276. shared_future & operator=( shared_future && other) noexcept {
  277. if ( BOOST_LIKELY( this != & other) ) {
  278. base_type::operator=( std::move( other) );
  279. }
  280. return * this;
  281. }
  282. shared_future & operator=( future< R & > && other) noexcept {
  283. base_type::operator=( std::move( other) );
  284. return * this;
  285. }
  286. R & get() const {
  287. if ( BOOST_UNLIKELY( ! valid() ) ) {
  288. throw future_uninitialized{};
  289. }
  290. return base_type::state_->get();
  291. }
  292. using base_type::valid;
  293. using base_type::get_exception_ptr;
  294. using base_type::wait;
  295. using base_type::wait_for;
  296. using base_type::wait_until;
  297. };
  298. template<>
  299. class shared_future< void > : private detail::future_base< void > {
  300. private:
  301. typedef detail::future_base< void > base_type;
  302. explicit shared_future( base_type::ptr_type const& p) noexcept :
  303. base_type{ p } {
  304. }
  305. public:
  306. shared_future() = default;
  307. ~shared_future() = default;
  308. inline
  309. shared_future( shared_future const& other) :
  310. base_type{ other } {
  311. }
  312. inline
  313. shared_future( shared_future && other) noexcept :
  314. base_type{ std::move( other) } {
  315. }
  316. inline
  317. shared_future( future< void > && other) noexcept :
  318. base_type{ std::move( other) } {
  319. }
  320. inline
  321. shared_future & operator=( shared_future const& other) noexcept {
  322. if ( BOOST_LIKELY( this != & other) ) {
  323. base_type::operator=( other);
  324. }
  325. return * this;
  326. }
  327. inline
  328. shared_future & operator=( shared_future && other) noexcept {
  329. if ( BOOST_LIKELY( this != & other) ) {
  330. base_type::operator=( std::move( other) );
  331. }
  332. return * this;
  333. }
  334. inline
  335. shared_future & operator=( future< void > && other) noexcept {
  336. base_type::operator=( std::move( other) );
  337. return * this;
  338. }
  339. inline
  340. void get() const {
  341. if ( BOOST_UNLIKELY( ! valid() ) ) {
  342. throw future_uninitialized{};
  343. }
  344. base_type::state_->get();
  345. }
  346. using base_type::valid;
  347. using base_type::get_exception_ptr;
  348. using base_type::wait;
  349. using base_type::wait_for;
  350. using base_type::wait_until;
  351. };
  352. template< typename R >
  353. shared_future< R >
  354. future< R >::share() {
  355. if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
  356. throw future_uninitialized{};
  357. }
  358. return shared_future< R >{ std::move( * this) };
  359. }
  360. template< typename R >
  361. shared_future< R & >
  362. future< R & >::share() {
  363. if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
  364. throw future_uninitialized{};
  365. }
  366. return shared_future< R & >{ std::move( * this) };
  367. }
  368. inline
  369. shared_future< void >
  370. future< void >::share() {
  371. if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
  372. throw future_uninitialized{};
  373. }
  374. return shared_future< void >{ std::move( * this) };
  375. }
  376. }}
  377. #endif