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