Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:34

0001 
0002 //          Copyright Oliver Kowalke 2014.
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //    (See accompanying file LICENSE_1_0.txt or copy at
0005 //          http://www.boost.org/LICENSE_1_0.txt)
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 // push_coroutine< T >
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     // destroy control structure
0038     cb->~control_block();
0039     // destroy coroutine's stack
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                // create synthesized pull_coroutine< T >
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                        // call coroutine-fn with synthesized pull_coroutine as argument
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                        // store other exceptions in exception-pointer
0068                        except = std::current_exception();
0069                    }
0070                }
0071                // set termination flags
0072                state |= state_t::complete;
0073                // jump back
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           // create synthesized pull_coroutine< T >
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                   // call coroutine-fn with synthesized pull_coroutine as argument
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                   // store other exceptions in exception-pointer
0099                   except = std::current_exception();
0100               }
0101           }
0102           // set termination flags
0103           state |= state_t::complete;
0104           // jump back
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     // pass data to other context
0135     other->set( data);
0136     // resume other context
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     // pass data to other context
0147     other->set( std::move( data) );
0148     // resume other context
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 // push_coroutine< T & >
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     // destroy control structure
0169     cb->~control_block();
0170     // destroy coroutine's stack
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                // create synthesized pull_coroutine< T & >
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                        // call coroutine-fn with synthesized pull_coroutine as argument
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                        // store other exceptions in exception-pointer
0199                        except = std::current_exception();
0200                    }
0201                }
0202                // set termination flags
0203                state |= state_t::complete;
0204                // jump back
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           // create synthesized pull_coroutine< T & >
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                   // call coroutine-fn with synthesized pull_coroutine as argument
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                   // store other exceptions in exception-pointer
0230                   except = std::current_exception();
0231               }
0232           }
0233           // set termination flags
0234           state |= state_t::complete;
0235           // jump back
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     // pass data to other context
0267     other->set( data);
0268     // resume other context
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 // push_coroutine< void >
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     // destroy control structure
0289     cb->~control_block();
0290     // destroy coroutine's stack
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                // create synthesized pull_coroutine< void >
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                        // call coroutine-fn with synthesized pull_coroutine as argument
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                        // store other exceptions in exception-pointer
0317                        except = std::current_exception();
0318                    }
0319                }
0320                // set termination flags
0321                state |= state_t::complete;
0322                // jump back
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           // create synthesized pull_coroutine< void >
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                   // call coroutine-fn with synthesized pull_coroutine as argument
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                   // store other exceptions in exception-pointer
0348                   except = std::current_exception();
0349               }
0350           }
0351           // set termination flags
0352           state |= state_t::complete;
0353           // jump back
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 // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP