File indexing completed on 2025-01-18 09:30:34
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
0008 #define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
0009
0010 #include <algorithm>
0011 #include <exception>
0012 #include <memory>
0013
0014 #include <boost/assert.hpp>
0015 #include <boost/config.hpp>
0016 #include <boost/context/detail/config.hpp>
0017
0018 #include <boost/context/fiber.hpp>
0019
0020 #include <boost/coroutine2/detail/config.hpp>
0021 #include <boost/coroutine2/detail/wrap.hpp>
0022
0023 #ifdef BOOST_HAS_ABI_HEADERS
0024 # include BOOST_ABI_PREFIX
0025 #endif
0026
0027 namespace boost {
0028 namespace coroutines2 {
0029 namespace detail {
0030
0031
0032
0033 template< typename T >
0034 void
0035 push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
0036 boost::context::fiber c = std::move( cb->c);
0037
0038 cb->~control_block();
0039
0040 cb->state |= state_t::destroy;
0041 }
0042
0043 template< typename T >
0044 template< typename StackAllocator, typename Fn >
0045 push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
0046 Fn && fn) :
0047 #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
0048 c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
0049 wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::fiber && c) mutable {
0050
0051 typename pull_coroutine< T >::control_block synthesized_cb{ this, c };
0052 pull_coroutine< T > synthesized{ & synthesized_cb };
0053 other = & synthesized_cb;
0054 other->c = std::move( other->c).resume();
0055 if ( state_t::none == ( state & state_t::destroy) ) {
0056 try {
0057 auto fn = std::move( fn_);
0058
0059 fn( synthesized);
0060 } catch ( boost::context::detail::forced_unwind const&) {
0061 throw;
0062 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
0063 } catch ( abi::__forced_unwind const&) {
0064 throw;
0065 #endif
0066 } catch (...) {
0067
0068 except = std::current_exception();
0069 }
0070 }
0071
0072 state |= state_t::complete;
0073
0074 other->c = std::move( other->c).resume();
0075 return std::move( other->c);
0076 },
0077 std::forward< Fn >( fn) ) },
0078 #else
0079 c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
0080 [this,fn_=std::forward< Fn >( fn)](boost::context::fiber && c) mutable {
0081
0082 typename pull_coroutine< T >::control_block synthesized_cb{ this, c };
0083 pull_coroutine< T > synthesized{ & synthesized_cb };
0084 other = & synthesized_cb;
0085 other->c = std::move( other->c).resume();
0086 if ( state_t::none == ( state & state_t::destroy) ) {
0087 try {
0088 auto fn = std::move( fn_);
0089
0090 fn( synthesized);
0091 } catch ( boost::context::detail::forced_unwind const&) {
0092 throw;
0093 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
0094 } catch ( abi::__forced_unwind const&) {
0095 throw;
0096 #endif
0097 } catch (...) {
0098
0099 except = std::current_exception();
0100 }
0101 }
0102
0103 state |= state_t::complete;
0104
0105 return std::move( other->c).resume();
0106 } },
0107 #endif
0108 other{ nullptr },
0109 state{ state_t::unwind },
0110 except{} {
0111 c = std::move( c).resume();
0112 }
0113
0114 template< typename T >
0115 push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
0116 boost::context::fiber & c_) noexcept :
0117 c{ std::move( c_) },
0118 other{ cb },
0119 state{ state_t::none },
0120 except{} {
0121 }
0122
0123 template< typename T >
0124 void
0125 push_coroutine< T >::control_block::deallocate() noexcept {
0126 if ( state_t::none != ( state & state_t::unwind) ) {
0127 destroy( this);
0128 }
0129 }
0130
0131 template< typename T >
0132 void
0133 push_coroutine< T >::control_block::resume( T const& data) {
0134
0135 other->set( data);
0136
0137 c = std::move( c).resume();
0138 if ( except) {
0139 std::rethrow_exception( except);
0140 }
0141 }
0142
0143 template< typename T >
0144 void
0145 push_coroutine< T >::control_block::resume( T && data) {
0146
0147 other->set( std::move( data) );
0148
0149 c = std::move( c).resume();
0150 if ( except) {
0151 std::rethrow_exception( except);
0152 }
0153 }
0154
0155 template< typename T >
0156 bool
0157 push_coroutine< T >::control_block::valid() const noexcept {
0158 return state_t::none == ( state & state_t::complete );
0159 }
0160
0161
0162
0163
0164 template< typename T >
0165 void
0166 push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
0167 boost::context::fiber c = std::move( cb->c);
0168
0169 cb->~control_block();
0170
0171 cb->state |= state_t::destroy;
0172 }
0173
0174 template< typename T >
0175 template< typename StackAllocator, typename Fn >
0176 push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
0177 Fn && fn) :
0178 #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
0179 c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
0180 wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::fiber && c) mutable {
0181
0182 typename pull_coroutine< T & >::control_block synthesized_cb{ this, c };
0183 pull_coroutine< T & > synthesized{ & synthesized_cb };
0184 other = & synthesized_cb;
0185 other->c = std::move( other->c).resume();
0186 if ( state_t::none == ( state & state_t::destroy) ) {
0187 try {
0188 auto fn = std::move( fn_);
0189
0190 fn( synthesized);
0191 } catch ( boost::context::detail::forced_unwind const&) {
0192 throw;
0193 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
0194 } catch ( abi::__forced_unwind const&) {
0195 throw;
0196 #endif
0197 } catch (...) {
0198
0199 except = std::current_exception();
0200 }
0201 }
0202
0203 state |= state_t::complete;
0204
0205 other->c = std::move( other->c).resume();
0206 return std::move( other->c);
0207 },
0208 std::forward< Fn >( fn) ) },
0209 #else
0210 c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
0211 [this,fn_=std::forward< Fn >( fn)](boost::context::fiber && c) mutable {
0212
0213 typename pull_coroutine< T & >::control_block synthesized_cb{ this, c };
0214 pull_coroutine< T & > synthesized{ & synthesized_cb };
0215 other = & synthesized_cb;
0216 other->c = std::move( other->c).resume();
0217 if ( state_t::none == ( state & state_t::destroy) ) {
0218 try {
0219 auto fn = std::move( fn_);
0220
0221 fn( synthesized);
0222 } catch ( boost::context::detail::forced_unwind const&) {
0223 throw;
0224 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
0225 } catch ( abi::__forced_unwind const&) {
0226 throw;
0227 #endif
0228 } catch (...) {
0229
0230 except = std::current_exception();
0231 }
0232 }
0233
0234 state |= state_t::complete;
0235
0236 other->c = std::move( other->c).resume();
0237 return std::move( other->c);
0238 } },
0239 #endif
0240 other{ nullptr },
0241 state{ state_t::unwind },
0242 except{} {
0243 c = std::move( c).resume();
0244 }
0245
0246 template< typename T >
0247 push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
0248 boost::context::fiber & c_) noexcept :
0249 c{ std::move( c_) },
0250 other{ cb },
0251 state{ state_t::none },
0252 except{} {
0253 }
0254
0255 template< typename T >
0256 void
0257 push_coroutine< T & >::control_block::deallocate() noexcept {
0258 if ( state_t::none != ( state & state_t::unwind) ) {
0259 destroy( this);
0260 }
0261 }
0262
0263 template< typename T >
0264 void
0265 push_coroutine< T & >::control_block::resume( T & data) {
0266
0267 other->set( data);
0268
0269 c = std::move( c).resume();
0270 if ( except) {
0271 std::rethrow_exception( except);
0272 }
0273 }
0274
0275 template< typename T >
0276 bool
0277 push_coroutine< T & >::control_block::valid() const noexcept {
0278 return state_t::none == ( state & state_t::complete );
0279 }
0280
0281
0282
0283
0284 inline
0285 void
0286 push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
0287 boost::context::fiber c = std::move( cb->c);
0288
0289 cb->~control_block();
0290
0291 cb->state |= state_t::destroy;
0292 }
0293
0294 template< typename StackAllocator, typename Fn >
0295 push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc, Fn && fn) :
0296 #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
0297 c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
0298 wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::fiber && c) mutable {
0299
0300 typename pull_coroutine< void >::control_block synthesized_cb{ this, c };
0301 pull_coroutine< void > synthesized{ & synthesized_cb };
0302 other = & synthesized_cb;
0303 other->c = std::move( other->c).resume();
0304 if ( state_t::none == ( state & state_t::destroy) ) {
0305 try {
0306 auto fn = std::move( fn_);
0307
0308 fn( synthesized);
0309 } catch ( boost::context::detail::forced_unwind const&) {
0310 throw;
0311 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
0312 } catch ( abi::__forced_unwind const&) {
0313 throw;
0314 #endif
0315 } catch (...) {
0316
0317 except = std::current_exception();
0318 }
0319 }
0320
0321 state |= state_t::complete;
0322
0323 other->c = std::move( other->c).resume();
0324 return std::move( other->c);
0325 },
0326 std::forward< Fn >( fn) ) },
0327 #else
0328 c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
0329 [this,fn_=std::forward< Fn >( fn)](boost::context::fiber && c) mutable {
0330
0331 typename pull_coroutine< void >::control_block synthesized_cb{ this, c};
0332 pull_coroutine< void > synthesized{ & synthesized_cb };
0333 other = & synthesized_cb;
0334 other->c = std::move( other->c).resume();
0335 if ( state_t::none == ( state & state_t::destroy) ) {
0336 try {
0337 auto fn = std::move( fn_);
0338
0339 fn( synthesized);
0340 } catch ( boost::context::detail::forced_unwind const&) {
0341 throw;
0342 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
0343 } catch ( abi::__forced_unwind const&) {
0344 throw;
0345 #endif
0346 } catch (...) {
0347
0348 except = std::current_exception();
0349 }
0350 }
0351
0352 state |= state_t::complete;
0353
0354 other->c = std::move( other->c).resume();
0355 return std::move( other->c);
0356 } },
0357 #endif
0358 other{ nullptr },
0359 state{ state_t::unwind },
0360 except{} {
0361 c = std::move( c).resume();
0362 }
0363
0364 inline
0365 push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
0366 boost::context::fiber & c_) noexcept :
0367 c{ std::move( c_) },
0368 other{ cb },
0369 state{ state_t::none },
0370 except{} {
0371 }
0372
0373 inline
0374 void
0375 push_coroutine< void >::control_block::deallocate() noexcept {
0376 if ( state_t::none != ( state & state_t::unwind) ) {
0377 destroy( this);
0378 }
0379 }
0380
0381 inline
0382 void
0383 push_coroutine< void >::control_block::resume() {
0384 c = std::move( c).resume();
0385 if ( except) {
0386 std::rethrow_exception( except);
0387 }
0388 }
0389
0390 inline
0391 bool
0392 push_coroutine< void >::control_block::valid() const noexcept {
0393 return state_t::none == ( state & state_t::complete );
0394 }
0395
0396 }}}
0397
0398 #ifdef BOOST_HAS_ABI_HEADERS
0399 # include BOOST_ABI_SUFFIX
0400 #endif
0401
0402 #endif