Refactor the folder structure which only had 2 'real' modules, now it's more real, no need for splitting into folders beside the external one
This commit is contained in:
98
src/coroutines.cpp
Normal file
98
src/coroutines.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
typedef void CoroutineFunction(mco_coro *co);
|
||||
CCtx *_CoroutineContext = NULL;
|
||||
|
||||
CCtx *GetCoroutineContext() {
|
||||
Assert(_CoroutineContext);
|
||||
return _CoroutineContext;
|
||||
}
|
||||
|
||||
void DestroyCoroutine(CCtx *n) {
|
||||
mco_destroy(n->co);
|
||||
Release(&n->arena);
|
||||
}
|
||||
|
||||
void RemoveCoroutine(String name) {
|
||||
IterRemove(ActiveCoroutines) {
|
||||
IterRemovePrepare(ActiveCoroutines);
|
||||
if (it.name == name) {
|
||||
DestroyCoroutine(&it);
|
||||
remove_item = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCtx CreateCoroutine(CoroutineFunction *func, String name) {
|
||||
mco_desc desc = mco_desc_init(func, 0);
|
||||
mco_coro *coro = NULL;
|
||||
mco_result ok = mco_create(&coro, &desc);
|
||||
assert(ok == MCO_SUCCESS);
|
||||
return {coro, name};
|
||||
}
|
||||
|
||||
#define AddCoroutine(x) AddCoroutineEx(x, #x)
|
||||
CCtx *AddCoroutineEx(CoroutineFunction *func, String name) {
|
||||
CCtx coroutine = CreateCoroutine(func, name);
|
||||
Add(&ActiveCoroutines, coroutine);
|
||||
return GetLast(ActiveCoroutines);
|
||||
}
|
||||
|
||||
void ResumeCoroutine(CCtx *dat) {
|
||||
CCtx *prev_curr = _CoroutineContext;
|
||||
_CoroutineContext = dat;
|
||||
mco_result ok = mco_resume(dat->co);
|
||||
Assert(ok == MCO_SUCCESS);
|
||||
_CoroutineContext = prev_curr;
|
||||
}
|
||||
|
||||
void UpdateCoroutines(Event *event) {
|
||||
ProfileFunction();
|
||||
double start = GetTimeSeconds();
|
||||
for (;ActiveCoroutines.len;) {
|
||||
IterRemove(ActiveCoroutines) {
|
||||
IterRemovePrepare(ActiveCoroutines);
|
||||
ProfileScopeEx(it.name);
|
||||
|
||||
mco_state status = mco_status(it.co);
|
||||
if (status == MCO_DEAD) {
|
||||
DestroyCoroutine(&it);
|
||||
remove_item = true;
|
||||
} else {
|
||||
mco_push(it.co, &event, sizeof(Event *));
|
||||
_CoroutineContext = ⁢
|
||||
mco_result ok = mco_resume(it.co);
|
||||
if (ok != MCO_SUCCESS) {
|
||||
ReportErrorf("failed to resume coroutine %d", ok);
|
||||
DestroyCoroutine(&it);
|
||||
remove_item = true;
|
||||
}
|
||||
_CoroutineContext = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if SLOW_BUILD
|
||||
//:CoroutineLeakCheck
|
||||
// Make sure we don't leak scratch arenas between coroutine boundaries.
|
||||
// it leads to memory corruption! If you hit Assert here make sure you
|
||||
// don't leak the scratch arena.
|
||||
for (int i = 0; i < Lengthof(ScratchArenas); i += 1) {
|
||||
Assert(ScratchArenas[i].refs == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
double took = GetTimeSeconds() - start;
|
||||
if (took > (0.016666 / 3.0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Event *Yield(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;
|
||||
}
|
||||
Reference in New Issue
Block a user