]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/fiber/future/promise.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / fiber / future / promise.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_PROMISE_HPP
8 #define BOOST_FIBERS_PROMISE_HPP
9
10 #include <algorithm>
11 #include <memory>
12 #include <utility>
13
14 #include <boost/config.hpp>
15 #include <boost/core/pointer_traits.hpp>
16
17 #include <boost/fiber/exceptions.hpp>
18 #include <boost/fiber/future/detail/shared_state.hpp>
19 #include <boost/fiber/future/detail/shared_state_object.hpp>
20 #include <boost/fiber/future/future.hpp>
21
22 namespace boost {
23 namespace fibers {
24 namespace detail {
25
26 template< typename R >
27 struct promise_base {
28 typedef typename shared_state< R >::ptr_type ptr_type;
29
30 bool obtained_{ false };
31 ptr_type future_{};
32
33 promise_base() :
34 promise_base{ std::allocator_arg, std::allocator< promise_base >{} } {
35 }
36
37 template< typename Allocator >
38 promise_base( std::allocator_arg_t, Allocator alloc) {
39 typedef detail::shared_state_object< R, Allocator > object_type;
40 typedef std::allocator_traits< typename object_type::allocator_type > traits_type;
41 typedef pointer_traits< typename traits_type::pointer > ptrait_type;
42 typename object_type::allocator_type a{ alloc };
43 typename traits_type::pointer ptr{ traits_type::allocate( a, 1) };
44 typename ptrait_type::element_type* p = boost::to_address(ptr);
45
46 try {
47 traits_type::construct( a, p, a);
48 } catch (...) {
49 traits_type::deallocate( a, ptr, 1);
50 throw;
51 }
52 future_.reset(p);
53 }
54
55 ~promise_base() {
56 if ( future_) {
57 future_->owner_destroyed();
58 }
59 }
60
61 promise_base( promise_base const&) = delete;
62 promise_base & operator=( promise_base const&) = delete;
63
64 promise_base( promise_base && other) noexcept :
65 obtained_{ other.obtained_ },
66 future_{ std::move( other.future_) } {
67 other.obtained_ = false;
68 }
69
70 promise_base & operator=( promise_base && other) noexcept {
71 if ( BOOST_LIKELY( this != & other) ) {
72 promise_base tmp{ std::move( other) };
73 swap( tmp);
74 }
75 return * this;
76 }
77
78 future< R > get_future() {
79 if ( BOOST_UNLIKELY( obtained_) ) {
80 throw future_already_retrieved{};
81 }
82 if ( BOOST_UNLIKELY( ! future_) ) {
83 throw promise_uninitialized{};
84 }
85 obtained_ = true;
86 return future< R >{ future_ };
87 }
88
89 void swap( promise_base & other) noexcept {
90 std::swap( obtained_, other.obtained_);
91 future_.swap( other.future_);
92 }
93
94 void set_exception( std::exception_ptr p) {
95 if ( BOOST_UNLIKELY( ! future_) ) {
96 throw promise_uninitialized{};
97 }
98 future_->set_exception( p);
99 }
100 };
101
102 }
103
104 template< typename R >
105 class promise : private detail::promise_base< R > {
106 private:
107 typedef detail::promise_base< R > base_type;
108
109 public:
110 promise() = default;
111
112 template< typename Allocator >
113 promise( std::allocator_arg_t, Allocator alloc) :
114 base_type{ std::allocator_arg, alloc } {
115 }
116
117 promise( promise const&) = delete;
118 promise & operator=( promise const&) = delete;
119
120 promise( promise && other) noexcept = default;
121 promise & operator=( promise && other) = default;
122
123 void set_value( R const& value) {
124 if ( BOOST_UNLIKELY( ! base_type::future_) ) {
125 throw promise_uninitialized{};
126 }
127 base_type::future_->set_value( value);
128 }
129
130 void set_value( R && value) {
131 if ( BOOST_UNLIKELY( ! base_type::future_) ) {
132 throw promise_uninitialized{};
133 }
134 base_type::future_->set_value( std::move( value) );
135 }
136
137 void swap( promise & other) noexcept {
138 base_type::swap( other);
139 }
140
141 using base_type::get_future;
142 using base_type::set_exception;
143 };
144
145 template< typename R >
146 class promise< R & > : private detail::promise_base< R & > {
147 private:
148 typedef detail::promise_base< R & > base_type;
149
150 public:
151 promise() = default;
152
153 template< typename Allocator >
154 promise( std::allocator_arg_t, Allocator alloc) :
155 base_type{ std::allocator_arg, alloc } {
156 }
157
158 promise( promise const&) = delete;
159 promise & operator=( promise const&) = delete;
160
161 promise( promise && other) noexcept = default;
162 promise & operator=( promise && other) noexcept = default;
163
164 void set_value( R & value) {
165 if ( BOOST_UNLIKELY( ! base_type::future_) ) {
166 throw promise_uninitialized{};
167 }
168 base_type::future_->set_value( value);
169 }
170
171 void swap( promise & other) noexcept {
172 base_type::swap( other);
173 }
174
175 using base_type::get_future;
176 using base_type::set_exception;
177 };
178
179 template<>
180 class promise< void > : private detail::promise_base< void > {
181 private:
182 typedef detail::promise_base< void > base_type;
183
184 public:
185 promise() = default;
186
187 template< typename Allocator >
188 promise( std::allocator_arg_t, Allocator alloc) :
189 base_type{ std::allocator_arg, alloc } {
190 }
191
192 promise( promise const&) = delete;
193 promise & operator=( promise const&) = delete;
194
195 promise( promise && other) noexcept = default;
196 promise & operator=( promise && other) noexcept = default;
197
198 inline
199 void set_value() {
200 if ( BOOST_UNLIKELY( ! base_type::future_) ) {
201 throw promise_uninitialized{};
202 }
203 base_type::future_->set_value();
204 }
205
206 inline
207 void swap( promise & other) noexcept {
208 base_type::swap( other);
209 }
210
211 using base_type::get_future;
212 using base_type::set_exception;
213 };
214
215 template< typename R >
216 void swap( promise< R > & l, promise< R > & r) noexcept {
217 l.swap( r);
218 }
219
220 }}
221
222 #endif // BOOST_FIBERS_PROMISE_HPP