2 // Copyright Oliver Kowalke 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef BOOST_FIBERS_FUTURE_HPP
8 #define BOOST_FIBERS_FUTURE_HPP
14 #include <boost/config.hpp>
16 #include <boost/fiber/detail/config.hpp>
17 #include <boost/fiber/exceptions.hpp>
18 #include <boost/fiber/future/detail/shared_state.hpp>
19 #include <boost/fiber/future/future_status.hpp>
25 template< typename R >
27 typedef typename shared_state< R >::ptr_t ptr_t;
31 constexpr future_base() noexcept = default;
33 explicit future_base( ptr_t const& p) noexcept :
37 ~future_base() = default;
39 future_base( future_base const& other) :
40 state_{ other.state_ } {
43 future_base( future_base && other) noexcept :
44 state_{ other.state_ } {
48 future_base & operator=( future_base const& other) noexcept {
49 if ( this == & other) return * this;
50 state_ = other.state_;
54 future_base & operator=( future_base && other) noexcept {
55 if ( this == & other) return * this;
56 state_ = other.state_;
61 bool valid() const noexcept {
62 return nullptr != state_.get();
65 std::exception_ptr get_exception_ptr() {
67 throw future_uninitialized{};
69 return state_->get_exception_ptr();
74 throw future_uninitialized{};
79 template< typename Rep, typename Period >
80 future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
82 throw future_uninitialized{};
84 return state_->wait_for( timeout_duration);
87 template< typename Clock, typename Duration >
88 future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
90 throw future_uninitialized{};
92 return state_->wait_until( timeout_time);
96 template< typename R >
101 template< typename R >
104 template< typename Signature >
107 template< typename R >
108 class future : private detail::future_base< R > {
110 typedef detail::future_base< R > base_t;
112 friend struct detail::promise_base< R >;
113 friend class shared_future< R >;
114 template< typename Signature >
115 friend class packaged_task;
117 explicit future( typename base_t::ptr_t const& p) noexcept :
122 constexpr future() noexcept = default;
124 future( future const&) = delete;
125 future & operator=( future const&) = delete;
127 future( future && other) noexcept :
128 base_t{ std::move( other) } {
131 future & operator=( future && other) noexcept {
132 if ( this == & other) return * this;
133 base_t::operator=( std::move( other) );
137 shared_future< R > share();
140 if ( ! base_t::valid() ) {
141 throw future_uninitialized{};
143 typename base_t::ptr_t tmp{};
144 tmp.swap( base_t::state_);
145 return std::move( tmp->get() );
149 using base_t::get_exception_ptr;
151 using base_t::wait_for;
152 using base_t::wait_until;
155 template< typename R >
156 class future< R & > : private detail::future_base< R & > {
158 typedef detail::future_base< R & > base_t;
160 friend struct detail::promise_base< R & >;
161 friend class shared_future< R & >;
162 template< typename Signature >
163 friend class packaged_task;
165 explicit future( typename base_t::ptr_t const& p) noexcept :
170 constexpr future() noexcept = default;
172 future( future const&) = delete;
173 future & operator=( future const&) = delete;
175 future( future && other) noexcept :
176 base_t{ std::move( other) } {
179 future & operator=( future && other) noexcept {
180 if ( this == & other) return * this;
181 base_t::operator=( std::move( other) );
185 shared_future< R & > share();
188 if ( ! base_t::valid() ) {
189 throw future_uninitialized{};
191 typename base_t::ptr_t tmp{};
192 tmp.swap( base_t::state_);
197 using base_t::get_exception_ptr;
199 using base_t::wait_for;
200 using base_t::wait_until;
204 class future< void > : private detail::future_base< void > {
206 typedef detail::future_base< void > base_t;
208 friend struct detail::promise_base< void >;
209 friend class shared_future< void >;
210 template< typename Signature >
211 friend class packaged_task;
213 explicit future( base_t::ptr_t const& p) noexcept :
218 constexpr future() noexcept = default;
220 future( future const&) = delete;
221 future & operator=( future const&) = delete;
224 future( future && other) noexcept :
225 base_t{ std::move( other) } {
229 future & operator=( future && other) noexcept {
230 if ( this == & other) return * this;
231 base_t::operator=( std::move( other) );
235 shared_future< void > share();
239 if ( ! base_t::valid() ) {
240 throw future_uninitialized{};
243 tmp.swap( base_t::state_);
248 using base_t::get_exception_ptr;
250 using base_t::wait_for;
251 using base_t::wait_until;
255 template< typename R >
256 class shared_future : private detail::future_base< R > {
258 typedef detail::future_base< R > base_t;
260 explicit shared_future( typename base_t::ptr_t const& p) noexcept :
265 constexpr shared_future() noexcept = default;
267 ~shared_future() = default;
269 shared_future( shared_future const& other) :
273 shared_future( shared_future && other) noexcept :
274 base_t{ std::move( other) } {
277 shared_future( future< R > && other) noexcept :
278 base_t{ std::move( other) } {
281 shared_future & operator=( shared_future const& other) noexcept {
282 if ( this == & other) return * this;
283 base_t::operator=( other);
287 shared_future & operator=( shared_future && other) noexcept {
288 if ( this == & other) return * this;
289 base_t::operator=( std::move( other) );
293 shared_future & operator=( future< R > && other) noexcept {
294 base_t::operator=( std::move( other) );
298 R const& get() const {
300 throw future_uninitialized{};
302 return base_t::state_->get();
306 using base_t::get_exception_ptr;
308 using base_t::wait_for;
309 using base_t::wait_until;
312 template< typename R >
313 class shared_future< R & > : private detail::future_base< R & > {
315 typedef detail::future_base< R & > base_t;
317 explicit shared_future( typename base_t::ptr_t const& p) noexcept :
322 constexpr shared_future() noexcept = default;
324 ~shared_future() = default;
326 shared_future( shared_future const& other) :
330 shared_future( shared_future && other) noexcept :
331 base_t{ std::move( other) } {
334 shared_future( future< R & > && other) noexcept :
335 base_t{ std::move( other) } {
338 shared_future & operator=( shared_future const& other) noexcept {
339 if ( this == & other) return * this;
340 base_t::operator=( other);
344 shared_future & operator=( shared_future && other) noexcept {
345 if ( this == & other) return * this;
346 base_t::operator=( std::move( other) );
350 shared_future & operator=( future< R & > && other) noexcept {
351 base_t::operator=( std::move( other) );
357 throw future_uninitialized{};
359 return base_t::state_->get();
363 using base_t::get_exception_ptr;
365 using base_t::wait_for;
366 using base_t::wait_until;
370 class shared_future< void > : private detail::future_base< void > {
372 typedef detail::future_base< void > base_t;
374 explicit shared_future( base_t::ptr_t const& p) noexcept :
379 constexpr shared_future() noexcept = default;
381 ~shared_future() = default;
384 shared_future( shared_future const& other) :
389 shared_future( shared_future && other) noexcept :
390 base_t{ std::move( other) } {
394 shared_future( future< void > && other) noexcept :
395 base_t{ std::move( other) } {
399 shared_future & operator=( shared_future const& other) noexcept {
400 if ( this == & other) return * this;
401 base_t::operator=( other);
406 shared_future & operator=( shared_future && other) noexcept {
407 if ( this == & other) return * this;
408 base_t::operator=( std::move( other) );
413 shared_future & operator=( future< void > && other) noexcept {
414 base_t::operator=( std::move( other) );
421 throw future_uninitialized{};
423 base_t::state_->get();
427 using base_t::get_exception_ptr;
429 using base_t::wait_for;
430 using base_t::wait_until;
434 template< typename R >
436 future< R >::share() {
437 if ( ! base_t::valid() ) {
438 throw future_uninitialized{};
440 return shared_future< R >{ std::move( * this) };
443 template< typename R >
445 future< R & >::share() {
446 if ( ! base_t::valid() ) {
447 throw future_uninitialized{};
449 return shared_future< R & >{ std::move( * this) };
453 shared_future< void >
454 future< void >::share() {
455 if ( ! base_t::valid() ) {
456 throw future_uninitialized{};
458 return shared_future< void >{ std::move( * this) };