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