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