File indexing completed on 2025-01-18 09:30:32
0001
0002
0003
0004
0005
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