typedef void      CoroutineProc(mco_coro *co);
Array<mco_coro *> ActiveCoroutines;

mco_coro *CoAdd(CoroutineProc *proc) {
    mco_desc desc = mco_desc_init(proc, 0);

    mco_coro  *coro = NULL;
    mco_result ok   = mco_create(&coro, &desc);
    if (ok != MCO_SUCCESS) {
        ReportWarningf("failed to create coroutine %d", ok);
        return NULL;
    }

    mco_resume(coro);
    Add(&ActiveCoroutines, coro);
    return coro;
}

void CoUpdate(Event *event) {
    IterRemove(ActiveCoroutines) {
        IterRemovePrepare(ActiveCoroutines);

        mco_state status = mco_status(it);
        if (status == MCO_DEAD) {
            mco_destroy(it);
            remove_item = true;
        } else {
            mco_push(it, &event, sizeof(Event *));
            mco_result ok = mco_resume(it);
            if (ok != MCO_SUCCESS) {
                ReportWarningf("failed to resume coroutine %d", ok);
                mco_destroy(it);
                remove_item = true;
            }
        }
    }
}

Event *CoYield(mco_coro *co) {
    mco_result ok = mco_yield(co);
    Assert(ok == MCO_SUCCESS);

    Event *event = NULL;
    ok           = mco_pop(co, &event, sizeof(Event *));
    Assert(ok == MCO_SUCCESS);

    return event;
}