#include "threads" #include "assert" #include #include static coroutine main_coroutine; static coroutine* current_coroutine = &main_coroutine; void ctxSwitchDirect(void* src, void* dst) { current_coroutine = dst; } coroutine* this_coroutine() { return current_coroutine; } void ?{}(coroutine* this) { this->last = NULL; this->name = "A Coroutine"; this->notHalted = true; } void suspend() { coroutine* src = this_coroutine(); // optimization assertf( src->last == (coroutine*)0, "Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n" "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.", src->name, src ); assertf( src->last->notHalted, "Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n" "Possible cause is terminated coroutine's main routine has already returned.", src->name, src, src->last->name, src->last ); ctxSwitchDirect( src, src->last ); } forall(dtype T | coroutine_t(T)) void resume(T* cor) { coroutine* src = this_coroutine(); // optimization coroutine* dst = this_coroutine(cor); if ( src != dst ) { // not resuming self ? assertf( dst->notHalted , "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n" "Possible cause is terminated coroutine's main routine has already returned.", src->name, src, dst->name, dst ); dst->last = src; // set last resumer } // if ctxSwitchDirect( src, dst ); // always done for performance testing }