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