Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:35

0001 
0002 //          Copyright Oliver Kowalke 2013.
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //    (See accompanying file LICENSE_1_0.txt or copy at
0005 //          http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_FIBERS_PROMISE_HPP
0008 #define BOOST_FIBERS_PROMISE_HPP
0009 
0010 #include <algorithm>
0011 #include <memory>
0012 #include <utility>
0013 
0014 #include <boost/config.hpp>
0015 #include <boost/core/pointer_traits.hpp>
0016 
0017 #include <boost/fiber/exceptions.hpp>
0018 #include <boost/fiber/future/detail/shared_state.hpp>
0019 #include <boost/fiber/future/detail/shared_state_object.hpp>
0020 #include <boost/fiber/future/future.hpp>
0021 
0022 namespace boost {
0023 namespace fibers {
0024 namespace detail {
0025 
0026 template< typename R >
0027 struct promise_base {
0028     typedef typename shared_state< R >::ptr_type   ptr_type;
0029 
0030     bool            obtained_{ false };
0031     ptr_type        future_{};
0032 
0033     promise_base() :
0034         promise_base{ std::allocator_arg, std::allocator< promise_base >{} } {
0035     }
0036 
0037     template< typename Allocator >
0038     promise_base( std::allocator_arg_t, Allocator alloc) {
0039         typedef detail::shared_state_object< R, Allocator >  object_type;
0040         typedef std::allocator_traits< typename object_type::allocator_type > traits_type;
0041         typedef pointer_traits< typename traits_type::pointer > ptrait_type;
0042         typename object_type::allocator_type a{ alloc };
0043         typename traits_type::pointer ptr{ traits_type::allocate( a, 1) };
0044         typename ptrait_type::element_type* p = boost::to_address(ptr);
0045 
0046         try {
0047             traits_type::construct( a, p, a);
0048         } catch (...) {
0049             traits_type::deallocate( a, ptr, 1);
0050             throw;
0051         }
0052         future_.reset(p);
0053     }
0054 
0055     ~promise_base() {
0056         if ( future_ && obtained_) {
0057             future_->owner_destroyed();
0058         }
0059     }
0060 
0061     promise_base( promise_base const&) = delete;
0062     promise_base & operator=( promise_base const&) = delete;
0063 
0064     promise_base( promise_base && other) noexcept :
0065         obtained_{ other.obtained_ },
0066         future_{ std::move( other.future_) } {
0067         other.obtained_ = false;
0068     }
0069 
0070     promise_base & operator=( promise_base && other) noexcept {
0071         if ( BOOST_LIKELY( this != & other) ) {
0072             promise_base tmp{ std::move( other) };
0073             swap( tmp);
0074         }
0075         return * this;
0076     }
0077 
0078     future< R > get_future() {
0079         if ( BOOST_UNLIKELY( obtained_) ) {
0080             throw future_already_retrieved{};
0081         }
0082         if ( BOOST_UNLIKELY( ! future_) ) {
0083             throw promise_uninitialized{};
0084         }
0085         obtained_ = true;
0086         return future< R >{ future_ };
0087     }
0088 
0089     void swap( promise_base & other) noexcept {
0090         std::swap( obtained_, other.obtained_);
0091         future_.swap( other.future_);
0092     }
0093 
0094     void set_exception( std::exception_ptr p) {
0095         if ( BOOST_UNLIKELY( ! future_) ) {
0096             throw promise_uninitialized{};
0097         }
0098         future_->set_exception( p);
0099     }
0100 };
0101 
0102 }
0103 
0104 template< typename R >
0105 class promise : private detail::promise_base< R > {
0106 private:
0107     typedef detail::promise_base< R >  base_type;
0108 
0109 public:
0110     promise() = default;
0111 
0112     template< typename Allocator >
0113     promise( std::allocator_arg_t, Allocator alloc) :
0114         base_type{ std::allocator_arg, alloc } {
0115     }
0116 
0117     promise( promise const&) = delete;
0118     promise & operator=( promise const&) = delete;
0119 
0120     promise( promise && other) = default;
0121     promise & operator=( promise && other) = default;
0122 
0123     void set_value( R const& value) {
0124         if ( BOOST_UNLIKELY( ! base_type::future_) ) {
0125             throw promise_uninitialized{};
0126         }
0127         base_type::future_->set_value( value);
0128     }
0129 
0130     void set_value( R && value) {
0131         if ( BOOST_UNLIKELY( ! base_type::future_) ) {
0132             throw promise_uninitialized{};
0133         }
0134         base_type::future_->set_value( std::move( value) );
0135     }
0136 
0137     void swap( promise & other) noexcept {
0138         base_type::swap( other);
0139     }
0140 
0141     using base_type::get_future;
0142     using base_type::set_exception;
0143 };
0144 
0145 template< typename R >
0146 class promise< R & > : private detail::promise_base< R & > {
0147 private:
0148     typedef detail::promise_base< R & >  base_type;
0149 
0150 public:
0151     promise() = default;
0152 
0153     template< typename Allocator >
0154     promise( std::allocator_arg_t, Allocator alloc) :
0155         base_type{ std::allocator_arg, alloc } {
0156     }
0157 
0158     promise( promise const&) = delete;
0159     promise & operator=( promise const&) = delete;
0160 
0161     promise( promise && other) = default;
0162     promise & operator=( promise && other) = default;
0163 
0164     void set_value( R & value) {
0165         if ( BOOST_UNLIKELY( ! base_type::future_) ) {
0166             throw promise_uninitialized{};
0167         }
0168         base_type::future_->set_value( value);
0169     }
0170 
0171     void swap( promise & other) noexcept {
0172         base_type::swap( other);
0173     }
0174 
0175     using base_type::get_future;
0176     using base_type::set_exception;
0177 };
0178 
0179 template<>
0180 class promise< void > : private detail::promise_base< void > {
0181 private:
0182     typedef detail::promise_base< void >  base_type;
0183 
0184 public:
0185     promise() = default;
0186 
0187     template< typename Allocator >
0188     promise( std::allocator_arg_t, Allocator alloc) :
0189         base_type{ std::allocator_arg, alloc } {
0190     }
0191 
0192     promise( promise const&) = delete;
0193     promise & operator=( promise const&) = delete;
0194 
0195     promise( promise && other)  = default;
0196     promise & operator=( promise && other) = default;
0197 
0198     inline
0199     void set_value() {
0200         if ( BOOST_UNLIKELY( ! base_type::future_) ) {
0201             throw promise_uninitialized{};
0202         }
0203         base_type::future_->set_value();
0204     }
0205 
0206     inline
0207     void swap( promise & other) noexcept {
0208         base_type::swap( other);
0209     }
0210 
0211     using base_type::get_future;
0212     using base_type::set_exception;
0213 };
0214 
0215 template< typename R >
0216 void swap( promise< R > & l, promise< R > & r) noexcept {
0217     l.swap( r);
0218 }
0219 
0220 }}
0221 
0222 #endif // BOOST_FIBERS_PROMISE_HPP