/* * This function invokes the start function of the coroutine when the * coroutine is first called. If it was called from coro_new, then it sets * up the stack and initializes the saved context. */ void _coro_enter(coro c) { if (setjmp(c->ctxt)) { /* start the coroutine; stack is empty at this point. */ cvalue _return; _return.p = _cur; _cur->start(_value); /* return the exited coroutine to the exit handler */ coro_call(&_on_exit, _return); } /* this code executes when _coro_enter is called from coro_new */ INIT_CTXT: { /* local and new stack pointers at identical relative positions on the stack */ intptr_t local_sp = (intptr_t)&local_sp; /* I don't know what the addition "- sizeof(void *)" is for when the stack grows downards */ intptr_t new_sp = c->stack_base + (_stack_grows_up ? _frame_offset : c->stack_size - _frame_offset - sizeof(void *)); /* copy local stack frame to the new stack */ _coro_cpframe(local_sp, new_sp); /* reset any locals in the saved state to point to the new stack */ _coro_rebase(c, local_sp, new_sp); } }
void Luagame::Luagame::run() { std::vector<coro_call> coroutines; for (auto& box : boxes) { coroutines.push_back(coro_call( [&](coro_yield& yield) { cur_yield = &yield; box.run(); })); } bool one_run; do { one_run = false; for (auto& coro : coroutines) { if (coro) { one_run = true; coro(); } } } while (one_run); }
void coro_run(coro *next) { coro *caller = coro_new(NULL, NULL); coro_call(caller, next); coro_release(caller); }