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