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_type ptr_type;
31 future_base() = default;
33 explicit future_base( ptr_type 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 ( BOOST_LIKELY( this != & other) ) {
50 state_ = other.state_;
55 future_base & operator=( future_base && other) noexcept {
56 if ( BOOST_LIKELY( this != & other) ) {
57 state_ = other.state_;
63 bool valid() const noexcept {
64 return nullptr != state_.get();
67 std::exception_ptr get_exception_ptr() {
68 if ( BOOST_UNLIKELY( ! valid() ) ) {
69 throw future_uninitialized{};
71 return state_->get_exception_ptr();
75 if ( BOOST_UNLIKELY( ! valid() ) ) {
76 throw future_uninitialized{};
81 template< typename Rep, typename Period >
82 future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
83 if ( BOOST_UNLIKELY( ! valid() ) ) {
84 throw future_uninitialized{};
86 return state_->wait_for( timeout_duration);
89 template< typename Clock, typename Duration >
90 future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
91 if ( BOOST_UNLIKELY( ! valid() ) ) {
92 throw future_uninitialized{};
94 return state_->wait_until( timeout_time);
98 template< typename R >
103 template< typename R >
106 template< typename Signature >
109 template< typename R >
110 class future : private detail::future_base< R > {
112 typedef detail::future_base< R > base_type;
114 friend struct detail::promise_base< R >;
115 friend class shared_future< R >;
116 template< typename Signature >
117 friend class packaged_task;
119 explicit future( typename base_type::ptr_type const& p) noexcept :
126 future( future const&) = delete;
127 future & operator=( future const&) = delete;
129 future( future && other) noexcept :
130 base_type{ std::move( other) } {
133 future & operator=( future && other) noexcept {
134 if ( BOOST_LIKELY( this != & other) ) {
135 base_type::operator=( std::move( other) );
140 shared_future< R > share();
143 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
144 throw future_uninitialized{};
146 typename base_type::ptr_type tmp{};
147 tmp.swap( base_type::state_);
148 return std::move( tmp->get() );
151 using base_type::valid;
152 using base_type::get_exception_ptr;
153 using base_type::wait;
154 using base_type::wait_for;
155 using base_type::wait_until;
158 template< typename R >
159 class future< R & > : private detail::future_base< R & > {
161 typedef detail::future_base< R & > base_type;
163 friend struct detail::promise_base< R & >;
164 friend class shared_future< R & >;
165 template< typename Signature >
166 friend class packaged_task;
168 explicit future( typename base_type::ptr_type const& p) noexcept :
175 future( future const&) = delete;
176 future & operator=( future const&) = delete;
178 future( future && other) noexcept :
179 base_type{ std::move( other) } {
182 future & operator=( future && other) noexcept {
183 if ( BOOST_LIKELY( this != & other) ) {
184 base_type::operator=( std::move( other) );
189 shared_future< R & > share();
192 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
193 throw future_uninitialized{};
195 typename base_type::ptr_type tmp{};
196 tmp.swap( base_type::state_);
200 using base_type::valid;
201 using base_type::get_exception_ptr;
202 using base_type::wait;
203 using base_type::wait_for;
204 using base_type::wait_until;
208 class future< void > : private detail::future_base< void > {
210 typedef detail::future_base< void > base_type;
212 friend struct detail::promise_base< void >;
213 friend class shared_future< void >;
214 template< typename Signature >
215 friend class packaged_task;
217 explicit future( base_type::ptr_type const& p) noexcept :
224 future( future const&) = delete;
225 future & operator=( future const&) = delete;
228 future( future && other) noexcept :
229 base_type{ std::move( other) } {
233 future & operator=( future && other) noexcept {
234 if ( BOOST_LIKELY( this != & other) ) {
235 base_type::operator=( std::move( other) );
240 shared_future< void > share();
244 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
245 throw future_uninitialized{};
247 base_type::ptr_type tmp{};
248 tmp.swap( base_type::state_);
252 using base_type::valid;
253 using base_type::get_exception_ptr;
254 using base_type::wait;
255 using base_type::wait_for;
256 using base_type::wait_until;
260 template< typename R >
261 class shared_future : private detail::future_base< R > {
263 typedef detail::future_base< R > base_type;
265 explicit shared_future( typename base_type::ptr_type const& p) noexcept :
270 shared_future() = default;
272 ~shared_future() = default;
274 shared_future( shared_future const& other) :
278 shared_future( shared_future && other) noexcept :
279 base_type{ std::move( other) } {
282 shared_future( future< R > && other) noexcept :
283 base_type{ std::move( other) } {
286 shared_future & operator=( shared_future const& other) noexcept {
287 if ( BOOST_LIKELY( this != & other) ) {
288 base_type::operator=( other);
293 shared_future & operator=( shared_future && other) noexcept {
294 if ( BOOST_LIKELY( this != & other) ) {
295 base_type::operator=( std::move( other) );
300 shared_future & operator=( future< R > && other) noexcept {
301 base_type::operator=( std::move( other) );
305 R const& get() const {
306 if ( BOOST_UNLIKELY( ! valid() ) ) {
307 throw future_uninitialized{};
309 return base_type::state_->get();
312 using base_type::valid;
313 using base_type::get_exception_ptr;
314 using base_type::wait;
315 using base_type::wait_for;
316 using base_type::wait_until;
319 template< typename R >
320 class shared_future< R & > : private detail::future_base< R & > {
322 typedef detail::future_base< R & > base_type;
324 explicit shared_future( typename base_type::ptr_type const& p) noexcept :
329 shared_future() = default;
331 ~shared_future() = default;
333 shared_future( shared_future const& other) :
337 shared_future( shared_future && other) noexcept :
338 base_type{ std::move( other) } {
341 shared_future( future< R & > && other) noexcept :
342 base_type{ std::move( other) } {
345 shared_future & operator=( shared_future const& other) noexcept {
346 if ( BOOST_LIKELY( this != & other) ) {
347 base_type::operator=( other);
352 shared_future & operator=( shared_future && other) noexcept {
353 if ( BOOST_LIKELY( this != & other) ) {
354 base_type::operator=( std::move( other) );
359 shared_future & operator=( future< R & > && other) noexcept {
360 base_type::operator=( std::move( other) );
365 if ( BOOST_UNLIKELY( ! valid() ) ) {
366 throw future_uninitialized{};
368 return base_type::state_->get();
371 using base_type::valid;
372 using base_type::get_exception_ptr;
373 using base_type::wait;
374 using base_type::wait_for;
375 using base_type::wait_until;
379 class shared_future< void > : private detail::future_base< void > {
381 typedef detail::future_base< void > base_type;
383 explicit shared_future( base_type::ptr_type const& p) noexcept :
388 shared_future() = default;
390 ~shared_future() = default;
393 shared_future( shared_future const& other) :
398 shared_future( shared_future && other) noexcept :
399 base_type{ std::move( other) } {
403 shared_future( future< void > && other) noexcept :
404 base_type{ std::move( other) } {
408 shared_future & operator=( shared_future const& other) noexcept {
409 if ( BOOST_LIKELY( this != & other) ) {
410 base_type::operator=( other);
416 shared_future & operator=( shared_future && other) noexcept {
417 if ( BOOST_LIKELY( this != & other) ) {
418 base_type::operator=( std::move( other) );
424 shared_future & operator=( future< void > && other) noexcept {
425 base_type::operator=( std::move( other) );
431 if ( BOOST_UNLIKELY( ! valid() ) ) {
432 throw future_uninitialized{};
434 base_type::state_->get();
437 using base_type::valid;
438 using base_type::get_exception_ptr;
439 using base_type::wait;
440 using base_type::wait_for;
441 using base_type::wait_until;
445 template< typename R >
447 future< R >::share() {
448 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
449 throw future_uninitialized{};
451 return shared_future< R >{ std::move( * this) };
454 template< typename R >
456 future< R & >::share() {
457 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
458 throw future_uninitialized{};
460 return shared_future< R & >{ std::move( * this) };
464 shared_future< void >
465 future< void >::share() {
466 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
467 throw future_uninitialized{};
469 return shared_future< void >{ std::move( * this) };