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