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