Coroutine API rename

This commit is contained in:
Krzosa Karol
2026-01-30 21:44:28 +01:00
parent c9acc31cfc
commit 805f5de852
15 changed files with 84 additions and 60 deletions

View File

@@ -20,6 +20,7 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
#undef Yield
API void *VReserve(size_t size) { API void *VReserve(size_t size) {
void *result = (uint8_t *)VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); void *result = (uint8_t *)VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);

View File

@@ -93,6 +93,7 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
#undef Yield
#define BREAK() if (IsDebuggerPresent()) {__debugbreak();} #define BREAK() if (IsDebuggerPresent()) {__debugbreak();}
#elif OS_LINUX #elif OS_LINUX
#define BREAK() raise(SIGTRAP) #define BREAK() raise(SIGTRAP)

View File

@@ -462,6 +462,7 @@ API void CloseStdin(Process *process) {
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
#undef Yield
#include <stdio.h> #include <stdio.h>
#include <intrin.h> #include <intrin.h>

View File

@@ -476,6 +476,7 @@ MCO_API const char *mco_result_description(mco_result res); /* Get the descripti
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
#undef Yield
#endif #endif
#ifndef MCO_NO_DEFAULT_ALLOCATOR #ifndef MCO_NO_DEFAULT_ALLOCATOR

View File

@@ -21,7 +21,7 @@ void AddText(String string) {
void Wait(mco_coro *co) { void Wait(mco_coro *co) {
Add(&EventPlayback, {EVENT_KIND_INVALID}); Add(&EventPlayback, {EVENT_KIND_INVALID});
for (Event *event = CoYield(co); event->kind != EVENT_KIND_INVALID; event = CoYield(co)) { for (Event *event = Yield(co); event->kind != EVENT_KIND_INVALID; event = Yield(co)) {
} }
} }
@@ -153,8 +153,8 @@ void InitTests() {
WaitForEvents = false; WaitForEvents = false;
TestDir = Format(TestArena, "%S/test_env", GetExeDir(TestArena)); TestDir = Format(TestArena, "%S/test_env", GetExeDir(TestArena));
CoRemove("Test"); RemoveCoroutine("Test");
CoData *data = CoAdd(Test); CCtx *data = AddCoroutine(Test);
data->dont_wait_until_resolved = true; data->dont_wait_until_resolved = true;
CoResume(data); ResumeCoroutine(data);
} }

View File

@@ -1,41 +1,47 @@
typedef void CoroutineProc(mco_coro *co); typedef void CoroutineFunction(mco_coro *co);
CoData *CoCurr = NULL; CCtx *_CoroutineContext = NULL;
void CoDestroy(CoData *n) { CCtx *GetCoroutineContext() {
Assert(_CoroutineContext);
return _CoroutineContext;
}
void DestroyCoroutine(CCtx *n) {
mco_destroy(n->co); mco_destroy(n->co);
Release(&n->arena); Release(&n->arena);
} }
void CoRemove(String name) { void RemoveCoroutine(String name) {
IterRemove(ActiveCoroutines) { IterRemove(ActiveCoroutines) {
IterRemovePrepare(ActiveCoroutines); IterRemovePrepare(ActiveCoroutines);
if (it.name == name) { if (it.name == name) {
CoDestroy(&it); DestroyCoroutine(&it);
remove_item = true; remove_item = true;
} }
} }
} }
#define CoAdd(x) CoAddEx(x, #x) CCtx CreateCoroutine(CoroutineFunction *func, String name) {
CoData *CoAddEx(CoroutineProc *proc, String name) { mco_desc desc = mco_desc_init(func, 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) { assert(ok == MCO_SUCCESS);
ReportWarningf("failed to create coroutine %d", ok); return {coro, name};
return NULL;
} }
Add(&ActiveCoroutines, {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); return GetLast(ActiveCoroutines);
} }
void CoResume(CoData *dat) { void ResumeCoroutine(CCtx *dat) {
CoData *prev_curr = CoCurr; CCtx *prev_curr = _CoroutineContext;
CoCurr = dat; _CoroutineContext = dat;
mco_result ok = mco_resume(dat->co); mco_result ok = mco_resume(dat->co);
Assert(ok == MCO_SUCCESS); Assert(ok == MCO_SUCCESS);
CoCurr = prev_curr; _CoroutineContext = prev_curr;
} }
void UpdateCoroutines(Event *event) { void UpdateCoroutines(Event *event) {
@@ -48,17 +54,18 @@ void UpdateCoroutines(Event *event) {
mco_state status = mco_status(it.co); mco_state status = mco_status(it.co);
if (status == MCO_DEAD) { if (status == MCO_DEAD) {
CoDestroy(&it); DestroyCoroutine(&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; _CoroutineContext = &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);
CoDestroy(&it); DestroyCoroutine(&it);
remove_item = true; remove_item = true;
} }
_CoroutineContext = NULL;
} }
} }
@@ -79,7 +86,7 @@ void UpdateCoroutines(Event *event) {
} }
} }
Event *CoYield(mco_coro *co) { Event *Yield(mco_coro *co) {
mco_result ok = mco_yield(co); mco_result ok = mco_yield(co);
Assert(ok == MCO_SUCCESS); Assert(ok == MCO_SUCCESS);

View File

@@ -110,8 +110,14 @@ Array<Variable> Variables;
Array<Process> ActiveProcesses = {}; Array<Process> ActiveProcesses = {};
Array<String> ProcessEnviroment = {}; Array<String> ProcessEnviroment = {};
struct CoData { mco_coro *co; String name; BlockArena arena; bool dont_wait_until_resolved; void *user_ctx; }; struct CCtx {
Array<CoData> ActiveCoroutines; mco_coro *co;
String name;
BlockArena arena;
bool dont_wait_until_resolved;
void *user_ctx;
};
Array<CCtx> ActiveCoroutines;
Color GruvboxDark0Hard = {0x1d, 0x20, 0x21, 0xff}; Color GruvboxDark0Hard = {0x1d, 0x20, 0x21, 0xff};
Color GruvboxDark0 = {0x28, 0x28, 0x28, 0xff}; Color GruvboxDark0 = {0x28, 0x28, 0x28, 0xff};

View File

@@ -38,6 +38,7 @@ void CMD_Reopen() {
} RegisterCommand(CMD_Reopen, "", "Reads again from disk the current buffer"); } RegisterCommand(CMD_Reopen, "", "Reads again from disk the current buffer");
void CO_Rename(mco_coro *co) { void CO_Rename(mco_coro *co) {
CCtx *ctx = GetCoroutineContext();
BSet main = GetBSet(PrimaryWindowID); BSet main = GetBSet(PrimaryWindowID);
Buffer *original_buffer = main.buffer; Buffer *original_buffer = main.buffer;
JumpTempBuffer(&main); JumpTempBuffer(&main);
@@ -60,11 +61,12 @@ void CO_Rename(mco_coro *co) {
return; return;
} }
String16 string16 = GetString(main.buffer, {a.range.max + 1, b.range.max}); String16 string16 = GetString(main.buffer, {a.range.max + 1, b.range.max});
String string = ToString(CoCurr->arena, string16); String string = ToString(ctx->arena, string16);
original_buffer->name = Intern(&GlobalInternTable, string); original_buffer->name = Intern(&GlobalInternTable, string);
} RegisterCoroutineCommand(CO_Rename, "", "Opens a UI asking for a new name of a buffer open in the last active primary window"); } RegisterCoroutineCommand(CO_Rename, "", "Opens a UI asking for a new name of a buffer open in the last active primary window");
void CO_Close(mco_coro *co) { void CO_Close(mco_coro *co) {
CCtx *ctx = GetCoroutineContext();
BSet main = GetBSet(PrimaryWindowID); BSet main = GetBSet(PrimaryWindowID);
if (main.buffer->special || main.buffer->temp) { if (main.buffer->special || main.buffer->temp) {
Close(main.view->id); Close(main.view->id);
@@ -92,7 +94,7 @@ void CO_Close(mco_coro *co) {
return; return;
} }
String question = Format(CoCurr->arena, "Do you want to save [%S] before closing?", main.buffer->name); String question = Format(ctx->arena, "Do you want to save [%S] before closing?", main.buffer->name);
UIAction ui_action = QueryUserYesNoCancel(co, main, question); UIAction ui_action = QueryUserYesNoCancel(co, main, question);
if (ui_action == UIAction_Yes) { if (ui_action == UIAction_Yes) {
SaveBuffer(main.buffer); SaveBuffer(main.buffer);
@@ -116,9 +118,10 @@ void CO_CloseAll(mco_coro *co) {
} RegisterCoroutineCommand(CO_CloseAll, "", "Ask user which files to save and close all open normal views and buffers"); } RegisterCoroutineCommand(CO_CloseAll, "", "Ask user which files to save and close all open normal views and buffers");
void CO_ReplaceAll(mco_coro *co) { void CO_ReplaceAll(mco_coro *co) {
CCtx *ctx = GetCoroutineContext();
BSet main = GetBSet(PrimaryWindowID); BSet main = GetBSet(PrimaryWindowID);
String16 string = FetchLoadWord(main.view); String16 string = FetchLoadWord(main.view);
String string8 = ToString(CoCurr->arena, string); String string8 = ToString(ctx->arena, string);
String16 needle = {}; String16 needle = {};
String16 replace = {}; String16 replace = {};
@@ -144,7 +147,7 @@ void CO_ReplaceAll(mco_coro *co) {
{ {
JumpTempBuffer(&main); JumpTempBuffer(&main);
NextActiveWindowID = main.window->id; NextActiveWindowID = main.window->id;
RawAppendf(main.buffer, ":Submit (enter) :Cancel (escape)\nString to replace with::%S", ToString(CoCurr->arena, needle)); RawAppendf(main.buffer, ":Submit (enter) :Cancel (escape)\nString to replace with::%S", ToString(ctx->arena, needle));
Caret field_seek = BaseFindNext(main.buffer, u"with::", MakeCaret(0), SeekFlag_None); Caret field_seek = BaseFindNext(main.buffer, u"with::", MakeCaret(0), SeekFlag_None);
main.view->carets[0] = MakeCaret(main.buffer->len, field_seek.range.max); main.view->carets[0] = MakeCaret(main.buffer->len, field_seek.range.max);

View File

@@ -11,7 +11,7 @@ void Windows_SetupVCVarsall(mco_coro *co) {
if (!ProcessIsActive(view->id)) { if (!ProcessIsActive(view->id)) {
break; break;
} }
CoYield(co); Yield(co);
} }
Scratch scratch; Scratch scratch;
@@ -30,8 +30,8 @@ void Windows_SetupVCVarsall(mco_coro *co) {
void LoadVCVars() { void LoadVCVars() {
CoRemove("Windows_SetupVCVarsall"); RemoveCoroutine("Windows_SetupVCVarsall");
CoData *co_data = CoAdd(Windows_SetupVCVarsall); CCtx *co_data = AddCoroutine(Windows_SetupVCVarsall);
co_data->dont_wait_until_resolved = true; co_data->dont_wait_until_resolved = true;
CoResume(co_data); ResumeCoroutine(co_data);
} }

View File

@@ -10,12 +10,13 @@ void SetProjectDirectory(String dir) {
} }
void CO_OpenCode(mco_coro *co) { void CO_OpenCode(mco_coro *co) {
Array<String> patterns = SplitWhitespace(CoCurr->arena, OpenCodePatterns); CCtx *ctx = GetCoroutineContext();
Array<String> exclude_patterns = SplitWhitespace(CoCurr->arena, OpenCodeExcludePatterns); Array<String> patterns = SplitWhitespace(ctx->arena, OpenCodePatterns);
Array<String> dirs = {CoCurr->arena}; Array<String> exclude_patterns = SplitWhitespace(ctx->arena, OpenCodeExcludePatterns);
Add(&dirs, Copy(CoCurr->arena, ProjectDirectory)); Array<String> dirs = {ctx->arena};
Add(&dirs, Copy(ctx->arena, ProjectDirectory));
for (int diri = 0; diri < dirs.len; diri += 1) { for (int diri = 0; diri < dirs.len; diri += 1) {
for (FileIter it = IterateFiles(CoCurr->arena, dirs[diri]); IsValid(it); Advance(&it)) { for (FileIter it = IterateFiles(ctx->arena, dirs[diri]); IsValid(it); Advance(&it)) {
bool should_open = true; bool should_open = true;
if (!it.is_directory) { if (!it.is_directory) {
should_open = false; should_open = false;
@@ -45,7 +46,7 @@ void CO_OpenCode(mco_coro *co) {
BufferOpenFile(it.absolute_path); BufferOpenFile(it.absolute_path);
} }
CoYield(co); Yield(co);
} }
} }
} RegisterCoroutineCommand( } RegisterCoroutineCommand(

View File

@@ -2098,6 +2098,7 @@ uint8_t reply_buf[REPLY_BUF_SIZE];
ClientContext RDBG_Ctx; ClientContext RDBG_Ctx;
bool RDBG_InitConnection(mco_coro *co, bool create_session = true) { bool RDBG_InitConnection(mco_coro *co, bool create_session = true) {
CCtx *ctx = GetCoroutineContext();
ReportConsolef("Remedybg: InitConnection"); ReportConsolef("Remedybg: InitConnection");
enum rdbg_CommandResult res; enum rdbg_CommandResult res;
if (RDBG_Ctx.command_pipe_handle != NULL) { if (RDBG_Ctx.command_pipe_handle != NULL) {
@@ -2112,7 +2113,7 @@ bool RDBG_InitConnection(mco_coro *co, bool create_session = true) {
if (create_session) { if (create_session) {
if (BinaryUnderDebug.len) { if (BinaryUnderDebug.len) {
Window *window = GetWindow(PrimaryWindowID); Window *window = GetWindow(PrimaryWindowID);
ResolvedOpen res = ResolveOpen(CoCurr->arena, window, BinaryUnderDebug, ResolveOpenMeta_DontError | ResolveOpenMeta_DontExec); ResolvedOpen res = ResolveOpen(ctx->arena, window, BinaryUnderDebug, ResolveOpenMeta_DontError | ResolveOpenMeta_DontExec);
if (res.kind == OpenKind_Goto) { if (res.kind == OpenKind_Goto) {
file = Intern(&GlobalInternTable, res.path); file = Intern(&GlobalInternTable, res.path);
} }
@@ -2133,8 +2134,8 @@ bool RDBG_InitConnection(mco_coro *co, bool create_session = true) {
} }
} }
String session_name = Format(CoCurr->arena, "te%llu", GetTimeNanos()); String session_name = Format(ctx->arena, "te%llu", GetTimeNanos());
String remedy_string = Format(CoCurr->arena, "%S --servername %S", RemedyBGPath, session_name); String remedy_string = Format(ctx->arena, "%S --servername %S", RemedyBGPath, session_name);
ReportConsolef("Remedybg: %S", remedy_string); ReportConsolef("Remedybg: %S", remedy_string);
Exec(LogView->id, true, remedy_string, GetPrimaryDirectory()); Exec(LogView->id, true, remedy_string, GetPrimaryDirectory());
MemoryZero(&RDBG_Ctx, sizeof(RDBG_Ctx)); MemoryZero(&RDBG_Ctx, sizeof(RDBG_Ctx));

View File

@@ -4,9 +4,10 @@ struct SearchOpenBuffersParams {
}; };
void Coro_SearchOpenBuffers(mco_coro *co) { void Coro_SearchOpenBuffers(mco_coro *co) {
SearchOpenBuffersParams *param = (SearchOpenBuffersParams *)CoCurr->user_ctx; CCtx *ctx = GetCoroutineContext();
SearchOpenBuffersParams *param = (SearchOpenBuffersParams *)ctx->user_ctx;
Array<BufferID> buffers = {CoCurr->arena}; Array<BufferID> buffers = {ctx->arena};
For (Buffers) { For (Buffers) {
Add(&buffers, it->id); Add(&buffers, it->id);
} }
@@ -36,7 +37,7 @@ void Coro_SearchOpenBuffers(mco_coro *co) {
Appendf(out_view, "%S ||> %S:%lld:%lld\n", line_string8, it->name, (long long)line + 1, (long long)column + 1); Appendf(out_view, "%S ||> %S:%lld:%lld\n", line_string8, it->name, (long long)line + 1, (long long)column + 1);
} }
} }
CoYield(co); Yield(co);
} }
} }
@@ -55,14 +56,14 @@ void UpdateSearchOpenBuffersView() {
Replace(active.view, line_string); Replace(active.view, line_string);
Append(active.view, "\n", false); Append(active.view, "\n", false);
CoRemove("Coro_SearchOpenBuffers"); RemoveCoroutine("Coro_SearchOpenBuffers");
CoData *dat = CoAdd(Coro_SearchOpenBuffers); CCtx *dat = AddCoroutine(Coro_SearchOpenBuffers);
SearchOpenBuffersParams *param = AllocType(dat->arena, SearchOpenBuffersParams); SearchOpenBuffersParams *param = AllocType(dat->arena, SearchOpenBuffersParams);
param->needle = Copy16(dat->arena, line_string); param->needle = Copy16(dat->arena, line_string);
param->view = active.view->id; param->view = active.view->id;
dat->user_ctx = param; dat->user_ctx = param;
dat->dont_wait_until_resolved = true; dat->dont_wait_until_resolved = true;
CoResume(dat); ResumeCoroutine(dat);
active.view->carets[0] = caret; active.view->carets[0] = caret;
} }

View File

@@ -175,9 +175,9 @@ void ShowQuitAppUI(mco_coro *co) {
} }
void CMD_Quit() { void CMD_Quit() {
CoRemove("ShowQuitAppUI"); RemoveCoroutine("ShowQuitAppUI");
CoData *data = CoAdd(ShowQuitAppUI); CCtx *data = AddCoroutine(ShowQuitAppUI);
CoResume(data); ResumeCoroutine(data);
} RegisterCommand(CMD_Quit, "", "Ask user which files he would like to save and exit"); } RegisterCommand(CMD_Quit, "", "Ask user which files he would like to save and exit");
void OnCommand(Event event) { void OnCommand(Event event) {

View File

@@ -293,10 +293,10 @@ struct Register_Command {
}; };
#define RegisterCommand(name, binding, docs) Register_Command RC__##name(&GlobalCommands, name, #name, binding, docs) #define RegisterCommand(name, binding, docs) Register_Command RC__##name(&GlobalCommands, name, #name, binding, docs)
#define RegisterCoroutineCommand(name, binding, docs, ...) void CMD_##name() {\ #define RegisterCoroutineCommand(name, binding, docs, ...) void CMD_##name() {\
CoRemove(#name);\ RemoveCoroutine(#name);\
CoData *data = CoAdd(name);\ CCtx *data = AddCoroutine(name);\
__VA_ARGS__\ __VA_ARGS__\
CoResume(data);\ ResumeCoroutine(data);\
}\ }\
Register_Command RC__##name(&GlobalCommands, CMD_##name, #name, binding, docs) Register_Command RC__##name(&GlobalCommands, CMD_##name, #name, binding, docs)

View File

@@ -35,7 +35,7 @@ UIAction WaitForUIAction(mco_coro *co, BSet main) {
break; break;
} }
CoYield(co); Yield(co);
} }
Close(main.buffer->id); Close(main.buffer->id);
return result; return result;
@@ -118,8 +118,9 @@ String16 QueryUserString(mco_coro *co, String ask) {
// 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? // 3. Imagine a scenario where the coroutine gets deleted before completion, will the memory leak?
UIAction ShowCloseAllUI(mco_coro *co) { UIAction ShowCloseAllUI(mco_coro *co) {
CCtx *ctx = GetCoroutineContext();
BSet main = GetBSet(PrimaryWindowID); BSet main = GetBSet(PrimaryWindowID);
Array<BufferID> buffers = {CoCurr->arena}; Array<BufferID> buffers = {ctx->arena};
For (Buffers) Add(&buffers, it->id); For (Buffers) Add(&buffers, it->id);
ForItem (id, buffers) { ForItem (id, buffers) {
Buffer *it = GetBuffer(id, NULL); Buffer *it = GetBuffer(id, NULL);
@@ -130,7 +131,7 @@ UIAction ShowCloseAllUI(mco_coro *co) {
continue; continue;
} }
String question = Format(CoCurr->arena, "Do you want to save [%S] before closing?", it->name); String question = Format(ctx->arena, "Do you want to save [%S] before closing?", it->name);
UIAction ui_action = QueryUserYesNoCancel(co, main, question); UIAction ui_action = QueryUserYesNoCancel(co, main, question);
it = GetBuffer(id, NULL); it = GetBuffer(id, NULL);
if (it && ui_action == UIAction_Yes) { if (it && ui_action == UIAction_Yes) {
@@ -167,7 +168,7 @@ String QueryUserFile(mco_coro *co) {
break; break;
} }
CoYield(co); Yield(co);
} }
window->active_view = original_view; window->active_view = original_view;
return window->ui_query_file; return window->ui_query_file;