]> git.proxmox.com Git - ceph.git/blob - 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
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
26 namespace boost {
27 namespace coroutines2 {
28 namespace detail {
29
30 // push_coroutine< T >
31
32 template< typename T >
33 void
34 push_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
43 template< typename T >
44 template< typename StackAllocator, typename Fn >
45 push_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
114 template< typename T >
115 push_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
123 template< typename T >
124 void
125 push_coroutine< T >::control_block::deallocate() noexcept {
126 if ( state_t::none != ( state & state_t::unwind) ) {
127 destroy( this);
128 }
129 }
130
131 template< typename T >
132 void
133 push_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
142 template< typename T >
143 void
144 push_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
153 template< typename T >
154 bool
155 push_coroutine< T >::control_block::valid() const noexcept {
156 return state_t::none == ( state & state_t::complete );
157 }
158
159
160 // push_coroutine< T & >
161
162 template< typename T >
163 void
164 push_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
173 template< typename T >
174 template< typename StackAllocator, typename Fn >
175 push_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
244 template< typename T >
245 push_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
253 template< typename T >
254 void
255 push_coroutine< T & >::control_block::deallocate() noexcept {
256 if ( state_t::none != ( state & state_t::unwind) ) {
257 destroy( this);
258 }
259 }
260
261 template< typename T >
262 void
263 push_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
272 template< typename T >
273 bool
274 push_coroutine< T & >::control_block::valid() const noexcept {
275 return state_t::none == ( state & state_t::complete );
276 }
277
278
279 // push_coroutine< void >
280
281 inline
282 void
283 push_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
292 template< typename StackAllocator, typename Fn >
293 push_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
354 inline
355 push_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
363 inline
364 void
365 push_coroutine< void >::control_block::deallocate() noexcept {
366 if ( state_t::none != ( state & state_t::unwind) ) {
367 destroy( this);
368 }
369 }
370
371 inline
372 void
373 push_coroutine< void >::control_block::resume() {
374 ctx = ctx();
375 if ( except) {
376 std::rethrow_exception( except);
377 }
378 }
379
380 inline
381 bool
382 push_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