]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/coroutine2/detail/pull_control_block_cc.ipp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / coroutine2 / detail / pull_control_block_cc.ipp
1
2 // Copyright Oliver Kowalke 2016.
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_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
8 #define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
9
10 #include <algorithm>
11 #include <exception>
12 #include <memory>
13 #include <tuple>
14
15 #include <boost/assert.hpp>
16 #include <boost/config.hpp>
17
18 #include <boost/context/continuation.hpp>
19
20 #include <boost/coroutine2/detail/config.hpp>
21 #include <boost/coroutine2/detail/forced_unwind.hpp>
22 #include <boost/coroutine2/detail/wrap.hpp>
23
24 #ifdef BOOST_HAS_ABI_HEADERS
25 # include BOOST_ABI_PREFIX
26 #endif
27
28 namespace boost {
29 namespace coroutines2 {
30 namespace detail {
31
32 // pull_coroutine< T >
33
34 template< typename T >
35 void
36 pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
37 boost::context::continuation c = std::move( cb->c);
38 // destroy control structure
39 cb->~control_block();
40 // destroy coroutine's stack
41 cb->state |= state_t::destroy;
42 }
43
44 template< typename T >
45 template< typename StackAllocator, typename Fn >
46 pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
47 Fn && fn) :
48 c{},
49 other{ nullptr },
50 state{ state_t::unwind },
51 except{},
52 bvalid{ false },
53 storage{} {
54 #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
55 c = boost::context::callcc(
56 std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
57 wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
58 // create synthesized push_coroutine< T >
59 typename push_coroutine< T >::control_block synthesized_cb{ this, c };
60 push_coroutine< T > synthesized{ & synthesized_cb };
61 other = & synthesized_cb;
62 if ( state_t::none == ( state & state_t::destroy) ) {
63 try {
64 auto fn = std::move( fn_);
65 // call coroutine-fn with synthesized push_coroutine as argument
66 fn( synthesized);
67 } catch ( boost::context::detail::forced_unwind const&) {
68 throw;
69 } catch (...) {
70 // store other exceptions in exception-pointer
71 except = std::current_exception();
72 }
73 }
74 // set termination flags
75 state |= state_t::complete;
76 // jump back
77 return other->c.resume();
78 },
79 std::forward< Fn >( fn) ) );
80 #else
81 c = boost::context::callcc(
82 std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
83 [this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
84 // create synthesized push_coroutine< T >
85 typename push_coroutine< T >::control_block synthesized_cb{ this, c };
86 push_coroutine< T > synthesized{ & synthesized_cb };
87 other = & synthesized_cb;
88 if ( state_t::none == ( state & state_t::destroy) ) {
89 try {
90 auto fn = std::move( fn_);
91 // call coroutine-fn with synthesized push_coroutine as argument
92 fn( synthesized);
93 } catch ( boost::context::detail::forced_unwind const&) {
94 throw;
95 } catch (...) {
96 // store other exceptions in exception-pointer
97 except = std::current_exception();
98 }
99 }
100 // set termination flags
101 state |= state_t::complete;
102 // jump back
103 return other->c.resume();
104 });
105 #endif
106 if ( except) {
107 std::rethrow_exception( except);
108 }
109 }
110
111 template< typename T >
112 pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
113 boost::context::continuation & c_) noexcept :
114 c{ std::move( c_) },
115 other{ cb },
116 state{ state_t::none },
117 except{},
118 bvalid{ false },
119 storage{} {
120 }
121
122 template< typename T >
123 pull_coroutine< T >::control_block::~control_block() {
124 // destroy data if set
125 if ( bvalid) {
126 reinterpret_cast< T * >( std::addressof( storage) )->~T();
127 }
128 }
129
130 template< typename T >
131 void
132 pull_coroutine< T >::control_block::deallocate() noexcept {
133 if ( state_t::none != ( state & state_t::unwind) ) {
134 destroy( this);
135 }
136 }
137
138 template< typename T >
139 void
140 pull_coroutine< T >::control_block::resume() {
141 c = c.resume();
142 if ( except) {
143 std::rethrow_exception( except);
144 }
145 }
146
147 template< typename T >
148 void
149 pull_coroutine< T >::control_block::set( T const& t) {
150 // destroy data if set
151 if ( bvalid) {
152 reinterpret_cast< T * >( std::addressof( storage) )->~T();
153 }
154 ::new ( static_cast< void * >( std::addressof( storage) ) ) T( t);
155 bvalid = true;
156 }
157
158 template< typename T >
159 void
160 pull_coroutine< T >::control_block::set( T && t) {
161 // destroy data if set
162 if ( bvalid) {
163 reinterpret_cast< T * >( std::addressof( storage) )->~T();
164 }
165 ::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( t) );
166 bvalid = true;
167 }
168
169 template< typename T >
170 T &
171 pull_coroutine< T >::control_block::get() noexcept {
172 return * reinterpret_cast< T * >( std::addressof( storage) );
173 }
174
175 template< typename T >
176 bool
177 pull_coroutine< T >::control_block::valid() const noexcept {
178 return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
179 }
180
181
182 // pull_coroutine< T & >
183
184 template< typename T >
185 void
186 pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
187 boost::context::continuation c = std::move( cb->c);
188 // destroy control structure
189 cb->~control_block();
190 // destroy coroutine's stack
191 cb->state |= state_t::destroy;
192 }
193
194 template< typename T >
195 template< typename StackAllocator, typename Fn >
196 pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
197 Fn && fn) :
198 c{},
199 other{ nullptr },
200 state{ state_t::unwind },
201 except{},
202 bvalid{ false },
203 storage{} {
204 #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
205 c = boost::context::callcc(
206 std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
207 wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
208 // create synthesized push_coroutine< T & >
209 typename push_coroutine< T & >::control_block synthesized_cb{ this, c };
210 push_coroutine< T & > synthesized{ & synthesized_cb };
211 other = & synthesized_cb;
212 if ( state_t::none == ( state & state_t::destroy) ) {
213 try {
214 auto fn = std::move( fn_);
215 // call coroutine-fn with synthesized push_coroutine as argument
216 fn( synthesized);
217 } catch ( boost::context::detail::forced_unwind const&) {
218 throw;
219 } catch (...) {
220 // store other exceptions in exception-pointer
221 except = std::current_exception();
222 }
223 }
224 // set termination flags
225 state |= state_t::complete;
226 // jump back
227 return other->c.resume();
228 },
229 std::forward< Fn >( fn) ) );
230 #else
231 c = boost::context::callcc(
232 std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
233 [this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
234 // create synthesized push_coroutine< T & >
235 typename push_coroutine< T & >::control_block synthesized_cb{ this, c };
236 push_coroutine< T & > synthesized{ & synthesized_cb };
237 other = & synthesized_cb;
238 if ( state_t::none == ( state & state_t::destroy) ) {
239 try {
240 auto fn = std::move( fn_);
241 // call coroutine-fn with synthesized push_coroutine as argument
242 fn( synthesized);
243 } catch ( boost::context::detail::forced_unwind const&) {
244 throw;
245 } catch (...) {
246 // store other exceptions in exception-pointer
247 except = std::current_exception();
248 }
249 }
250 // set termination flags
251 state |= state_t::complete;
252 // jump back
253 return other->c.resume();
254 });
255 #endif
256 if ( except) {
257 std::rethrow_exception( except);
258 }
259 }
260
261 template< typename T >
262 pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
263 boost::context::continuation & c_) noexcept :
264 c{ std::move( c_) },
265 other{ cb },
266 state{ state_t::none },
267 except{},
268 bvalid{ false },
269 storage{} {
270 }
271
272 template< typename T >
273 void
274 pull_coroutine< T & >::control_block::deallocate() noexcept {
275 if ( state_t::none != ( state & state_t::unwind) ) {
276 destroy( this);
277 }
278 }
279
280 template< typename T >
281 void
282 pull_coroutine< T & >::control_block::resume() {
283 c = c.resume();
284 if ( except) {
285 std::rethrow_exception( except);
286 }
287 }
288
289 template< typename T >
290 void
291 pull_coroutine< T & >::control_block::set( T & t) {
292 ::new ( static_cast< void * >( std::addressof( storage) ) ) holder{ t };
293 bvalid = true;
294 }
295
296 template< typename T >
297 T &
298 pull_coroutine< T & >::control_block::get() noexcept {
299 return reinterpret_cast< holder * >( std::addressof( storage) )->t;
300 }
301
302 template< typename T >
303 bool
304 pull_coroutine< T & >::control_block::valid() const noexcept {
305 return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
306 }
307
308
309 // pull_coroutine< void >
310
311 inline
312 void
313 pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
314 boost::context::continuation c = std::move( cb->c);
315 // destroy control structure
316 cb->~control_block();
317 // destroy coroutine's stack
318 cb->state |= state_t::destroy;
319 }
320
321 template< typename StackAllocator, typename Fn >
322 pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
323 Fn && fn) :
324 c{},
325 other{ nullptr },
326 state{ state_t::unwind },
327 except{} {
328 #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
329 c = boost::context::callcc(
330 std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
331 wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
332 // create synthesized push_coroutine< void >
333 typename push_coroutine< void >::control_block synthesized_cb{ this, c };
334 push_coroutine< void > synthesized{ & synthesized_cb };
335 other = & synthesized_cb;
336 if ( state_t::none == ( state & state_t::destroy) ) {
337 try {
338 auto fn = std::move( fn_);
339 // call coroutine-fn with synthesized push_coroutine as argument
340 fn( synthesized);
341 } catch ( boost::context::detail::forced_unwind const&) {
342 throw;
343 } catch (...) {
344 // store other exceptions in exception-pointer
345 except = std::current_exception();
346 }
347 }
348 // set termination flags
349 state |= state_t::complete;
350 // jump back
351 return other->c.resume();
352 },
353 std::forward< Fn >( fn) ) );
354 #else
355 c = boost::context::callcc(
356 std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
357 [this,fn_=std::forward< Fn >( fn)]( boost::context::continuation && c) mutable {
358 // create synthesized push_coroutine< void >
359 typename push_coroutine< void >::control_block synthesized_cb{ this, c };
360 push_coroutine< void > synthesized{ & synthesized_cb };
361 other = & synthesized_cb;
362 if ( state_t::none == ( state & state_t::destroy) ) {
363 try {
364 auto fn = std::move( fn_);
365 // call coroutine-fn with synthesized push_coroutine as argument
366 fn( synthesized);
367 } catch ( boost::context::detail::forced_unwind const&) {
368 throw;
369 } catch (...) {
370 // store other exceptions in exception-pointer
371 except = std::current_exception();
372 }
373 }
374 // set termination flags
375 state |= state_t::complete;
376 // jump back to ctx
377 return other->c.resume();
378 });
379 #endif
380 if ( except) {
381 std::rethrow_exception( except);
382 }
383 }
384
385 inline
386 pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
387 boost::context::continuation & c_) noexcept :
388 c{ std::move( c_) },
389 other{ cb },
390 state{ state_t::none },
391 except{} {
392 }
393
394 inline
395 void
396 pull_coroutine< void >::control_block::deallocate() noexcept {
397 if ( state_t::none != ( state & state_t::unwind) ) {
398 destroy( this);
399 }
400 }
401
402 inline
403 void
404 pull_coroutine< void >::control_block::resume() {
405 c = c.resume();
406 if ( except) {
407 std::rethrow_exception( except);
408 }
409 }
410
411 inline
412 bool
413 pull_coroutine< void >::control_block::valid() const noexcept {
414 return nullptr != other && state_t::none == ( state & state_t::complete);
415 }
416
417 }}}
418
419 #ifdef BOOST_HAS_ABI_HEADERS
420 # include BOOST_ABI_SUFFIX
421 #endif
422
423 #endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP