From f94151af2dd55fa585ccf8b97e49cf6ccd288778 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Fri, 26 Feb 2016 00:50:19 -0500 Subject: [PATCH] coroutines on windows via fibers --- 4coder_custom.h | 1 + 4ed.cpp | 2 +- 4ed_system.h | 34 ++++++++- buffer/4coder_buffer_abstract.cpp | 2 +- win32_4ed.cpp | 110 +++++++++++++++++++++++++++--- 5 files changed, 137 insertions(+), 12 deletions(-) diff --git a/4coder_custom.h b/4coder_custom.h index 96cca109..e55b0f68 100644 --- a/4coder_custom.h +++ b/4coder_custom.h @@ -254,6 +254,7 @@ extern "C"{ #define BUFFER_SEEK_DELIMITER_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out) #define BUFFER_READ_RANGE_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, int end, char *out) #define BUFFER_REPLACE_RANGE_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, int end, char *str, int len) +// TODO(allen): buffer save // File view manipulation #define GET_VIEW_MAX_INDEX_SIG(name) int name(void *cmd_context) diff --git a/4ed.cpp b/4ed.cpp index 3220020d..92bea35c 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -3280,7 +3280,7 @@ App_Init_Sig(app_init){ // NOTE(allen): file setup vars->working_set.file_index_count = 1; - vars->working_set.file_max_count = 29; + vars->working_set.file_max_count = 120; vars->working_set.files = push_array(partition, Editing_File, vars->working_set.file_max_count); diff --git a/4ed_system.h b/4ed_system.h index 19cc0e3b..012a5ed9 100644 --- a/4ed_system.h +++ b/4ed_system.h @@ -61,6 +61,32 @@ typedef Sys_CLI_Update_Step_Sig(System_CLI_Update_Step); #define Sys_CLI_End_Update_Sig(name) b32 name(CLI_Handles *cli) typedef Sys_CLI_End_Update_Sig(System_CLI_End_Update); +// coroutine + +#define Coroutine_Function_Sig(name) void name(struct Coroutine *coroutine) +typedef Coroutine_Function_Sig(Coroutine_Function); + +struct Coroutine{ + Plat_Handle plat_handle; + Coroutine_Function *func; + void *yield_handle; + void *in; + void *out; + i32 done; +}; + +#define Sys_Launch_Coroutine_Sig(name) Coroutine *name(Coroutine_Function *func, void *in, void *out) +typedef Sys_Launch_Coroutine_Sig(System_Launch_Coroutine); + +#define Sys_Resume_Coroutine_Sig(name) void name(Coroutine *coroutine, void *in, void *out) +typedef Sys_Resume_Coroutine_Sig(System_Resume_Coroutine); + +#define Sys_Yield_Coroutine_Sig(name) void *name(Coroutine *coroutine) +typedef Sys_Yield_Coroutine_Sig(System_Yield_Coroutine); + +#define Sys_Release_Coroutine_Sig(name) void name(Coroutine *coroutine) +typedef Sys_Release_Coroutine_Sig(System_Relase_Coroutine); + // thread struct Thread_Context; @@ -170,7 +196,13 @@ struct System_Functions{ // time: 1 System_Time *time; - + + // coroutine: 4 + System_Launch_Coroutine *launch_coroutine; + System_Resume_Coroutine *resume_coroutine; + System_Yield_Coroutine *yield_coroutine; + System_Relase_Coroutine *release_coroutine; + // cli: 4 System_CLI_Call *cli_call; System_CLI_Begin_Update *cli_begin_update; diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp index 34452ce8..0607791a 100644 --- a/buffer/4coder_buffer_abstract.cpp +++ b/buffer/4coder_buffer_abstract.cpp @@ -433,10 +433,10 @@ buffer_seek_range_camel_left(Buffer_Type *buffer, int pos, int an_pos){ assert_4tech(an_pos <= pos); assert_4tech(0 <= an_pos); + --pos; loop = buffer_backify_loop(buffer, pos, an_pos+1); if (buffer_backify_good(&loop)){ prev_ch = loop.data[0]; - --pos; for (;buffer_backify_good(&loop); buffer_backify_next(&loop)){ diff --git a/win32_4ed.cpp b/win32_4ed.cpp index 7145ad85..057ce0f3 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -99,6 +99,11 @@ struct Win32_Input_Chunk{ Win32_Input_Chunk_Persistent pers; }; +struct Win32_Coroutine{ + Coroutine coroutine; + Win32_Coroutine *next; +}; + struct Win32_Vars{ HWND window_handle; HDC window_hdc; @@ -146,8 +151,14 @@ struct Win32_Vars{ #if FRED_INTERNAL Sys_Bubble internal_bubble; #endif - + Font_Load_System fnt; + + // NOTE(allen): I don't expect to have many of these, but it pays + // to look a head a little so this is set up so that we can just bump + // it up if needed. + Win32_Coroutine coroutine_data[2]; + Win32_Coroutine *coroutine_free; }; globalvar Win32_Vars win32vars; @@ -570,16 +581,22 @@ Win32Resize(i32 width, i32 height){ internal HANDLE Win32Handle(Plat_Handle h){ HANDLE result; - result = {}; - result = *(HANDLE*)(&h); + memcpy(&result, &h, sizeof(result)); + return(result); +} + +internal void* +Win32Ptr(Plat_Handle h){ + void *result; + memcpy(&result, &h, sizeof(result)); return(result); } internal Plat_Handle Win32GenHandle(HANDLE h){ - Assert(sizeof(Plat_Handle) >= sizeof(HANDLE)); - Plat_Handle result; - result = *(Plat_Handle*)(&h); + Plat_Handle result = {}; + Assert(sizeof(Plat_Handle) >= sizeof(h)); + memcpy(&result, &h, sizeof(h)); return(result); } @@ -705,11 +722,11 @@ system_grow_thread_memory(Thread_Memory *memory){ old_data = memory->data; old_size = memory->size; new_size = LargeRoundUp(memory->size*2, Kbytes(4)); - memory->data = Win32GetMemory(new_size); + memory->data = system_get_memory(new_size); memory->size = new_size; if (old_data){ memcpy(memory->data, old_data, old_size); - Win32FreeMemory(old_data); + system_free_memory(old_data); } system_release_lock(CANCEL_LOCK0 + memory->id - 1); } @@ -730,6 +747,76 @@ INTERNAL_get_thread_states(Thread_Group_ID id, bool8 *running, i32 *pending){ } #endif +internal Coroutine* +Win32AllocCoroutine(){ + Win32_Coroutine *result = win32vars.coroutine_free; + Assert(result != 0); + win32vars.coroutine_free = result->next; + return(&result->coroutine); +} + +internal void +Win32FreeCoroutine(Coroutine *coroutine){ + Win32_Coroutine *data = (Win32_Coroutine*)coroutine; + data->next = win32vars.coroutine_free; + win32vars.coroutine_free = data; +} + +internal void +Win32CoroutineMain(void *arg_){ + Coroutine *coroutine = (Coroutine*)arg_; + coroutine->func(coroutine); + coroutine->done = 1; + SwitchToFiber(coroutine->yield_handle); +} + +internal +Sys_Launch_Coroutine_Sig(system_launch_coroutine){ + Coroutine *coroutine; + void *fiber; + + coroutine = Win32AllocCoroutine(); + + fiber = CreateFiber(0, Win32CoroutineMain, coroutine); + + coroutine->plat_handle = Win32GenHandle(fiber); + coroutine->func = func; + coroutine->yield_handle = GetCurrentFiber(); + coroutine->in = in; + coroutine->out = out; + coroutine->done = 0; + + SwitchToFiber(fiber); + + return(coroutine); +} + +Sys_Resume_Coroutine_Sig(system_resume_coroutine){ + void *fiber; + + Assert(coroutine->done == 0); + + coroutine->yield_handle = GetCurrentFiber(); + coroutine->in = in; + coroutine->out = out; + + fiber = Win32Ptr(coroutine->plat_handle); + + SwitchToFiber(fiber); +} + +Sys_Yield_Coroutine_Sig(system_yield_coroutine){ + void *result; + SwitchToFiber(coroutine->yield_handle); + result = coroutine->in; + return(result); +} + +Sys_Release_Coroutine_Sig(system_release_coroutine){ + Assert(coroutine->done); + Win32FreeCoroutine(coroutine); +} + internal Sys_CLI_Call_Sig(system_cli_call){ char cmd[] = "c:\\windows\\system32\\cmd.exe"; @@ -947,6 +1034,11 @@ Win32LoadSystemCode(){ win32vars.system->post_clipboard = system_post_clipboard; win32vars.system->time = system_time; + win32vars.system->launch_coroutine = system_launch_coroutine; + win32vars.system->resume_coroutine = system_resume_coroutine; + win32vars.system->yield_coroutine = system_yield_coroutine; + win32vars.system->release_coroutine = system_release_coroutine; + win32vars.system->cli_call = system_cli_call; win32vars.system->cli_begin_update = system_cli_begin_update; win32vars.system->cli_update_step = system_cli_update_step; @@ -1780,7 +1872,7 @@ main(int argc, char **argv){ } - File_Slot file_slots[32]; + File_Slot file_slots[120]; sysshared_init_file_exchange(&exchange_vars, file_slots, ArrayCount(file_slots), 0); Font_Load_Parameters params[32];