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