File indexing completed on 2025-01-31 09:37:22
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_FIBERS_DETAIL_SHARED_STATE_H
0008 #define BOOST_FIBERS_DETAIL_SHARED_STATE_H
0009
0010 #include <algorithm>
0011 #include <atomic>
0012 #include <chrono>
0013 #include <cstddef>
0014 #include <exception>
0015 #include <memory>
0016 #include <mutex>
0017 #include <type_traits>
0018
0019 #include <boost/assert.hpp>
0020 #include <boost/config.hpp>
0021 #include <boost/intrusive_ptr.hpp>
0022
0023 #include <boost/fiber/detail/config.hpp>
0024 #include <boost/fiber/future/future_status.hpp>
0025 #include <boost/fiber/condition_variable.hpp>
0026 #include <boost/fiber/exceptions.hpp>
0027 #include <boost/fiber/mutex.hpp>
0028
0029 #ifdef BOOST_HAS_ABI_HEADERS
0030 # include BOOST_ABI_PREFIX
0031 #endif
0032
0033 namespace boost {
0034 namespace fibers {
0035 namespace detail {
0036
0037 class shared_state_base {
0038 private:
0039 std::atomic< std::size_t > use_count_{ 0 };
0040 mutable condition_variable waiters_{};
0041
0042 protected:
0043 mutable mutex mtx_{};
0044 bool ready_{ false };
0045 std::exception_ptr except_{};
0046
0047 void mark_ready_and_notify_( std::unique_lock< mutex > & lk) noexcept {
0048 BOOST_ASSERT( lk.owns_lock() );
0049 ready_ = true;
0050 lk.unlock();
0051 waiters_.notify_all();
0052 }
0053
0054 void owner_destroyed_( std::unique_lock< mutex > & lk) {
0055 BOOST_ASSERT( lk.owns_lock() );
0056 if ( ! ready_) {
0057 set_exception_(
0058 std::make_exception_ptr( broken_promise() ),
0059 lk);
0060 }
0061 }
0062
0063 void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
0064 BOOST_ASSERT( lk.owns_lock() );
0065 if ( BOOST_UNLIKELY( ready_) ) {
0066 throw promise_already_satisfied();
0067 }
0068 except_ = except;
0069 mark_ready_and_notify_( lk);
0070 }
0071
0072 std::exception_ptr get_exception_ptr_( std::unique_lock< mutex > & lk) {
0073 BOOST_ASSERT( lk.owns_lock() );
0074 wait_( lk);
0075 return except_;
0076 }
0077
0078 void wait_( std::unique_lock< mutex > & lk) const {
0079 BOOST_ASSERT( lk.owns_lock() );
0080 waiters_.wait( lk, [this](){ return ready_; });
0081 }
0082
0083 template< typename Rep, typename Period >
0084 future_status wait_for_( std::unique_lock< mutex > & lk,
0085 std::chrono::duration< Rep, Period > const& timeout_duration) const {
0086 BOOST_ASSERT( lk.owns_lock() );
0087 return waiters_.wait_for( lk, timeout_duration, [this](){ return ready_; })
0088 ? future_status::ready
0089 : future_status::timeout;
0090 }
0091
0092 template< typename Clock, typename Duration >
0093 future_status wait_until_( std::unique_lock< mutex > & lk,
0094 std::chrono::time_point< Clock, Duration > const& timeout_time) const {
0095 BOOST_ASSERT( lk.owns_lock() );
0096 return waiters_.wait_until( lk, timeout_time, [this](){ return ready_; })
0097 ? future_status::ready
0098 : future_status::timeout;
0099 }
0100
0101 virtual void deallocate_future() noexcept = 0;
0102
0103 public:
0104 shared_state_base() = default;
0105
0106 virtual ~shared_state_base() = default;
0107
0108 shared_state_base( shared_state_base const&) = delete;
0109 shared_state_base & operator=( shared_state_base const&) = delete;
0110
0111 void owner_destroyed() {
0112 std::unique_lock< mutex > lk{ mtx_ };
0113 owner_destroyed_( lk);
0114 }
0115
0116 void set_exception( std::exception_ptr except) {
0117 std::unique_lock< mutex > lk{ mtx_ };
0118 set_exception_( except, lk);
0119 }
0120
0121 std::exception_ptr get_exception_ptr() {
0122 std::unique_lock< mutex > lk{ mtx_ };
0123 return get_exception_ptr_( lk);
0124 }
0125
0126 void wait() const {
0127 std::unique_lock< mutex > lk{ mtx_ };
0128 wait_( lk);
0129 }
0130
0131 template< typename Rep, typename Period >
0132 future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
0133 std::unique_lock< mutex > lk{ mtx_ };
0134 return wait_for_( lk, timeout_duration);
0135 }
0136
0137 template< typename Clock, typename Duration >
0138 future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
0139 std::unique_lock< mutex > lk{ mtx_ };
0140 return wait_until_( lk, timeout_time);
0141 }
0142
0143 friend inline
0144 void intrusive_ptr_add_ref( shared_state_base * p) noexcept {
0145 p->use_count_.fetch_add( 1, std::memory_order_relaxed);
0146 }
0147
0148 friend inline
0149 void intrusive_ptr_release( shared_state_base * p) noexcept {
0150 if ( 1 == p->use_count_.fetch_sub( 1, std::memory_order_release) ) {
0151 std::atomic_thread_fence( std::memory_order_acquire);
0152 p->deallocate_future();
0153 }
0154 }
0155 };
0156
0157 template< typename R >
0158 class shared_state : public shared_state_base {
0159 private:
0160 typename std::aligned_storage< sizeof( R), alignof( R) >::type storage_{};
0161
0162 void set_value_( R const& value, std::unique_lock< mutex > & lk) {
0163 BOOST_ASSERT( lk.owns_lock() );
0164 if ( BOOST_UNLIKELY( ready_) ) {
0165 throw promise_already_satisfied{};
0166 }
0167 ::new ( static_cast< void * >( std::addressof( storage_) ) ) R( value );
0168 mark_ready_and_notify_( lk);
0169 }
0170
0171 void set_value_( R && value, std::unique_lock< mutex > & lk) {
0172 BOOST_ASSERT( lk.owns_lock() );
0173 if ( BOOST_UNLIKELY( ready_) ) {
0174 throw promise_already_satisfied{};
0175 }
0176 ::new ( static_cast< void * >( std::addressof( storage_) ) ) R( std::move( value) );
0177 mark_ready_and_notify_( lk);
0178 }
0179
0180 R & get_( std::unique_lock< mutex > & lk) {
0181 BOOST_ASSERT( lk.owns_lock() );
0182 wait_( lk);
0183 if ( except_) {
0184 std::rethrow_exception( except_);
0185 }
0186 return * reinterpret_cast< R * >( std::addressof( storage_) );
0187 }
0188
0189 public:
0190 typedef intrusive_ptr< shared_state > ptr_type;
0191
0192 shared_state() = default;
0193
0194 virtual ~shared_state() {
0195 if ( ready_ && ! except_) {
0196 reinterpret_cast< R * >( std::addressof( storage_) )->~R();
0197 }
0198 }
0199
0200 shared_state( shared_state const&) = delete;
0201 shared_state & operator=( shared_state const&) = delete;
0202
0203 void set_value( R const& value) {
0204 std::unique_lock< mutex > lk{ mtx_ };
0205 set_value_( value, lk);
0206 }
0207
0208 void set_value( R && value) {
0209 std::unique_lock< mutex > lk{ mtx_ };
0210 set_value_( std::move( value), lk);
0211 }
0212
0213 R & get() {
0214 std::unique_lock< mutex > lk{ mtx_ };
0215 return get_( lk);
0216 }
0217 };
0218
0219 template< typename R >
0220 class shared_state< R & > : public shared_state_base {
0221 private:
0222 R * value_{ nullptr };
0223
0224 void set_value_( R & value, std::unique_lock< mutex > & lk) {
0225 BOOST_ASSERT( lk.owns_lock() );
0226 if ( BOOST_UNLIKELY( ready_) ) {
0227 throw promise_already_satisfied();
0228 }
0229 value_ = std::addressof( value);
0230 mark_ready_and_notify_( lk);
0231 }
0232
0233 R & get_( std::unique_lock< mutex > & lk) {
0234 BOOST_ASSERT( lk.owns_lock() );
0235 wait_( lk);
0236 if ( except_) {
0237 std::rethrow_exception( except_);
0238 }
0239 return * value_;
0240 }
0241
0242 public:
0243 typedef intrusive_ptr< shared_state > ptr_type;
0244
0245 shared_state() = default;
0246
0247 virtual ~shared_state() = default;
0248
0249 shared_state( shared_state const&) = delete;
0250 shared_state & operator=( shared_state const&) = delete;
0251
0252 void set_value( R & value) {
0253 std::unique_lock< mutex > lk{ mtx_ };
0254 set_value_( value, lk);
0255 }
0256
0257 R & get() {
0258 std::unique_lock< mutex > lk{ mtx_ };
0259 return get_( lk);
0260 }
0261 };
0262
0263 template<>
0264 class shared_state< void > : public shared_state_base {
0265 private:
0266 inline
0267 void set_value_( std::unique_lock< mutex > & lk) {
0268 BOOST_ASSERT( lk.owns_lock() );
0269 if ( BOOST_UNLIKELY( ready_) ) {
0270 throw promise_already_satisfied();
0271 }
0272 mark_ready_and_notify_( lk);
0273 }
0274
0275 inline
0276 void get_( std::unique_lock< mutex > & lk) {
0277 BOOST_ASSERT( lk.owns_lock() );
0278 wait_( lk);
0279 if ( except_) {
0280 std::rethrow_exception( except_);
0281 }
0282 }
0283
0284 public:
0285 typedef intrusive_ptr< shared_state > ptr_type;
0286
0287 shared_state() = default;
0288
0289 virtual ~shared_state() = default;
0290
0291 shared_state( shared_state const&) = delete;
0292 shared_state & operator=( shared_state const&) = delete;
0293
0294 inline
0295 void set_value() {
0296 std::unique_lock< mutex > lk{ mtx_ };
0297 set_value_( lk);
0298 }
0299
0300 inline
0301 void get() {
0302 std::unique_lock< mutex > lk{ mtx_ };
0303 get_( lk);
0304 }
0305 };
0306
0307 }}}
0308
0309 #ifdef BOOST_HAS_ABI_HEADERS
0310 # include BOOST_ABI_SUFFIX
0311 #endif
0312
0313 #endif