bool coroutine_impl::operator()() { assert(!done); // Passing this, as the trampoline expects it as a parameter. (Used only on the first call.) main.jump(gen, reinterpret_cast<intptr_t>(this), true); if (exception) std::rethrow_exception(exception); return !done; }
// Run in callee. void coroutine_impl::run() { auto yield = [this]() { if (deleted) throw coroutine::stop(); gen.jump(main, {}, true); if (deleted) throw coroutine::stop(); }; try { body(std::move(yield)); } catch (coroutine::stop&) {} catch (...) { exception = std::current_exception(); } done = true; gen.jump(main, {}, true); }
R * yield_to_( Other * other, typename Other::param_type * to) { BOOST_ASSERT( ! is_complete() ); BOOST_ASSERT( is_running() ); BOOST_ASSERT( ! other->is_complete() ); BOOST_ASSERT( ! other->is_running() ); other->caller_ = caller_; flags_ &= ~flag_running; param_type * from( reinterpret_cast< param_type * >( callee_.jump( other->callee_, reinterpret_cast< intptr_t >( to), preserve_fpu() ) ) ); flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); BOOST_ASSERT( from->data); return from->data; }