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