Coroutine arenas

This commit is contained in:
krzosa
2025-12-29 10:36:16 +01:00
parent 35d68bda61
commit 0f03f248c7
4 changed files with 26 additions and 15 deletions

View File

@@ -3,6 +3,7 @@
Debug session: Debug session:
- Report errorf - use coroutine dialogs - Report errorf - use coroutine dialogs
- Replace in render layer also
Use session 1: Use session 1:
- OpenCommand in command window freezes the app - OpenCommand in command window freezes the app

View File

@@ -654,12 +654,11 @@ String CodeSkipPatterns[] = {".git/", ".obj", ".o", ".pdb", ".exe"};
String Coro_OpenCodeDir; String Coro_OpenCodeDir;
void Coro_OpenCode(mco_coro *co) { void Coro_OpenCode(mco_coro *co) {
BlockArena arena = {}; Array<String> dirs = {CoCurr->arena};
Array<String> dirs = {arena};
Add(&dirs, Coro_OpenCodeDir); Add(&dirs, Coro_OpenCodeDir);
int i = 0; int i = 0;
for (int diri = 0; diri < dirs.len; diri += 1) { for (int diri = 0; diri < dirs.len; diri += 1) {
for (FileIter it = IterateFiles(arena, dirs[diri]); IsValid(it); Advance(&it)) { for (FileIter it = IterateFiles(CoCurr->arena, dirs[diri]); IsValid(it); Advance(&it)) {
bool match = false; bool match = false;
for (int endings_i = 0; endings_i < Lengthof(CodeSkipPatterns); endings_i += 1) { for (int endings_i = 0; endings_i < Lengthof(CodeSkipPatterns); endings_i += 1) {
String ending = CodeSkipPatterns[endings_i]; String ending = CodeSkipPatterns[endings_i];
@@ -680,7 +679,6 @@ void Coro_OpenCode(mco_coro *co) {
CoYield(co); CoYield(co);
} }
} }
Release(&arena);
} }
void OpenCode(String dir) { void OpenCode(String dir) {
@@ -707,6 +705,7 @@ void AddHook(Array<CommandData> *arr, String name, String binding, Function *fun
Add(arr, n); Add(arr, n);
} }
// @todo: rename to temp buffer? but there is already a thing like that...
String Coro_YesNoCancel(mco_coro *co, BSet main, String question) { String Coro_YesNoCancel(mco_coro *co, BSet main, String question) {
JumpGarbageBuffer(&main); JumpGarbageBuffer(&main);
NextActiveWindowID = main.window->id; NextActiveWindowID = main.window->id;
@@ -766,8 +765,7 @@ void Coro_Close(mco_coro *co) {
return; return;
} }
Scratch scratch; String question = Format(CoCurr->arena, "Do you want to save [%S] before closing?", main.buffer->name);
String question = Format(scratch, "Do you want to save [%S] before closing?", main.buffer->name);
String result = Coro_YesNoCancel(co, main, question); String result = Coro_YesNoCancel(co, main, question);
if (result == "Yes") { if (result == "Yes") {
SaveBuffer(main.buffer); SaveBuffer(main.buffer);
@@ -786,10 +784,10 @@ void Command_Close() {
// Considerations with coroutines: // Considerations with coroutines:
// 1. Does scratch memory leak across Yield boundary? Or interacts badly with Yield stuff in any way? // 1. Does scratch memory leak across Yield boundary? Or interacts badly with Yield stuff in any way?
// 2. Are pointers and globals correct over time? Or might they get deleted etc. // 2. Are pointers and globals correct over time? Or might they get deleted etc.
// 3. Imagine a scenario where the coroutine gets deleted before completion, will the memory leak?
String Coro_CloseAllEx(mco_coro *co) { String Coro_CloseAllEx(mco_coro *co) {
Scratch scratch;
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
Array<BufferID> buffers = {scratch}; Array<BufferID> buffers = {CoCurr->arena};
For (Buffers) Add(&buffers, it->id); For (Buffers) Add(&buffers, it->id);
ForItem (id, buffers) { ForItem (id, buffers) {
Buffer *it = GetBuffer(id); Buffer *it = GetBuffer(id);
@@ -800,7 +798,7 @@ String Coro_CloseAllEx(mco_coro *co) {
continue; continue;
} }
String question = Format(scratch, "Do you want to save [%S] before closing?", it->name); String question = Format(CoCurr->arena, "Do you want to save [%S] before closing?", it->name);
String result = Coro_YesNoCancel(co, main, question); String result = Coro_YesNoCancel(co, main, question);
it = GetBuffer(id, NULL); it = GetBuffer(id, NULL);
if (it && result == "Yes") { if (it && result == "Yes") {

View File

@@ -1,10 +1,17 @@
typedef void CoroutineProc(mco_coro *co); typedef void CoroutineProc(mco_coro *co);
CoData *CoCurr = NULL;
void CoDestroy(CoData *n) {
mco_destroy(n->co);
Release(&n->arena);
}
void CoRemove(String name) { void CoRemove(String name) {
IterRemove(ActiveCoroutines) { IterRemove(ActiveCoroutines) {
IterRemovePrepare(ActiveCoroutines); IterRemovePrepare(ActiveCoroutines);
if (it.name == name) { if (it.name == name) {
mco_destroy(it.co); mco_destroy(it.co);
Release(&it.arena);
remove_item = true; remove_item = true;
} }
} }
@@ -15,15 +22,19 @@ CoData *CoAddEx(CoroutineProc *proc, String name) {
CoRemove(name); CoRemove(name);
mco_desc desc = mco_desc_init(proc, 0); mco_desc desc = mco_desc_init(proc, 0);
mco_coro *coro = NULL; mco_coro *coro = NULL;
mco_result ok = mco_create(&coro, &desc); mco_result ok = mco_create(&coro, &desc);
if (ok != MCO_SUCCESS) { if (ok != MCO_SUCCESS) {
ReportWarningf("failed to create coroutine %d", ok); ReportWarningf("failed to create coroutine %d", ok);
return NULL; return NULL;
} }
mco_resume(coro);
Add(&ActiveCoroutines, {coro, name}); Add(&ActiveCoroutines, {coro, name});
CoData *prev_curr = CoCurr;
CoCurr = GetLast(ActiveCoroutines);
ok = mco_resume(coro);
Assert(ok == MCO_SUCCESS);
CoCurr = prev_curr;
return GetLast(ActiveCoroutines); return GetLast(ActiveCoroutines);
} }
@@ -37,14 +48,15 @@ void CoUpdate(Event *event) {
mco_state status = mco_status(it.co); mco_state status = mco_status(it.co);
if (status == MCO_DEAD) { if (status == MCO_DEAD) {
mco_destroy(it.co); CoDestroy(&it);
remove_item = true; remove_item = true;
} else { } else {
mco_push(it.co, &event, sizeof(Event *)); mco_push(it.co, &event, sizeof(Event *));
CoCurr = &it;
mco_result ok = mco_resume(it.co); mco_result ok = mco_resume(it.co);
if (ok != MCO_SUCCESS) { if (ok != MCO_SUCCESS) {
ReportWarningf("failed to resume coroutine %d", ok); ReportWarningf("failed to resume coroutine %d", ok);
mco_destroy(it.co); CoDestroy(&it);
remove_item = true; remove_item = true;
} }
} }

View File

@@ -87,7 +87,7 @@ Array<Variable> Variables;
Array<Process> ActiveProcesses = {}; Array<Process> ActiveProcesses = {};
Array<String> ProcessEnviroment = {}; Array<String> ProcessEnviroment = {};
struct CoData { mco_coro *co; String name; bool dont_wait_until_resolved; }; struct CoData { mco_coro *co; String name; BlockArena arena; bool dont_wait_until_resolved; void *user_ctx; };
Array<CoData> ActiveCoroutines; Array<CoData> ActiveCoroutines;