Back to home page

EIC code displayed by LXR

 
 

    


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

0001 
0002 //          Copyright Oliver Kowalke 2009.
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_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
0008 #define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
0009 
0010 #include <boost/assert.hpp>
0011 #include <boost/config.hpp>
0012 #include <boost/context/detail/config.hpp>
0013 #include <boost/cstdint.hpp>
0014 #include <boost/exception_ptr.hpp>
0015 #include <boost/move/move.hpp>
0016 
0017 #include <boost/coroutine/detail/config.hpp>
0018 #include <boost/coroutine/detail/coroutine_context.hpp>
0019 #include <boost/coroutine/detail/flags.hpp>
0020 #include <boost/coroutine/detail/preallocated.hpp>
0021 #include <boost/coroutine/detail/pull_coroutine_impl.hpp>
0022 #include <boost/coroutine/detail/trampoline_pull.hpp>
0023 #include <boost/coroutine/exceptions.hpp>
0024 #include <boost/coroutine/flags.hpp>
0025 #include <boost/coroutine/stack_context.hpp>
0026 
0027 #ifdef BOOST_HAS_ABI_HEADERS
0028 #  include BOOST_ABI_PREFIX
0029 #endif
0030 
0031 #if defined(BOOST_MSVC)
0032 # pragma warning(push)
0033 # pragma warning(disable:4355)
0034 #endif
0035 
0036 namespace boost {
0037 namespace coroutines {
0038 namespace detail {
0039 
0040 struct pull_coroutine_context
0041 {
0042     coroutine_context   caller;
0043     coroutine_context   callee;
0044 
0045     template< typename Coro >
0046     pull_coroutine_context( preallocated const& palloc, Coro *) :
0047         caller(),
0048         callee( trampoline_pull< Coro >, palloc)
0049     {}
0050 };
0051 
0052 template< typename PushCoro, typename R, typename Fn, typename StackAllocator >
0053 class pull_coroutine_object : private pull_coroutine_context,
0054                               public pull_coroutine_impl< R >
0055 {
0056 private:
0057     typedef pull_coroutine_context                                      ctx_t;
0058     typedef pull_coroutine_impl< R >                                    base_t;
0059     typedef pull_coroutine_object< PushCoro, R, Fn, StackAllocator >    obj_t;
0060 
0061     Fn                  fn_;
0062     stack_context       stack_ctx_;
0063     StackAllocator      stack_alloc_;
0064 
0065     static void deallocate_( obj_t * obj)
0066     {
0067         stack_context stack_ctx( obj->stack_ctx_);
0068         StackAllocator stack_alloc( obj->stack_alloc_);
0069         obj->unwind_stack();
0070         obj->~obj_t();
0071         stack_alloc.deallocate( stack_ctx);
0072     }
0073 
0074 public:
0075 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0076     pull_coroutine_object( Fn fn, attributes const& attrs,
0077                            preallocated const& palloc,
0078                            StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0079         ctx_t( palloc, this),
0080         base_t( & this->caller,
0081                 & this->callee,
0082                 stack_unwind == attrs.do_unwind),
0083         fn_( fn),
0084         stack_ctx_( palloc.sctx),
0085         stack_alloc_( stack_alloc)
0086     {}
0087 #endif
0088 
0089     pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
0090                            preallocated const& palloc,
0091                            StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0092         ctx_t( palloc, this),
0093         base_t( & this->caller,
0094                 & this->callee,
0095                 stack_unwind == attrs.do_unwind),
0096 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0097         fn_( fn),
0098 #else
0099         fn_( boost::forward< Fn >( fn) ),
0100 #endif
0101         stack_ctx_( palloc.sctx),
0102         stack_alloc_( stack_alloc)
0103     {}
0104 
0105     void run()
0106     {
0107         BOOST_ASSERT( ! base_t::unwind_requested() );
0108 
0109         base_t::flags_ |= flag_started;
0110         base_t::flags_ |= flag_running;
0111 
0112         // create push_coroutine
0113         typename PushCoro::synth_type b( & this->callee, & this->caller, false);
0114         PushCoro push_coro( synthesized_t::syntesized, b);
0115         try
0116         { fn_( push_coro); }
0117         catch ( forced_unwind const&)
0118         {}
0119 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
0120         catch ( abi::__forced_unwind const&)
0121         { throw; }
0122 #endif
0123         catch (...)
0124         { base_t::except_ = current_exception(); }
0125 
0126         base_t::flags_ |= flag_complete;
0127         base_t::flags_ &= ~flag_running;
0128         typename base_t::param_type to;
0129         this->callee.jump(
0130             this->caller,
0131             & to);
0132         BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
0133     }
0134 
0135     void destroy()
0136     { deallocate_( this); }
0137 };
0138 
0139 template< typename PushCoro, typename R, typename Fn, typename StackAllocator >
0140 class pull_coroutine_object< PushCoro, R &, Fn, StackAllocator > : private pull_coroutine_context,
0141                                                                    public pull_coroutine_impl< R & >
0142 {
0143 private:
0144     typedef pull_coroutine_context                                      ctx_t;
0145     typedef pull_coroutine_impl< R & >                                  base_t;
0146     typedef pull_coroutine_object< PushCoro, R &, Fn, StackAllocator >  obj_t;
0147 
0148     Fn                  fn_;
0149     stack_context       stack_ctx_;
0150     StackAllocator      stack_alloc_;
0151 
0152     static void deallocate_( obj_t * obj)
0153     {
0154         stack_context stack_ctx( obj->stack_ctx_);
0155         StackAllocator stack_alloc( obj->stack_alloc_);
0156         obj->unwind_stack();
0157         obj->~obj_t();
0158         stack_alloc.deallocate( stack_ctx);
0159     }
0160 
0161 public:
0162 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0163     pull_coroutine_object( Fn fn, attributes const& attrs,
0164                            preallocated const& palloc,
0165                            StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0166         ctx_t( palloc, this),
0167         base_t( & this->caller,
0168                 & this->callee,
0169                 stack_unwind == attrs.do_unwind),
0170         fn_( fn),
0171         stack_ctx_( palloc.sctx),
0172         stack_alloc_( stack_alloc)
0173     {}
0174 #endif
0175 
0176     pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
0177                            preallocated const& palloc,
0178                            StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0179         ctx_t( palloc, this),
0180         base_t( & this->caller,
0181                 & this->callee,
0182                 stack_unwind == attrs.do_unwind),
0183 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0184         fn_( fn),
0185 #else
0186         fn_( boost::forward< Fn >( fn) ),
0187 #endif
0188         stack_ctx_( palloc.sctx),
0189         stack_alloc_( stack_alloc)
0190     {}
0191 
0192     void run()
0193     {
0194         BOOST_ASSERT( ! base_t::unwind_requested() );
0195 
0196         base_t::flags_ |= flag_started;
0197         base_t::flags_ |= flag_running;
0198 
0199         // create push_coroutine
0200         typename PushCoro::synth_type b( & this->callee, & this->caller, false);
0201         PushCoro push_coro( synthesized_t::syntesized, b);
0202         try
0203         { fn_( push_coro); }
0204         catch ( forced_unwind const&)
0205         {}
0206 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
0207         catch ( abi::__forced_unwind const&)
0208         { throw; }
0209 #endif
0210         catch (...)
0211         { base_t::except_ = current_exception(); }
0212 
0213         base_t::flags_ |= flag_complete;
0214         base_t::flags_ &= ~flag_running;
0215         typename base_t::param_type to;
0216         this->callee.jump(
0217             this->caller,
0218             & to);
0219         BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
0220     }
0221 
0222     void destroy()
0223     { deallocate_( this); }
0224 };
0225 
0226 template< typename PushCoro, typename Fn, typename StackAllocator >
0227 class pull_coroutine_object< PushCoro, void, Fn, StackAllocator > : private pull_coroutine_context,
0228                                                                     public pull_coroutine_impl< void >
0229 {
0230 private:
0231     typedef pull_coroutine_context                                      ctx_t;
0232     typedef pull_coroutine_impl< void >                                 base_t;
0233     typedef pull_coroutine_object< PushCoro, void, Fn, StackAllocator > obj_t;
0234 
0235     Fn                  fn_;
0236     stack_context       stack_ctx_;
0237     StackAllocator      stack_alloc_;
0238 
0239     static void deallocate_( obj_t * obj)
0240     {
0241         stack_context stack_ctx( obj->stack_ctx_);
0242         StackAllocator stack_alloc( obj->stack_alloc_);
0243         obj->unwind_stack();
0244         obj->~obj_t();
0245         stack_alloc.deallocate( stack_ctx);
0246     }
0247 
0248 public:
0249 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0250     pull_coroutine_object( Fn fn, attributes const& attrs,
0251                            preallocated const& palloc,
0252                            StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0253         ctx_t( palloc, this),
0254         base_t( & this->caller,
0255                 & this->callee,
0256                 stack_unwind == attrs.do_unwind),
0257         fn_( fn),
0258         stack_ctx_( palloc.sctx),
0259         stack_alloc_( stack_alloc)
0260     {}
0261 #endif
0262 
0263     pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
0264                            preallocated const& palloc,
0265                            StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0266         ctx_t( palloc, this),
0267         base_t( & this->caller,
0268                 & this->callee,
0269                 stack_unwind == attrs.do_unwind),
0270 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0271         fn_( fn),
0272 #else
0273         fn_( boost::forward< Fn >( fn) ),
0274 #endif
0275         stack_ctx_( palloc.sctx),
0276         stack_alloc_( stack_alloc)
0277     {}
0278 
0279     void run()
0280     {
0281         BOOST_ASSERT( ! base_t::unwind_requested() );
0282 
0283         base_t::flags_ |= flag_started;
0284         base_t::flags_ |= flag_running;
0285 
0286         // create push_coroutine
0287         typename PushCoro::synth_type b( & this->callee, & this->caller, false);
0288         PushCoro push_coro( synthesized_t::syntesized, b);
0289         try
0290         { fn_( push_coro); }
0291         catch ( forced_unwind const&)
0292         {}
0293 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
0294         catch ( abi::__forced_unwind const&)
0295         { throw; }
0296 #endif
0297         catch (...)
0298         { base_t::except_ = current_exception(); }
0299 
0300         base_t::flags_ |= flag_complete;
0301         base_t::flags_ &= ~flag_running;
0302         typename base_t::param_type to;
0303         this->callee.jump(
0304             this->caller,
0305             & to);
0306         BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
0307     }
0308 
0309     void destroy()
0310     { deallocate_( this); }
0311 };
0312 
0313 }}}
0314 
0315 #if defined(BOOST_MSVC)
0316 # pragma warning(pop)
0317 #endif
0318 
0319 #ifdef BOOST_HAS_ABI_HEADERS
0320 #  include BOOST_ABI_SUFFIX
0321 #endif
0322 
0323 #endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H