]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/include/boost/fiber/future/future.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / fiber / include / boost / fiber / future / future.hpp
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_FUTURE_HPP
8 #define BOOST_FIBERS_FUTURE_HPP
9
10 #include <algorithm>
11 #include <chrono>
12 #include <exception>
13
14 #include <boost/config.hpp>
15
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>
20
21 namespace boost {
22 namespace fibers {
23 namespace detail {
24
25 template< typename R >
26 struct future_base {
27 typedef typename shared_state< R >::ptr_t ptr_t;
28
29 ptr_t state_{};
30
31 constexpr future_base() noexcept = default;
32
33 explicit future_base( ptr_t const& p) noexcept :
34 state_{ p } {
35 }
36
37 ~future_base() = default;
38
39 future_base( future_base const& other) :
40 state_{ other.state_ } {
41 }
42
43 future_base( future_base && other) noexcept :
44 state_{ other.state_ } {
45 other.state_.reset();
46 }
47
48 future_base & operator=( future_base const& other) noexcept {
49 if ( this == & other) return * this;
50 state_ = other.state_;
51 return * this;
52 }
53
54 future_base & operator=( future_base && other) noexcept {
55 if ( this == & other) return * this;
56 state_ = other.state_;
57 other.state_.reset();
58 return * this;
59 }
60
61 bool valid() const noexcept {
62 return nullptr != state_.get();
63 }
64
65 std::exception_ptr get_exception_ptr() {
66 if ( ! valid() ) {
67 throw future_uninitialized{};
68 }
69 return state_->get_exception_ptr();
70 }
71
72 void wait() const {
73 if ( ! valid() ) {
74 throw future_uninitialized{};
75 }
76 state_->wait();
77 }
78
79 template< typename Rep, typename Period >
80 future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
81 if ( ! valid() ) {
82 throw future_uninitialized{};
83 }
84 return state_->wait_for( timeout_duration);
85 }
86
87 template< typename Clock, typename Duration >
88 future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
89 if ( ! valid() ) {
90 throw future_uninitialized{};
91 }
92 return state_->wait_until( timeout_time);
93 }
94 };
95
96 template< typename R >
97 struct promise_base;
98
99 }
100
101 template< typename R >
102 class shared_future;
103
104 template< typename Signature >
105 class packaged_task;
106
107 template< typename R >
108 class future : private detail::future_base< R > {
109 private:
110 typedef detail::future_base< R > base_t;
111
112 friend struct detail::promise_base< R >;
113 friend class shared_future< R >;
114 template< typename Signature >
115 friend class packaged_task;
116
117 explicit future( typename base_t::ptr_t const& p) noexcept :
118 base_t{ p } {
119 }
120
121 public:
122 constexpr future() noexcept = default;
123
124 future( future const&) = delete;
125 future & operator=( future const&) = delete;
126
127 future( future && other) noexcept :
128 base_t{ std::move( other) } {
129 }
130
131 future & operator=( future && other) noexcept {
132 if ( this == & other) return * this;
133 base_t::operator=( std::move( other) );
134 return * this;
135 }
136
137 shared_future< R > share();
138
139 R get() {
140 if ( ! base_t::valid() ) {
141 throw future_uninitialized{};
142 }
143 typename base_t::ptr_t tmp{};
144 tmp.swap( base_t::state_);
145 return std::move( tmp->get() );
146 }
147
148 using base_t::valid;
149 using base_t::get_exception_ptr;
150 using base_t::wait;
151 using base_t::wait_for;
152 using base_t::wait_until;
153 };
154
155 template< typename R >
156 class future< R & > : private detail::future_base< R & > {
157 private:
158 typedef detail::future_base< R & > base_t;
159
160 friend struct detail::promise_base< R & >;
161 friend class shared_future< R & >;
162 template< typename Signature >
163 friend class packaged_task;
164
165 explicit future( typename base_t::ptr_t const& p) noexcept :
166 base_t{ p } {
167 }
168
169 public:
170 constexpr future() noexcept = default;
171
172 future( future const&) = delete;
173 future & operator=( future const&) = delete;
174
175 future( future && other) noexcept :
176 base_t{ std::move( other) } {
177 }
178
179 future & operator=( future && other) noexcept {
180 if ( this == & other) return * this;
181 base_t::operator=( std::move( other) );
182 return * this;
183 }
184
185 shared_future< R & > share();
186
187 R & get() {
188 if ( ! base_t::valid() ) {
189 throw future_uninitialized{};
190 }
191 typename base_t::ptr_t tmp{};
192 tmp.swap( base_t::state_);
193 return tmp->get();
194 }
195
196 using base_t::valid;
197 using base_t::get_exception_ptr;
198 using base_t::wait;
199 using base_t::wait_for;
200 using base_t::wait_until;
201 };
202
203 template<>
204 class future< void > : private detail::future_base< void > {
205 private:
206 typedef detail::future_base< void > base_t;
207
208 friend struct detail::promise_base< void >;
209 friend class shared_future< void >;
210 template< typename Signature >
211 friend class packaged_task;
212
213 explicit future( base_t::ptr_t const& p) noexcept :
214 base_t{ p } {
215 }
216
217 public:
218 constexpr future() noexcept = default;
219
220 future( future const&) = delete;
221 future & operator=( future const&) = delete;
222
223 inline
224 future( future && other) noexcept :
225 base_t{ std::move( other) } {
226 }
227
228 inline
229 future & operator=( future && other) noexcept {
230 if ( this == & other) return * this;
231 base_t::operator=( std::move( other) );
232 return * this;
233 }
234
235 shared_future< void > share();
236
237 inline
238 void get() {
239 if ( ! base_t::valid() ) {
240 throw future_uninitialized{};
241 }
242 base_t::ptr_t tmp{};
243 tmp.swap( base_t::state_);
244 tmp->get();
245 }
246
247 using base_t::valid;
248 using base_t::get_exception_ptr;
249 using base_t::wait;
250 using base_t::wait_for;
251 using base_t::wait_until;
252 };
253
254
255 template< typename R >
256 class shared_future : private detail::future_base< R > {
257 private:
258 typedef detail::future_base< R > base_t;
259
260 explicit shared_future( typename base_t::ptr_t const& p) noexcept :
261 base_t{ p } {
262 }
263
264 public:
265 constexpr shared_future() noexcept = default;
266
267 ~shared_future() = default;
268
269 shared_future( shared_future const& other) :
270 base_t{ other } {
271 }
272
273 shared_future( shared_future && other) noexcept :
274 base_t{ std::move( other) } {
275 }
276
277 shared_future( future< R > && other) noexcept :
278 base_t{ std::move( other) } {
279 }
280
281 shared_future & operator=( shared_future const& other) noexcept {
282 if ( this == & other) return * this;
283 base_t::operator=( other);
284 return * this;
285 }
286
287 shared_future & operator=( shared_future && other) noexcept {
288 if ( this == & other) return * this;
289 base_t::operator=( std::move( other) );
290 return * this;
291 }
292
293 shared_future & operator=( future< R > && other) noexcept {
294 base_t::operator=( std::move( other) );
295 return * this;
296 }
297
298 R const& get() const {
299 if ( ! valid() ) {
300 throw future_uninitialized{};
301 }
302 return base_t::state_->get();
303 }
304
305 using base_t::valid;
306 using base_t::get_exception_ptr;
307 using base_t::wait;
308 using base_t::wait_for;
309 using base_t::wait_until;
310 };
311
312 template< typename R >
313 class shared_future< R & > : private detail::future_base< R & > {
314 private:
315 typedef detail::future_base< R & > base_t;
316
317 explicit shared_future( typename base_t::ptr_t const& p) noexcept :
318 base_t{ p } {
319 }
320
321 public:
322 constexpr shared_future() noexcept = default;
323
324 ~shared_future() = default;
325
326 shared_future( shared_future const& other) :
327 base_t{ other } {
328 }
329
330 shared_future( shared_future && other) noexcept :
331 base_t{ std::move( other) } {
332 }
333
334 shared_future( future< R & > && other) noexcept :
335 base_t{ std::move( other) } {
336 }
337
338 shared_future & operator=( shared_future const& other) noexcept {
339 if ( this == & other) return * this;
340 base_t::operator=( other);
341 return * this;
342 }
343
344 shared_future & operator=( shared_future && other) noexcept {
345 if ( this == & other) return * this;
346 base_t::operator=( std::move( other) );
347 return * this;
348 }
349
350 shared_future & operator=( future< R & > && other) noexcept {
351 base_t::operator=( std::move( other) );
352 return * this;
353 }
354
355 R & get() const {
356 if ( ! valid() ) {
357 throw future_uninitialized{};
358 }
359 return base_t::state_->get();
360 }
361
362 using base_t::valid;
363 using base_t::get_exception_ptr;
364 using base_t::wait;
365 using base_t::wait_for;
366 using base_t::wait_until;
367 };
368
369 template<>
370 class shared_future< void > : private detail::future_base< void > {
371 private:
372 typedef detail::future_base< void > base_t;
373
374 explicit shared_future( base_t::ptr_t const& p) noexcept :
375 base_t{ p } {
376 }
377
378 public:
379 constexpr shared_future() noexcept = default;
380
381 ~shared_future() = default;
382
383 inline
384 shared_future( shared_future const& other) :
385 base_t{ other } {
386 }
387
388 inline
389 shared_future( shared_future && other) noexcept :
390 base_t{ std::move( other) } {
391 }
392
393 inline
394 shared_future( future< void > && other) noexcept :
395 base_t{ std::move( other) } {
396 }
397
398 inline
399 shared_future & operator=( shared_future const& other) noexcept {
400 if ( this == & other) return * this;
401 base_t::operator=( other);
402 return * this;
403 }
404
405 inline
406 shared_future & operator=( shared_future && other) noexcept {
407 if ( this == & other) return * this;
408 base_t::operator=( std::move( other) );
409 return * this;
410 }
411
412 inline
413 shared_future & operator=( future< void > && other) noexcept {
414 base_t::operator=( std::move( other) );
415 return * this;
416 }
417
418 inline
419 void get() const {
420 if ( ! valid() ) {
421 throw future_uninitialized{};
422 }
423 base_t::state_->get();
424 }
425
426 using base_t::valid;
427 using base_t::get_exception_ptr;
428 using base_t::wait;
429 using base_t::wait_for;
430 using base_t::wait_until;
431 };
432
433
434 template< typename R >
435 shared_future< R >
436 future< R >::share() {
437 if ( ! base_t::valid() ) {
438 throw future_uninitialized{};
439 }
440 return shared_future< R >{ std::move( * this) };
441 }
442
443 template< typename R >
444 shared_future< R & >
445 future< R & >::share() {
446 if ( ! base_t::valid() ) {
447 throw future_uninitialized{};
448 }
449 return shared_future< R & >{ std::move( * this) };
450 }
451
452 inline
453 shared_future< void >
454 future< void >::share() {
455 if ( ! base_t::valid() ) {
456 throw future_uninitialized{};
457 }
458 return shared_future< void >{ std::move( * this) };
459 }
460
461 }}
462
463 #endif