]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/fiber/include/boost/fiber/future/detail/shared_state.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / fiber / include / boost / fiber / future / detail / shared_state.hpp
CommitLineData
7c673cae
FG
1
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)
6
7#ifndef BOOST_FIBERS_DETAIL_SHARED_STATE_H
8#define BOOST_FIBERS_DETAIL_SHARED_STATE_H
9
10#include <algorithm>
11#include <atomic>
12#include <chrono>
13#include <cstddef>
14#include <exception>
15#include <memory>
16#include <mutex>
17#include <type_traits>
18
19#include <boost/assert.hpp>
20#include <boost/config.hpp>
21#include <boost/intrusive_ptr.hpp>
22
23#include <boost/fiber/detail/config.hpp>
24#include <boost/fiber/future/future_status.hpp>
25#include <boost/fiber/condition_variable.hpp>
26#include <boost/fiber/exceptions.hpp>
27#include <boost/fiber/mutex.hpp>
28
29#ifdef BOOST_HAS_ABI_HEADERS
30# include BOOST_ABI_PREFIX
31#endif
32
33namespace boost {
34namespace fibers {
35namespace detail {
36
37class shared_state_base {
38private:
39 std::atomic< std::size_t > use_count_{ 0 };
40 mutable condition_variable waiters_{};
41
42protected:
43 mutable mutex mtx_{};
44 bool ready_{ false };
45 std::exception_ptr except_{};
46
47 void mark_ready_and_notify_( std::unique_lock< mutex > & lk) noexcept {
48 BOOST_ASSERT( lk.owns_lock() );
49 ready_ = true;
50 lk.unlock();
51 waiters_.notify_all();
52 }
53
54 void owner_destroyed_( std::unique_lock< mutex > & lk) {
55 BOOST_ASSERT( lk.owns_lock() );
56 if ( ! ready_) {
57 set_exception_(
58 std::make_exception_ptr( broken_promise() ),
59 lk);
60 }
61 }
62
63 void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
64 BOOST_ASSERT( lk.owns_lock() );
65 if ( ready_) {
66 throw promise_already_satisfied();
67 }
68 except_ = except;
69 mark_ready_and_notify_( lk);
70 }
71
72 std::exception_ptr get_exception_ptr_( std::unique_lock< mutex > & lk) {
73 BOOST_ASSERT( lk.owns_lock() );
74 wait_( lk);
75 return except_;
76 }
77
78 void wait_( std::unique_lock< mutex > & lk) const {
79 BOOST_ASSERT( lk.owns_lock() );
80 waiters_.wait( lk, [this](){ return ready_; });
81 }
82
83 template< typename Rep, typename Period >
84 future_status wait_for_( std::unique_lock< mutex > & lk,
85 std::chrono::duration< Rep, Period > const& timeout_duration) const {
86 BOOST_ASSERT( lk.owns_lock() );
87 return waiters_.wait_for( lk, timeout_duration, [this](){ return ready_; })
88 ? future_status::ready
89 : future_status::timeout;
90 }
91
92 template< typename Clock, typename Duration >
93 future_status wait_until_( std::unique_lock< mutex > & lk,
94 std::chrono::time_point< Clock, Duration > const& timeout_time) const {
95 BOOST_ASSERT( lk.owns_lock() );
96 return waiters_.wait_until( lk, timeout_time, [this](){ return ready_; })
97 ? future_status::ready
98 : future_status::timeout;
99 }
100
101 virtual void deallocate_future() noexcept = 0;
102
103public:
104 shared_state_base() = default;
105
106 virtual ~shared_state_base() = default;
107
108 shared_state_base( shared_state_base const&) = delete;
109 shared_state_base & operator=( shared_state_base const&) = delete;
110
111 void owner_destroyed() {
112 std::unique_lock< mutex > lk( mtx_);
113 owner_destroyed_( lk);
114 }
115
116 void set_exception( std::exception_ptr except) {
117 std::unique_lock< mutex > lk( mtx_);
118 set_exception_( except, lk);
119 }
120
121 std::exception_ptr get_exception_ptr() {
122 std::unique_lock< mutex > lk( mtx_);
123 return get_exception_ptr_( lk);
124 }
125
126 void wait() const {
127 std::unique_lock< mutex > lk( mtx_);
128 wait_( lk);
129 }
130
131 template< typename Rep, typename Period >
132 future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
133 std::unique_lock< mutex > lk( mtx_);
134 return wait_for_( lk, timeout_duration);
135 }
136
137 template< typename Clock, typename Duration >
138 future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
139 std::unique_lock< mutex > lk( mtx_);
140 return wait_until_( lk, timeout_time);
141 }
142
143 friend inline
144 void intrusive_ptr_add_ref( shared_state_base * p) noexcept {
145 ++p->use_count_;
146 }
147
148 friend inline
149 void intrusive_ptr_release( shared_state_base * p) noexcept {
150 if ( 0 == --p->use_count_) {
151 p->deallocate_future();
152 }
153 }
154};
155
156template< typename R >
157class shared_state : public shared_state_base {
158private:
159 typename std::aligned_storage< sizeof( R), alignof( R) >::type storage_{};
160
161 void set_value_( R const& value, std::unique_lock< mutex > & lk) {
162 BOOST_ASSERT( lk.owns_lock() );
163 if ( ready_) {
164 throw promise_already_satisfied();
165 }
166 ::new ( static_cast< void * >( std::addressof( storage_) ) ) R( value);
167 mark_ready_and_notify_( lk);
168 }
169
170 void set_value_( R && value, std::unique_lock< mutex > & lk) {
171 BOOST_ASSERT( lk.owns_lock() );
172 if ( ready_) {
173 throw promise_already_satisfied();
174 }
175 ::new ( static_cast< void * >( std::addressof( storage_) ) ) R( std::move( value) );
176 mark_ready_and_notify_( lk);
177 }
178
179 R & get_( std::unique_lock< mutex > & lk) {
180 BOOST_ASSERT( lk.owns_lock() );
181 wait_( lk);
182 if ( except_) {
183 std::rethrow_exception( except_);
184 }
185 return * reinterpret_cast< R * >( std::addressof( storage_) );
186 }
187
188public:
189 typedef intrusive_ptr< shared_state > ptr_t;
190
191 shared_state() = default;
192
193 virtual ~shared_state() {
194 if ( ready_ && ! except_) {
195 reinterpret_cast< R * >( & storage_)->~R();
196 }
197 }
198
199 shared_state( shared_state const&) = delete;
200 shared_state & operator=( shared_state const&) = delete;
201
202 void set_value( R const& value) {
203 std::unique_lock< mutex > lk( mtx_);
204 set_value_( value, lk);
205 }
206
207 void set_value( R && value) {
208 std::unique_lock< mutex > lk( mtx_);
209 set_value_( std::move( value), lk);
210 }
211
212 R & get() {
213 std::unique_lock< mutex > lk( mtx_);
214 return get_( lk);
215 }
216};
217
218template< typename R >
219class shared_state< R & > : public shared_state_base {
220private:
221 R * value_{ nullptr };
222
223 void set_value_( R & value, std::unique_lock< mutex > & lk) {
224 BOOST_ASSERT( lk.owns_lock() );
225 if ( ready_) {
226 throw promise_already_satisfied();
227 }
228 value_ = std::addressof( value);
229 mark_ready_and_notify_( lk);
230 }
231
232 R & get_( std::unique_lock< mutex > & lk) {
233 BOOST_ASSERT( lk.owns_lock() );
234 wait_( lk);
235 if ( except_) {
236 std::rethrow_exception( except_);
237 }
238 return * value_;
239 }
240
241public:
242 typedef intrusive_ptr< shared_state > ptr_t;
243
244 shared_state() = default;
245
246 virtual ~shared_state() = default;
247
248 shared_state( shared_state const&) = delete;
249 shared_state & operator=( shared_state const&) = delete;
250
251 void set_value( R & value) {
252 std::unique_lock< mutex > lk( mtx_);
253 set_value_( value, lk);
254 }
255
256 R & get() {
257 std::unique_lock< mutex > lk( mtx_);
258 return get_( lk);
259 }
260};
261
262template<>
263class shared_state< void > : public shared_state_base {
264private:
265 inline
266 void set_value_( std::unique_lock< mutex > & lk) {
267 BOOST_ASSERT( lk.owns_lock() );
268 if ( ready_) {
269 throw promise_already_satisfied();
270 }
271 mark_ready_and_notify_( lk);
272 }
273
274 inline
275 void get_( std::unique_lock< mutex > & lk) {
276 BOOST_ASSERT( lk.owns_lock() );
277 wait_( lk);
278 if ( except_) {
279 std::rethrow_exception( except_);
280 }
281 }
282
283public:
284 typedef intrusive_ptr< shared_state > ptr_t;
285
286 shared_state() = default;
287
288 virtual ~shared_state() = default;
289
290 shared_state( shared_state const&) = delete;
291 shared_state & operator=( shared_state const&) = delete;
292
293 inline
294 void set_value() {
295 std::unique_lock< mutex > lk( mtx_);
296 set_value_( lk);
297 }
298
299 inline
300 void get() {
301 std::unique_lock< mutex > lk( mtx_);
302 get_( lk);
303 }
304};
305
306}}}
307
308#ifdef BOOST_HAS_ABI_HEADERS
309# include BOOST_ABI_SUFFIX
310#endif
311
312#endif // BOOST_FIBERS_DETAIL_SHARED_STATE_H