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