Back to home page

EIC code displayed by LXR

 
 

    


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

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_SYMMETRIC_COROUTINE_OBJECT_H
0008 #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_OBJECT_H
0009 
0010 #include <boost/assert.hpp>
0011 #include <boost/config.hpp>
0012 #include <boost/move/move.hpp>
0013 
0014 #include <boost/coroutine/detail/config.hpp>
0015 #include <boost/coroutine/detail/flags.hpp>
0016 #include <boost/coroutine/detail/preallocated.hpp>
0017 #include <boost/coroutine/detail/symmetric_coroutine_impl.hpp>
0018 #include <boost/coroutine/detail/symmetric_coroutine_yield.hpp>
0019 #include <boost/coroutine/exceptions.hpp>
0020 #include <boost/coroutine/stack_context.hpp>
0021 
0022 #ifdef BOOST_HAS_ABI_HEADERS
0023 #  include BOOST_ABI_PREFIX
0024 #endif
0025 
0026 namespace boost {
0027 namespace coroutines {
0028 
0029 struct stack_context;
0030 
0031 namespace detail {
0032 
0033 template< typename R, typename Fn, typename StackAllocator >
0034 class symmetric_coroutine_object : public symmetric_coroutine_impl< R >
0035 {
0036 private:
0037     typedef symmetric_coroutine_impl< R >                       impl_t;
0038     typedef symmetric_coroutine_object< R, Fn, StackAllocator > obj_t;
0039 
0040     Fn                  fn_;
0041     stack_context       stack_ctx_;
0042     StackAllocator      stack_alloc_;
0043 
0044     static void deallocate_( obj_t * obj)
0045     {
0046         stack_context stack_ctx( obj->stack_ctx_);
0047         StackAllocator stack_alloc( obj->stack_alloc_);
0048         obj->unwind_stack();
0049         obj->~obj_t();
0050         stack_alloc.deallocate( stack_ctx);
0051     }
0052 
0053 public:
0054 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0055     symmetric_coroutine_object( Fn fn, attributes const& attrs,
0056                                 preallocated const& palloc,
0057                                 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0058         impl_t( palloc,
0059                 stack_unwind == attrs.do_unwind),
0060         fn_( fn),
0061         stack_ctx_( palloc.sctx),
0062         stack_alloc_( stack_alloc)
0063     {}
0064 #endif
0065 
0066     symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
0067                                 preallocated const& palloc,
0068                                 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0069         impl_t( palloc,
0070                 stack_unwind == attrs.do_unwind),
0071 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0072         fn_( fn),
0073 #else
0074         fn_( boost::forward< Fn >( fn) ),
0075 #endif
0076         stack_ctx_( palloc.sctx),
0077         stack_alloc_( stack_alloc)
0078     {}
0079 
0080     void run( R * r) BOOST_NOEXCEPT
0081     {
0082         BOOST_ASSERT( ! impl_t::unwind_requested() );
0083 
0084         impl_t::flags_ |= flag_started;
0085         impl_t::flags_ |= flag_running;
0086         try
0087         {
0088             symmetric_coroutine_yield< R > yc( this, r);
0089             fn_( yc);
0090         }
0091         catch ( forced_unwind const&)
0092         {}
0093         catch (...)
0094         { std::terminate(); }
0095 
0096         impl_t::flags_ |= flag_complete;
0097         impl_t::flags_ &= ~flag_running;
0098         typename impl_t::param_type to;
0099         impl_t::callee_.jump(
0100             impl_t::caller_, 
0101             & to);
0102         BOOST_ASSERT_MSG( false, "coroutine is complete");
0103     }
0104 
0105     void destroy()
0106     { deallocate_( this); }
0107 };
0108 
0109 template< typename R, typename Fn, typename StackAllocator >
0110 class symmetric_coroutine_object< R &, Fn, StackAllocator > : public symmetric_coroutine_impl< R & >
0111 {
0112 private:
0113     typedef symmetric_coroutine_impl< R & >                         impl_t;
0114     typedef symmetric_coroutine_object< R &, Fn, StackAllocator >   obj_t;
0115 
0116     Fn                  fn_;
0117     stack_context       stack_ctx_;
0118     StackAllocator      stack_alloc_;
0119 
0120     static void deallocate_( obj_t * obj)
0121     {
0122         stack_context stack_ctx( obj->stack_ctx_);
0123         StackAllocator stack_alloc( obj->stack_alloc_);
0124         obj->unwind_stack();
0125         obj->~obj_t();
0126         stack_alloc.deallocate( stack_ctx);
0127     }
0128 
0129 public:
0130 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0131     symmetric_coroutine_object( Fn fn, attributes const& attrs,
0132                                 preallocated const& palloc,
0133                                 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0134         impl_t( palloc,
0135                 stack_unwind == attrs.do_unwind),
0136         fn_( fn),
0137         stack_ctx_( palloc.sctx),
0138         stack_alloc_( stack_alloc)
0139     {}
0140 #endif
0141 
0142     symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
0143                                 preallocated const& palloc,
0144                                 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0145         impl_t( palloc,
0146                 stack_unwind == attrs.do_unwind),
0147 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0148         fn_( fn),
0149 #else
0150         fn_( boost::forward< Fn >( fn) ),
0151 #endif
0152         stack_ctx_( palloc.sctx),
0153         stack_alloc_( stack_alloc)
0154     {}
0155 
0156     void run( R * r) BOOST_NOEXCEPT
0157     {
0158         BOOST_ASSERT( ! impl_t::unwind_requested() );
0159 
0160         impl_t::flags_ |= flag_started;
0161         impl_t::flags_ |= flag_running;
0162         try
0163         {
0164             symmetric_coroutine_yield< R & > yc( this, r);
0165             fn_( yc);
0166         }
0167         catch ( forced_unwind const&)
0168         {}
0169         catch (...)
0170         { std::terminate(); }
0171 
0172         impl_t::flags_ |= flag_complete;
0173         impl_t::flags_ &= ~flag_running;
0174         typename impl_t::param_type to;
0175         impl_t::callee_.jump(
0176             impl_t::caller_, 
0177             & to);
0178         BOOST_ASSERT_MSG( false, "coroutine is complete");
0179     }
0180 
0181     void destroy()
0182     { deallocate_( this); }
0183 };
0184 
0185 template< typename Fn, typename StackAllocator >
0186 class symmetric_coroutine_object< void, Fn, StackAllocator > : public symmetric_coroutine_impl< void >
0187 {
0188 private:
0189     typedef symmetric_coroutine_impl< void >                        impl_t;
0190     typedef symmetric_coroutine_object< void, Fn, StackAllocator >  obj_t;
0191 
0192     Fn                  fn_;
0193     stack_context       stack_ctx_;
0194     StackAllocator      stack_alloc_;
0195 
0196     static void deallocate_( obj_t * obj)
0197     {
0198         stack_context stack_ctx( obj->stack_ctx_);
0199         StackAllocator stack_alloc( obj->stack_alloc_);
0200         obj->unwind_stack();
0201         obj->~obj_t();
0202         stack_alloc.deallocate( stack_ctx);
0203     }
0204 
0205 public:
0206 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0207     symmetric_coroutine_object( Fn fn, attributes const& attrs,
0208                                 preallocated const& palloc,
0209                                 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0210         impl_t( palloc,
0211                 stack_unwind == attrs.do_unwind),
0212         fn_( fn),
0213         stack_ctx_( palloc.sctx),
0214         stack_alloc_( stack_alloc)
0215     {}
0216 #endif
0217 
0218     symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
0219                                 preallocated const& palloc,
0220                                 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
0221         impl_t( palloc,
0222                 stack_unwind == attrs.do_unwind),
0223 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0224         fn_( fn),
0225 #else
0226         fn_( boost::forward< Fn >( fn) ),
0227 #endif
0228         stack_ctx_( palloc.sctx),
0229         stack_alloc_( stack_alloc)
0230     {}
0231 
0232     void run() BOOST_NOEXCEPT
0233     {
0234         BOOST_ASSERT( ! impl_t::unwind_requested() );
0235 
0236         impl_t::flags_ |= flag_started;
0237         impl_t::flags_ |= flag_running;
0238         try
0239         {
0240             symmetric_coroutine_yield< void > yc( this);
0241             fn_( yc);
0242         }
0243         catch ( forced_unwind const&)
0244         {}
0245         catch (...)
0246         { std::terminate(); }
0247 
0248         impl_t::flags_ |= flag_complete;
0249         impl_t::flags_ &= ~flag_running;
0250         typename impl_t::param_type to;
0251         impl_t::callee_.jump(
0252             impl_t::caller_, 
0253             & to);
0254         BOOST_ASSERT_MSG( false, "coroutine is complete");
0255     }
0256 
0257     void destroy()
0258     { deallocate_( this); }
0259 };
0260 
0261 }}}
0262 
0263 #ifdef BOOST_HAS_ABI_HEADERS
0264 #  include BOOST_ABI_SUFFIX
0265 #endif
0266 
0267 #endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_OBJECT_H