almost finished with a generalized coroutine solution

master
Allen Webster 2017-07-19 16:07:50 -04:00
parent 681f53fae1
commit e4a4608007
14 changed files with 477 additions and 321 deletions

64
4ed.cpp
View File

@ -304,9 +304,9 @@ restore_state(Application_Links *app, App_Coroutine_State state){
app->type_coroutine = state.type; app->type_coroutine = state.type;
} }
inline Coroutine* inline Coroutine_Head*
app_launch_coroutine(System_Functions *system, Application_Links *app, Coroutine_Type type, Coroutine *co, void *in, void *out){ app_launch_coroutine(System_Functions *system, Application_Links *app, Coroutine_Type type, Coroutine_Head *co, void *in, void *out){
Coroutine* result = 0; Coroutine_Head *result = 0;
App_Coroutine_State prev_state = get_state(app); App_Coroutine_State prev_state = get_state(app);
@ -318,9 +318,9 @@ app_launch_coroutine(System_Functions *system, Application_Links *app, Coroutine
return(result); return(result);
} }
inline Coroutine* inline Coroutine_Head*
app_resume_coroutine(System_Functions *system, Application_Links *app, Coroutine_Type type, Coroutine *co, void *in, void *out){ app_resume_coroutine(System_Functions *system, Application_Links *app, Coroutine_Type type, Coroutine_Head *co, void *in, void *out){
Coroutine* result = 0; Coroutine_Head *result = 0;
App_Coroutine_State prev_state = get_state(app); App_Coroutine_State prev_state = get_state(app);
@ -614,7 +614,7 @@ struct Command_In{
}; };
internal void internal void
command_caller(Coroutine *coroutine){ command_caller(Coroutine_Head *coroutine){
Command_In *cmd_in = (Command_In*)coroutine->in; Command_In *cmd_in = (Command_In*)coroutine->in;
Command_Data *command = cmd_in->cmd; Command_Data *command = cmd_in->cmd;
Models *models = command->models; Models *models = command->models;
@ -778,19 +778,19 @@ enum Command_Line_Mode{
}; };
internal void internal void
init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings, Command_Line_Parameters clparams){ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings, i32 argc, char **argv){
char *arg = 0; char *arg = 0;
Command_Line_Mode mode = CLMode_App; Command_Line_Mode mode = CLMode_App;
Command_Line_Action action = CLAct_Nothing; Command_Line_Action action = CLAct_Nothing;
b32 strict = false; b32 strict = false;
settings->init_files_max = ArrayCount(settings->init_files); settings->init_files_max = ArrayCount(settings->init_files);
for (i32 i = 1; i <= clparams.argc; ++i){ for (i32 i = 1; i <= argc; ++i){
if (i == clparams.argc){ if (i == argc){
arg = ""; arg = "";
} }
else{ else{
arg = clparams.argv[i]; arg = argv[i];
} }
if (arg[0] == '-' && arg[1] == '-'){ if (arg[0] == '-' && arg[1] == '-'){
@ -838,27 +838,27 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
case CLAct_CustomDLL: case CLAct_CustomDLL:
{ {
plat_settings->custom_dll_is_strict = (b8)strict; plat_settings->custom_dll_is_strict = (b8)strict;
if (i < clparams.argc){ if (i < argc){
plat_settings->custom_dll = clparams.argv[i]; plat_settings->custom_dll = argv[i];
} }
action = CLAct_Nothing; action = CLAct_Nothing;
}break; }break;
case CLAct_InitialFilePosition: case CLAct_InitialFilePosition:
{ {
if (i < clparams.argc){ if (i < argc){
settings->initial_line = str_to_int_c(clparams.argv[i]); settings->initial_line = str_to_int_c(argv[i]);
} }
action = CLAct_Nothing; action = CLAct_Nothing;
}break; }break;
case CLAct_WindowSize: case CLAct_WindowSize:
{ {
if (i + 1 < clparams.argc){ if (i + 1 < argc){
plat_settings->set_window_size = true; plat_settings->set_window_size = true;
i32 w = str_to_int_c(clparams.argv[i]); i32 w = str_to_int_c(argv[i]);
i32 h = str_to_int_c(clparams.argv[i+1]); i32 h = str_to_int_c(argv[i+1]);
if (w > 0){ if (w > 0){
plat_settings->window_w = w; plat_settings->window_w = w;
} }
@ -880,11 +880,11 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
case CLAct_WindowPosition: case CLAct_WindowPosition:
{ {
if (i + 1 < clparams.argc){ if (i + 1 < argc){
plat_settings->set_window_pos = true; plat_settings->set_window_pos = true;
i32 x = str_to_int_c(clparams.argv[i]); i32 x = str_to_int_c(argv[i]);
i32 y = str_to_int_c(clparams.argv[i+1]); i32 y = str_to_int_c(argv[i+1]);
if (x > 0){ if (x > 0){
plat_settings->window_x = x; plat_settings->window_x = x;
} }
@ -906,8 +906,8 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
case CLAct_FontSize: case CLAct_FontSize:
{ {
if (i < clparams.argc){ if (i < argc){
plat_settings->font_size = str_to_int_c(clparams.argv[i]); plat_settings->font_size = str_to_int_c(argv[i]);
plat_settings->font_size = clamp_bottom(8, plat_settings->font_size); plat_settings->font_size = clamp_bottom(8, plat_settings->font_size);
} }
action = CLAct_Nothing; action = CLAct_Nothing;
@ -935,9 +935,9 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
case CLMode_Custom: case CLMode_Custom:
{ {
settings->custom_flags = clparams.argv + i; settings->custom_flags = argv + i;
settings->custom_flags_count = clparams.argc - i; settings->custom_flags_count = argc - i;
i = clparams.argc; i = argc;
mode = CLMode_App; mode = CLMode_App;
}break; }break;
} }
@ -969,8 +969,8 @@ App_Read_Command_Line_Sig(app_read_command_line){
*settings = null_app_settings; *settings = null_app_settings;
plat_settings->font_size = 16; plat_settings->font_size = 16;
if (clparams.argc > 1){ if (argc > 1){
init_command_line_settings(&vars->models.settings, plat_settings, clparams); init_command_line_settings(&vars->models.settings, plat_settings, argc, argv);
} }
*files = vars->models.settings.init_files; *files = vars->models.settings.init_files;
@ -1623,11 +1623,11 @@ App_Step_Sig(app_step){
} }
if (there_is_unsaved){ if (there_is_unsaved){
Coroutine *command_coroutine = models->command_coroutine; Coroutine_Head *command_coroutine = models->command_coroutine;
Command_Data *command = cmd; Command_Data *command = cmd;
USE_VIEW(view); USE_VIEW(view);
for (i32 i = 0; i < 128 && command_coroutine; ++i){ for (i32 i = 0; i < 128 && command_coroutine != 0; ++i){
User_Input user_in = {0}; User_Input user_in = {0};
user_in.abort = true; user_in.abort = true;
@ -1686,7 +1686,7 @@ App_Step_Sig(app_step){
// NOTE(allen): Keyboard and Mouse input to command coroutine. // NOTE(allen): Keyboard and Mouse input to command coroutine.
if (models->command_coroutine != 0){ if (models->command_coroutine != 0){
Coroutine *command_coroutine = models->command_coroutine; Coroutine_Head *command_coroutine = models->command_coroutine;
u32 get_flags = models->command_coroutine_flags[0]; u32 get_flags = models->command_coroutine_flags[0];
u32 abort_flags = models->command_coroutine_flags[1]; u32 abort_flags = models->command_coroutine_flags[1];
@ -1969,7 +1969,7 @@ App_Step_Sig(app_step){
} }
Assert(models->command_coroutine == 0); Assert(models->command_coroutine == 0);
Coroutine *command_coroutine = system->create_coroutine(command_caller); Coroutine_Head *command_coroutine = system->create_coroutine(command_caller);
models->command_coroutine = command_coroutine; models->command_coroutine = command_coroutine;
Command_In cmd_in; Command_In cmd_in;

10
4ed.h
View File

@ -46,11 +46,6 @@ struct Input_Summary{
f32 dt; f32 dt;
}; };
struct Command_Line_Parameters{
char **argv;
int32_t argc;
};
typedef u8 Log_To_Type; typedef u8 Log_To_Type;
enum{ enum{
LogTo_Nothing, LogTo_Nothing,
@ -77,7 +72,7 @@ struct Plat_Settings{
}; };
#define App_Read_Command_Line_Sig(name) \ #define App_Read_Command_Line_Sig(name) \
i32 name(System_Functions *system, Application_Memory *memory, String current_directory, Plat_Settings *plat_settings, char ***files, i32 **file_count, Command_Line_Parameters clparams) i32 name(System_Functions *system, Application_Memory *memory, String current_directory, Plat_Settings *plat_settings, char ***files, i32 **file_count, i32 argc, char **argv)
typedef App_Read_Command_Line_Sig(App_Read_Command_Line); typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
@ -123,8 +118,7 @@ name(System_Functions *system, \
Render_Target *target, \ Render_Target *target, \
Application_Memory *memory, \ Application_Memory *memory, \
Application_Step_Input *input, \ Application_Step_Input *input, \
Application_Step_Result *app_result_, \ Application_Step_Result *app_result_)
Command_Line_Parameters params)
typedef App_Step_Sig(App_Step); typedef App_Step_Sig(App_Step);

View File

@ -2069,11 +2069,11 @@ DOC_SEE(User_Input)
*/{ */{
Command_Data *cmd = (Command_Data*)app->cmd_context; Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system; System_Functions *system = cmd->system;
Coroutine *coroutine = (Coroutine*)app->current_coroutine; Coroutine_Head *coroutine = (Coroutine_Head*)app->current_coroutine;
User_Input result = {0}; User_Input result = {0};
if (app->type_coroutine == Co_Command){ if (app->type_coroutine == Co_Command){
Assert(coroutine); Assert(coroutine != 0);
*((u32*)coroutine->out+0) = get_type; *((u32*)coroutine->out+0) = get_type;
*((u32*)coroutine->out+1) = abort_type; *((u32*)coroutine->out+1) = abort_type;
system->yield_coroutine(coroutine); system->yield_coroutine(coroutine);

View File

@ -57,7 +57,7 @@ struct Models{
Command_Binding prev_command; Command_Binding prev_command;
Coroutine *command_coroutine; Coroutine_Head *command_coroutine;
u32 command_coroutine_flags[2]; u32 command_coroutine_flags[2];
Hook_Function *hooks[hook_type_count]; Hook_Function *hooks[hook_type_count];

View File

@ -90,27 +90,25 @@ typedef Sys_CLI_Update_Step_Sig(System_CLI_Update_Step);
typedef Sys_CLI_End_Update_Sig(System_CLI_End_Update); typedef Sys_CLI_End_Update_Sig(System_CLI_End_Update);
// coroutine // coroutine
#define Coroutine_Function_Sig(name) void name(struct Coroutine *coroutine)
typedef Coroutine_Function_Sig(Coroutine_Function);
struct Coroutine{ struct Coroutine_Head{
Plat_Handle plat_handle;
Coroutine_Function *func;
void *yield_handle;
void *in; void *in;
void *out; void *out;
}; };
#define Sys_Create_Coroutine_Sig(name) Coroutine *name(Coroutine_Function *func) #define COROUTINE_SIG(n) void n(Coroutine_Head *coroutine)
typedef COROUTINE_SIG(Coroutine_Function);
#define Sys_Create_Coroutine_Sig(name) Coroutine_Head *name(Coroutine_Function *func)
typedef Sys_Create_Coroutine_Sig(System_Create_Coroutine); typedef Sys_Create_Coroutine_Sig(System_Create_Coroutine);
#define Sys_Launch_Coroutine_Sig(name) Coroutine *name(Coroutine *coroutine, void *in, void *out) #define Sys_Launch_Coroutine_Sig(name) Coroutine_Head *name(Coroutine_Head *head, void *in, void *out)
typedef Sys_Launch_Coroutine_Sig(System_Launch_Coroutine); typedef Sys_Launch_Coroutine_Sig(System_Launch_Coroutine);
#define Sys_Resume_Coroutine_Sig(name) Coroutine *name(Coroutine *coroutine, void *in, void *out) #define Sys_Resume_Coroutine_Sig(name) Coroutine_Head *name(Coroutine_Head *head, void *in, void *out)
typedef Sys_Resume_Coroutine_Sig(System_Resume_Coroutine); typedef Sys_Resume_Coroutine_Sig(System_Resume_Coroutine);
#define Sys_Yield_Coroutine_Sig(name) void name(Coroutine *coroutine) #define Sys_Yield_Coroutine_Sig(name) void name(Coroutine_Head *head)
typedef Sys_Yield_Coroutine_Sig(System_Yield_Coroutine); typedef Sys_Yield_Coroutine_Sig(System_Yield_Coroutine);
// thread // thread

View File

@ -14,7 +14,7 @@
struct View_Persistent{ struct View_Persistent{
i32 id; i32 id;
Coroutine *coroutine; Coroutine_Head *coroutine;
Event_Message message_passing_slot; Event_Message message_passing_slot;
}; };

View File

@ -1,8 +1,11 @@
/* /*
4tech_file_moving.h - Code for moving files around on the file system. * Mr. 4th Dimention - Allen Webster
By Allen Webster *
21.01.2017 (dd.mm.yyyy) * 21.01.2017
*/ *
* Moving files around on the file system.
*
*/
// TOP // TOP
@ -302,9 +305,9 @@ extern "C"{
#define FILE_ATTRIBUTE_NORMAL 0x00000080 #define FILE_ATTRIBUTE_NORMAL 0x00000080
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100 #define FILE_ATTRIBUTE_TEMPORARY 0x00000100
static u64 perf_frequency; global u64 perf_frequency;
static void internal void
fm_init_system(){ fm_init_system(){
LARGE_INTEGER lint; LARGE_INTEGER lint;
if (QueryPerformanceFrequency(&lint)){ if (QueryPerformanceFrequency(&lint)){
@ -313,7 +316,7 @@ fm_init_system(){
fm__init_memory(); fm__init_memory();
} }
static Temp_Dir internal Temp_Dir
fm_pushdir(char *dir){ fm_pushdir(char *dir){
Temp_Dir temp = {0}; Temp_Dir temp = {0};
GetCurrentDirectoryA(sizeof(temp.dir), temp.dir); GetCurrentDirectoryA(sizeof(temp.dir), temp.dir);
@ -321,12 +324,12 @@ fm_pushdir(char *dir){
return(temp); return(temp);
} }
static void internal void
fm_popdir(Temp_Dir temp){ fm_popdir(Temp_Dir temp){
SetCurrentDirectoryA(temp.dir); SetCurrentDirectoryA(temp.dir);
} }
static u64 internal u64
fm_get_time(){ fm_get_time(){
u64 time = 0; u64 time = 0;
LARGE_INTEGER lint; LARGE_INTEGER lint;
@ -337,13 +340,13 @@ fm_get_time(){
return(time); return(time);
} }
static i32 internal i32
fm_get_current_directory(char *buffer, i32 max){ fm_get_current_directory(char *buffer, i32 max){
i32 result = GetCurrentDirectoryA(max, buffer); i32 result = GetCurrentDirectoryA(max, buffer);
return(result); return(result);
} }
static void internal void
fm_execute_in_dir(char *dir, char *str, char *args){ fm_execute_in_dir(char *dir, char *str, char *args){
if (dir){ if (dir){
Temp_Dir temp = fm_pushdir(dir); Temp_Dir temp = fm_pushdir(dir);
@ -365,7 +368,7 @@ fm_execute_in_dir(char *dir, char *str, char *args){
} }
} }
static void internal void
fm_slash_fix(char *path){ fm_slash_fix(char *path){
if (path != 0){ if (path != 0){
for (i32 i = 0; path[i]; ++i){ for (i32 i = 0; path[i]; ++i){
@ -374,7 +377,7 @@ fm_slash_fix(char *path){
} }
} }
static void internal void
fm_make_folder_if_missing(char *dir){ fm_make_folder_if_missing(char *dir){
char *path = fm_str(dir); char *path = fm_str(dir);
char *p = path; char *p = path;
@ -388,23 +391,23 @@ fm_make_folder_if_missing(char *dir){
CreateDirectoryA(path, 0); CreateDirectoryA(path, 0);
} }
static void internal void
fm_clear_folder(char *folder){ fm_clear_folder(char *folder){
fprintf(stdout, "clearing folder %s\n", folder); fprintf(stdout, "clearing folder %s\n", folder);
systemf("del /S /Q /F %s\\* > nul & rmdir /S /Q %s > nul & mkdir %s > nul", folder, folder, folder); systemf("del /S /Q /F %s\\* > nul & rmdir /S /Q %s > nul & mkdir %s > nul", folder, folder, folder);
} }
static void internal void
fm_delete_file(char *file){ fm_delete_file(char *file){
systemf("del %s", file); systemf("del %s", file);
} }
static void internal void
fm_copy_file(char *file, char *newname){ fm_copy_file(char *file, char *newname){
CopyFileA(file, newname, 0); CopyFileA(file, newname, 0);
} }
static void internal void
fm_copy_all(char *source, char *tag, char *folder){ fm_copy_all(char *source, char *tag, char *folder){
if (source){ if (source){
fprintf(stdout, "copy %s\\%s to %s\n", source, tag, folder); fprintf(stdout, "copy %s\\%s to %s\n", source, tag, folder);
@ -433,7 +436,7 @@ fm_write_file(char *file_name, char *data, u32 size){
} }
} }
static void internal void
fm_zip(char *parent, char *folder, char *dest){ fm_zip(char *parent, char *folder, char *dest){
char cdir[512]; char cdir[512];
fm_get_current_directory(cdir, sizeof(cdir)); fm_get_current_directory(cdir, sizeof(cdir));
@ -454,7 +457,7 @@ fm_zip(char *parent, char *folder, char *dest){
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
static Temp_Dir internal Temp_Dir
fm_pushdir(char *dir){ fm_pushdir(char *dir){
Temp_Dir temp; Temp_Dir temp;
char *result = getcwd(temp.dir, sizeof(temp.dir)); char *result = getcwd(temp.dir, sizeof(temp.dir));
@ -467,17 +470,17 @@ fm_pushdir(char *dir){
return(temp); return(temp);
} }
static void internal void
fm_popdir(Temp_Dir temp){ fm_popdir(Temp_Dir temp){
chdir(temp.dir); chdir(temp.dir);
} }
static void internal void
fm_init_system(){ fm_init_system(){
fm__init_memory(); fm__init_memory();
} }
static u64 internal u64
fm_get_time(){ fm_get_time(){
struct timespec spec; struct timespec spec;
u64 result; u64 result;
@ -486,7 +489,7 @@ fm_get_time(){
return(result); return(result);
} }
static i32 internal i32
fm_get_current_directory(char *buffer, i32 max){ fm_get_current_directory(char *buffer, i32 max){
i32 result = 0; i32 result = 0;
char *d = getcwd(buffer, max); char *d = getcwd(buffer, max);
@ -496,7 +499,7 @@ fm_get_current_directory(char *buffer, i32 max){
return(result); return(result);
} }
static void internal void
fm_execute_in_dir(char *dir, char *str, char *args){ fm_execute_in_dir(char *dir, char *str, char *args){
if (dir){ if (dir){
if (args){ if (args){
@ -520,31 +523,31 @@ fm_execute_in_dir(char *dir, char *str, char *args){
} }
} }
static void internal void
fm_slash_fix(char *path){} fm_slash_fix(char *path){}
static void internal void
fm_make_folder_if_missing(char *dir){ fm_make_folder_if_missing(char *dir){
systemf("mkdir -p %s", dir); systemf("mkdir -p %s", dir);
} }
static void internal void
fm_clear_folder(char *folder){ fm_clear_folder(char *folder){
fprintf(stdout, "clearing folder %s\n", folder); fprintf(stdout, "clearing folder %s\n", folder);
systemf("rm -rf %s* > /dev/null", folder); systemf("rm -rf %s* > /dev/null", folder);
} }
static void internal void
fm_delete_file(char *file){ fm_delete_file(char *file){
systemf("rm %s", file); systemf("rm %s", file);
} }
static void internal void
fm_copy_file(char *file, char *newname){ fm_copy_file(char *file, char *newname){
systemf("cp %s %s", file, newname); systemf("cp %s %s", file, newname);
} }
static void internal void
fm_copy_all(char *source, char *tag, char *folder){ fm_copy_all(char *source, char *tag, char *folder){
if (source){ if (source){
fprintf(stdout, "copy %s/%s to %s\n", source, tag, folder); fprintf(stdout, "copy %s/%s to %s\n", source, tag, folder);
@ -566,7 +569,7 @@ fm_write_file(char *file_name, char *data, u32 size){
} }
} }
static void internal void
fm_zip(char *parent, char *folder, char *file){ fm_zip(char *parent, char *folder, char *file){
Temp_Dir temp = fm_pushdir(parent); Temp_Dir temp = fm_pushdir(parent);
printf("PARENT DIR: %s\n", parent); printf("PARENT DIR: %s\n", parent);

View File

@ -0,0 +1,253 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 19.07.2017
*
* Coroutine implementation from thread+mutex+cv
*
*/
// TOP
typedef u32 Coroutine_State;
enum{
CoroutineState_Dead,
CoroutineState_Active,
CoroutineState_Inactive,
CoroutineState_Waiting,
};
typedef u32 Coroutine_Type;
enum{
CoroutineType_Uninitialized,
CoroutineType_Root,
CoroutineType_Sub,
};
struct Coroutine{
Coroutine_Head head;
Thread thread;
Condition_Variable cv;
struct Coroutine_System *sys;
Coroutine_Function *function;
Coroutine *yield_ctx;
Coroutine_State state;
Coroutine_Type type;
};
struct Coroutine_System{
Mutex lock;
Condition_Variable init_cv;
b32 did_init;
Coroutine *active;
};
#define COROUTINE_INT_SKIP_SLEEP false
internal void
coroutine_internal_pass_control(Coroutine *me, Coroutine *other, Coroutine_State my_new_state, b32 do_sleep_loop = true){
Assert(me->state == CoroutineState_Active);
Assert(me->sys == other->sys);
me->state = my_new_state;
other->state = CoroutineState_Active;
me->sys->active = other;
system_signal_cv(&other->cv, &me->sys->lock);
if (do_sleep_loop){
for (;me->state != CoroutineState_Active;){
system_wait_cv(&me->cv, &me->sys->lock);
}
}
}
internal
PLAT_THREAD_SIG(coroutine_main){
Coroutine *me = (Coroutine*)ptr;
// NOTE(allen): Init handshake
Assert(me->state == CoroutineState_Dead);
system_acquire_lock(&me->sys->lock);
me->sys->did_init = true;
system_signal_cv(&me->sys->init_cv, &me->sys->lock);
for (;;){
// NOTE(allen): Wait until someone wakes us up, then go into our procedure.
for (;me->state != CoroutineState_Active;){
system_wait_cv(&me->cv, &me->sys->lock);
}
Assert(me->type != CoroutineType_Root);
Assert(me->yield_ctx != 0);
Assert(me->function != 0);
me->function(&me->head);
// NOTE(allen): Wake up the caller and set this coroutine back to being dead.
Coroutine *other = me->yield_ctx;
Assert(other != 0);
Assert(other->state == CoroutineState_Waiting);
coroutine_internal_pass_control(me, other, CoroutineState_Dead, COROUTINE_INT_SKIP_SLEEP);
me->function = 0;
}
}
internal void
init_coroutine_system(Coroutine *root, Coroutine_System *sys){
system_init_lock(&sys->lock);
system_init_cv(&sys->init_cv);
sys->active = root;
memset(root, 0, sizeof(*root));
root->sys = sys;
root->state = CoroutineState_Active;
root->type = CoroutineType_Root;
system_init_cv(&root->cv);
}
internal void
init_coroutine_sub(Coroutine *co, Coroutine_System *sys){
memset(co, 0, sizeof(*co));
co->sys = sys;
co->state = CoroutineState_Dead;
co->type = CoroutineType_Sub;
system_init_cv(&co->cv);
sys->did_init = false;
system_init_and_launch_thread(&co->thread, coroutine_main, co);
for (;!sys->did_init;){
system_wait_cv(&sys->init_cv, &sys->lock);
}
}
// HACK(allen): I want to bundle this with launch!
internal void
coroutine_set_function(Coroutine *me, Coroutine_Function *function){
Assert(me->state == CoroutineState_Dead);
me->function = function;
}
internal void
coroutine_launch(Coroutine *me, Coroutine *other){
Assert(me->sys == other->sys);
Assert(other->state == CoroutineState_Dead);
Assert(other->function != 0);
other->yield_ctx = me;
coroutine_internal_pass_control(me, other, CoroutineState_Waiting);
}
internal void
coroutine_yield(Coroutine *me){
Coroutine *other = me->yield_ctx;
Assert(other != 0);
Assert(me->sys == other->sys);
Assert(other->state == CoroutineState_Waiting);
coroutine_internal_pass_control(me, other, CoroutineState_Inactive);
}
internal void
coroutine_resume(Coroutine *me, Coroutine *other){
Assert(me->sys == other->sys);
Assert(other->state == CoroutineState_Inactive);
other->yield_ctx = me;
coroutine_internal_pass_control(me, other, CoroutineState_Waiting);
}
////////////////////////////////
struct Coroutine_Alloc_Block{
Coroutine coroutine;
Coroutine_Alloc_Block *next;
};
#define COROUTINE_SLOT_SIZE sizeof(Coroutine_Alloc_Block)
struct Coroutine_System_Auto_Alloc{
Coroutine_System sys;
Coroutine root;
Coroutine_Alloc_Block *head_free_uninit;
Coroutine_Alloc_Block *head_free_inited;
};
internal void
init_coroutine_system(Coroutine_System_Auto_Alloc *sys){
init_coroutine_system(&sys->root, &sys->sys);
sys->head_free_uninit = 0;
sys->head_free_inited = 0;
}
internal void
coroutine_system_provide_memory(Coroutine_System_Auto_Alloc *sys, void *memory, umem size){
memset(memory, 0, size);
Coroutine_Alloc_Block *blocks = (Coroutine_Alloc_Block*)memory;
umem count = (size / sizeof(*blocks));
Coroutine_Alloc_Block *old_head = sys->head_free_uninit;
sys->head_free_uninit = &blocks[0];
Coroutine_Alloc_Block *block = blocks;
for (u32 i = 1; i < count; ++i, ++block){
block->next = block + 1;
}
block->next = old_head;
}
internal Coroutine_Alloc_Block*
coroutine_system_pop(Coroutine_Alloc_Block **head){
Coroutine_Alloc_Block *result = *head;
if (result != 0){
*head = result->next;
}
result->next = 0;
return(result);
}
internal void
coroutine_system_push(Coroutine_Alloc_Block **head, Coroutine_Alloc_Block *block){
block->next = *head;
*head = block;
}
internal void
coroutine_system_force_init(Coroutine_System_Auto_Alloc *sys, u32 count){
for (u32 i = 0; i < count; ++i){
Coroutine_Alloc_Block *block = coroutine_system_pop(&sys->head_free_uninit);
if (block == 0){
break;
}
init_coroutine_sub(&block->coroutine, &sys->sys);
coroutine_system_push(&sys->head_free_inited, block);
}
}
internal Coroutine*
coroutine_system_alloc(Coroutine_System_Auto_Alloc *sys){
Coroutine_Alloc_Block *block = coroutine_system_pop(&sys->head_free_inited);
if (block == 0){
coroutine_system_force_init(sys, 1);
block = coroutine_system_pop(&sys->head_free_inited);
}
Coroutine *result = 0;
if (block != 0){
result = &block->coroutine;
}
return(result);
}
internal void
coroutine_system_free(Coroutine_System_Auto_Alloc *sys, Coroutine *co){
Coroutine_Alloc_Block *block = (Coroutine_Alloc_Block*)co;
coroutine_system_push(&sys->head_free_inited, block);
}
// BOTTOM

View File

@ -10,7 +10,7 @@
// TOP // TOP
internal void internal void
system_memory_init(){ memory_init(){
#if defined(FRED_INTERNAL) #if defined(FRED_INTERNAL)
# if defined(FTECH_64_BIT) # if defined(FTECH_64_BIT)
void *bases[] = { (void*)TB(1), (void*)TB(2), }; void *bases[] = { (void*)TB(1), (void*)TB(2), };
@ -120,5 +120,25 @@ load_custom_code(){
LOGF("Loaded custom file: %s\n", success_file); LOGF("Loaded custom file: %s\n", success_file);
} }
internal void
read_command_line(i32 argc, char **argv){
LOG("Reading command line\n");
char cwd[4096];
u32 size = sysfunc.get_current_path(cwd, sizeof(cwd));
if (size == 0 || size >= sizeof(cwd)){
system_error_box("Could not get current directory at launch.");
}
String curdir = make_string_cap(cwd, size, sizeof(cwd));
terminate_with_null(&curdir);
replace_char(&curdir, '\\', '/');
char **files = 0;
i32 *file_count = 0;
app.read_command_line(&sysfunc, &memory_vars, curdir, &plat_settings, &files, &file_count, argc, argv);
sysshared_filter_real_files(files, file_count);
LOG("Read command line.\n");
}
// BOTTOM // BOTTOM

View File

@ -85,7 +85,8 @@ system_load_library(Library *library, char *name, Load_Library_Location location
internal b32 internal b32
system_load_library(Library *library, char *name, Load_Library_Location location){ system_load_library(Library *library, char *name, Load_Library_Location location){
system_load_library(library, name, location, 0, 0); b32 result = system_load_library(library, name, location, 0, 0);
return(result);
} }
#endif #endif

View File

@ -369,7 +369,7 @@ INTERNAL_Sys_Get_Thread_States_Sig(system_internal_get_thread_states){
} }
internal void internal void
system_init_threaded_work_system(){ work_system_init(){
AssertThreadSizes(); AssertThreadSizes();
u32 core_count = CORE_COUNT; u32 core_count = CORE_COUNT;

View File

@ -105,14 +105,6 @@ enum {
LINUX_4ED_EVENT_CLI = (UINT64_C(5) << 32), LINUX_4ED_EVENT_CLI = (UINT64_C(5) << 32),
}; };
struct Linux_Coroutine {
Coroutine coroutine;
Linux_Coroutine *next;
ucontext_t ctx, yield_ctx;
stack_t stack;
b32 done;
};
// //
// Linux forward declarations // Linux forward declarations
// //
@ -129,6 +121,8 @@ global System_Functions sysfunc;
#include "linux_library_wrapper.h" #include "linux_library_wrapper.h"
#include "4ed_standard_libraries.cpp" #include "4ed_standard_libraries.cpp"
#include "4ed_coroutine.cpp"
//////////////////////////////// ////////////////////////////////
struct Linux_Vars{ struct Linux_Vars{
@ -183,9 +177,6 @@ struct Linux_Vars{
i32 dpi_x, dpi_y; i32 dpi_x, dpi_y;
b32 vsync; b32 vsync;
Linux_Coroutine coroutine_data[18];
Linux_Coroutine *coroutine_free;
}; };
//////////////////////////////// ////////////////////////////////
@ -199,6 +190,8 @@ global Libraries libraries;
global App_Functions app; global App_Functions app;
global Custom_API custom_api; global Custom_API custom_api;
global Coroutine_System_Auto_Alloc coroutines;
//////////////////////////////// ////////////////////////////////
#include "linux_icon.h" #include "linux_icon.h"
@ -326,91 +319,57 @@ Sys_Post_Clipboard_Sig(system_post_clipboard){
// Coroutine // Coroutine
// //
internal Linux_Coroutine*
LinuxAllocCoroutine(){
Linux_Coroutine *result = linuxvars.coroutine_free;
Assert(result != 0);
if (getcontext(&result->ctx) == -1){
perror("getcontext");
}
result->ctx.uc_stack = result->stack;
linuxvars.coroutine_free = result->next;
return(result);
}
internal void
LinuxFreeCoroutine(Linux_Coroutine *data){
data->next = linuxvars.coroutine_free;
linuxvars.coroutine_free = data;
}
internal void
LinuxCoroutineMain(void *arg_){
Linux_Coroutine *c = (Linux_Coroutine*)arg_;
c->coroutine.func(&c->coroutine);
c->done = 1;
LinuxFreeCoroutine(c);
setcontext((ucontext_t*)c->coroutine.yield_handle);
}
internal internal
Sys_Create_Coroutine_Sig(system_create_coroutine){ Sys_Create_Coroutine_Sig(system_create_coroutine){
Linux_Coroutine *c = LinuxAllocCoroutine(); Coroutine *coroutine = coroutine_system_alloc(&coroutines);
c->done = 0; Coroutine_Head *result = 0;
if (coroutine != 0){
makecontext(&c->ctx, (void (*)())LinuxCoroutineMain, 1, &c->coroutine); coroutine_set_function(coroutine, func);
result = &coroutine->head;
*(ucontext_t**)&c->coroutine.plat_handle = &c->ctx; }
c->coroutine.func = func; return(result);
return(&c->coroutine);
} }
internal internal
Sys_Launch_Coroutine_Sig(system_launch_coroutine){ Sys_Launch_Coroutine_Sig(system_launch_coroutine){
Linux_Coroutine *c = (Linux_Coroutine*)coroutine; Coroutine *coroutine = (Coroutine*)head;
ucontext_t* ctx = *(ucontext**)&coroutine->plat_handle; coroutine->head.in = in;
coroutine->head.out = out;
coroutine->yield_handle = &c->yield_ctx; Coroutine *active = coroutine->sys->active;
coroutine->in = in; Assert(active != 0);
coroutine->out = out; coroutine_launch(active, coroutine);
Assert(active == coroutine->sys->active);
swapcontext(&c->yield_ctx, ctx); Coroutine_Head *result = &coroutine->head;
if (coroutine->state == CoroutineState_Dead){
if (c->done){ coroutine_system_free(&coroutines, coroutine);
LinuxFreeCoroutine(c); result = 0;
coroutine = 0;
} }
return(result);
return(coroutine);
} }
internal
Sys_Resume_Coroutine_Sig(system_resume_coroutine){ Sys_Resume_Coroutine_Sig(system_resume_coroutine){
Linux_Coroutine *c = (Linux_Coroutine*)coroutine; Coroutine *coroutine = (Coroutine*)head;
void *fiber; coroutine->head.in = in;
coroutine->head.out = out;
Assert(!c->done); Coroutine *active = coroutine->sys->active;
Assert(active != 0);
coroutine_resume(active, coroutine);
Assert(active == coroutine->sys->active);
coroutine->yield_handle = &c->yield_ctx; Coroutine_Head *result = &coroutine->head;
coroutine->in = in; if (coroutine->state == CoroutineState_Dead){
coroutine->out = out; coroutine_system_free(&coroutines, coroutine);
result = 0;
ucontext *ctx = *(ucontext**)&coroutine->plat_handle;
swapcontext(&c->yield_ctx, ctx);
if (c->done){
LinuxFreeCoroutine(c);
coroutine = 0;
} }
return(result);
return(coroutine);
} }
internal
Sys_Yield_Coroutine_Sig(system_yield_coroutine){ Sys_Yield_Coroutine_Sig(system_yield_coroutine){
swapcontext(*(ucontext_t**)&coroutine->plat_handle, (ucontext*)coroutine->yield_handle); Coroutine *coroutine = (Coroutine*)head;
coroutine_yield(coroutine);
} }
// //
@ -1652,39 +1611,19 @@ main(int argc, char **argv){
// Memory init // Memory init
// //
system_memory_init(); memory_init();
// //
// Read command line // Read command line
// //
char* cwd = get_current_dir_name(); read_command_line(argc, argv);
if (!cwd){
char buf[1024];
snprintf(buf, sizeof(buf), "Call to get_current_dir_name failed: %s", strerror(errno));
system_error_box(buf);
}
String current_directory = make_string_slowly(cwd); //
// Threads
//
Command_Line_Parameters clparams; work_system_init();
clparams.argv = argv;
clparams.argc = argc;
char **files;
i32 *file_count;
i32 output_size;
output_size = app.read_command_line(&sysfunc, &memory_vars, current_directory, &plat_settings, &files, &file_count, clparams);
if (output_size > 0){
LOGF("%.*s", output_size, (char*)memory_vars.target_memory);
}
if (output_size != 0){
system_error_box("Error reading command-line arguments.");
}
sysshared_filter_real_files(files, file_count);
// //
// Coroutines // Coroutines
@ -1692,7 +1631,7 @@ main(int argc, char **argv){
linuxvars.coroutine_free = linuxvars.coroutine_data; linuxvars.coroutine_free = linuxvars.coroutine_data;
for (i32 i = 0; i+1 < ArrayCount(linuxvars.coroutine_data); ++i){ for (i32 i = 0; i+1 < ArrayCount(linuxvars.coroutine_data); ++i){
linuxvars.coroutine_data[i].next = linuxvars.coroutine_data + i + 1; linuxvars.coroutine_data[i].next = &linuxvars.coroutine_data[i + 1];
} }
const size_t stack_size = MB(2); const size_t stack_size = MB(2);
@ -1701,12 +1640,6 @@ main(int argc, char **argv){
linuxvars.coroutine_data[i].stack.ss_sp = system_memory_allocate(stack_size); linuxvars.coroutine_data[i].stack.ss_sp = system_memory_allocate(stack_size);
} }
//
// Threads
//
system_init_threaded_work_system();
// //
// X11 init // X11 init
// //
@ -1715,7 +1648,7 @@ main(int argc, char **argv){
if (!linuxvars.XDisplay){ if (!linuxvars.XDisplay){
// NOTE(inso): probably not worth trying the popup in this case... // NOTE(inso): probably not worth trying the popup in this case...
LOG("Can't open display!\n"); LOG("Can't open display!\n");
return(1); exit(1);
} }
#define LOAD_ATOM(x) linuxvars.atom_##x = XInternAtom(linuxvars.XDisplay, #x, False); #define LOAD_ATOM(x) linuxvars.atom_##x = XInternAtom(linuxvars.XDisplay, #x, False);
@ -1930,7 +1863,7 @@ main(int argc, char **argv){
b32 keep_running = linuxvars.keep_running; b32 keep_running = linuxvars.keep_running;
app.step(&sysfunc, &target, &memory_vars, &linuxvars.input, &result, clparams); app.step(&sysfunc, &target, &memory_vars, &linuxvars.input, &result);
if (result.perform_kill){ if (result.perform_kill){
break; break;

View File

@ -105,12 +105,6 @@ struct Win32_Input_Chunk{
Win32_Input_Chunk_Persistent pers; Win32_Input_Chunk_Persistent pers;
}; };
struct Win32_Coroutine{
Coroutine coroutine;
Win32_Coroutine *next;
i32 done;
};
//////////////////////////////// ////////////////////////////////
#define SLASH '\\' #define SLASH '\\'
@ -121,14 +115,11 @@ global System_Functions sysfunc;
#include "win32_library_wrapper.h" #include "win32_library_wrapper.h"
#include "4ed_standard_libraries.cpp" #include "4ed_standard_libraries.cpp"
#include "4ed_coroutine.cpp"
//////////////////////////////// ////////////////////////////////
struct Win32_Vars{ struct Win32_Vars{
Custom_API custom_api;
Win32_Coroutine coroutine_data[18];
Win32_Coroutine *coroutine_free;
Win32_Input_Chunk input_chunk; Win32_Input_Chunk input_chunk;
b32 lctrl_lalt_is_altgr; b32 lctrl_lalt_is_altgr;
b32 got_useful_event; b32 got_useful_event;
@ -168,6 +159,9 @@ global Plat_Settings plat_settings;
global Libraries libraries; global Libraries libraries;
global App_Functions app; global App_Functions app;
global Custom_API custom_api;
global Coroutine_System_Auto_Alloc coroutines;
//////////////////////////////// ////////////////////////////////
@ -272,94 +266,57 @@ Sys_Send_Exit_Signal_Sig(system_send_exit_signal){
// Coroutines // Coroutines
// //
internal Win32_Coroutine*
Win32AllocCoroutine(){
Win32_Coroutine *result = win32vars.coroutine_free;
Assert(result != 0);
win32vars.coroutine_free = result->next;
return(result);
}
internal void
Win32FreeCoroutine(Win32_Coroutine *data){
data->next = win32vars.coroutine_free;
win32vars.coroutine_free = data;
}
internal void CALL_CONVENTION
Win32CoroutineMain(void *arg_){
Win32_Coroutine *c = (Win32_Coroutine*)arg_;
c->coroutine.func(&c->coroutine);
c->done = 1;
Win32FreeCoroutine(c);
SwitchToFiber(c->coroutine.yield_handle);
}
internal internal
Sys_Create_Coroutine_Sig(system_create_coroutine){ Sys_Create_Coroutine_Sig(system_create_coroutine){
Win32_Coroutine *c; Coroutine *coroutine = coroutine_system_alloc(&coroutines);
Coroutine *coroutine; Coroutine_Head *result = 0;
void *fiber; if (coroutine != 0){
coroutine_set_function(coroutine, func);
c = Win32AllocCoroutine(); result = &coroutine->head;
c->done = 0; }
return(result);
coroutine = &c->coroutine;
fiber = CreateFiber(0, Win32CoroutineMain, coroutine);
coroutine->plat_handle = handle_type(fiber);
coroutine->func = func;
return(coroutine);
} }
internal internal
Sys_Launch_Coroutine_Sig(system_launch_coroutine){ Sys_Launch_Coroutine_Sig(system_launch_coroutine){
Win32_Coroutine *c = (Win32_Coroutine*)coroutine; Coroutine *coroutine = (Coroutine*)head;
void *fiber; coroutine->head.in = in;
coroutine->head.out = out;
fiber = handle_type(coroutine->plat_handle); Coroutine *active = coroutine->sys->active;
coroutine->yield_handle = GetCurrentFiber(); Assert(active != 0);
coroutine->in = in; coroutine_launch(active, coroutine);
coroutine->out = out; Assert(active == coroutine->sys->active);
SwitchToFiber(fiber); Coroutine_Head *result = &coroutine->head;
if (coroutine->state == CoroutineState_Dead){
if (c->done){ coroutine_system_free(&coroutines, coroutine);
DeleteFiber(fiber); result = 0;
Win32FreeCoroutine(c);
coroutine = 0;
} }
return(result);
return(coroutine);
} }
Sys_Resume_Coroutine_Sig(system_resume_coroutine){ Sys_Resume_Coroutine_Sig(system_resume_coroutine){
Win32_Coroutine *c = (Win32_Coroutine*)coroutine; Coroutine *coroutine = (Coroutine*)head;
void *fiber; coroutine->head.in = in;
coroutine->head.out = out;
Assert(c->done == 0); Coroutine *active = coroutine->sys->active;
Assert(active != 0);
coroutine_resume(active, coroutine);
Assert(active == coroutine->sys->active);
coroutine->yield_handle = GetCurrentFiber(); Coroutine_Head *result = &coroutine->head;
coroutine->in = in; if (coroutine->state == CoroutineState_Dead){
coroutine->out = out; coroutine_system_free(&coroutines, coroutine);
result = 0;
fiber = handle_type(coroutine->plat_handle);
SwitchToFiber(fiber);
if (c->done){
DeleteFiber(fiber);
Win32FreeCoroutine(c);
coroutine = 0;
} }
return(result);
return(coroutine);
} }
Sys_Yield_Coroutine_Sig(system_yield_coroutine){ Sys_Yield_Coroutine_Sig(system_yield_coroutine){
SwitchToFiber(coroutine->yield_handle); Coroutine *coroutine = (Coroutine*)head;
coroutine_yield(coroutine);
} }
// //
@ -1062,7 +1019,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
i32 argc = __argc; i32 argc = __argc;
char **argv = __argv; char **argv = __argv;
memset(&linuxvars, 0, sizeof(linuxvars)); memset(&win32vars, 0, sizeof(win32vars));
memset(&target, 0, sizeof(target)); memset(&target, 0, sizeof(target));
memset(&memory_vars, 0, sizeof(memory_vars)); memset(&memory_vars, 0, sizeof(memory_vars));
memset(&plat_settings, 0, sizeof(plat_settings)); memset(&plat_settings, 0, sizeof(plat_settings));
@ -1087,51 +1044,35 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
#endif #endif
// //
// Memory Initialization // Memory init
// //
system_memory_init(); memory_init();
//
// Threads
//
system_init_threaded_work_system();
//
// Coroutines
//
ConvertThreadToFiber(0);
win32vars.coroutine_free = win32vars.coroutine_data;
for (i32 i = 0; i+1 < ArrayCount(win32vars.coroutine_data); ++i){
win32vars.coroutine_data[i].next = &win32vars.coroutine_data[i + 1];
}
// //
// Read Command Line // Read Command Line
// //
LOG("Reading command line\n"); read_command_line(argc, argv);
DWORD required = (GetCurrentDirectory(0, 0)*4) + 1;
u8 *current_directory_mem = (u8*)system_memory_allocate(required);
DWORD written = GetCurrentDirectory_utf8(required, current_directory_mem);
String current_directory = make_string_cap(current_directory_mem, written, required); //
terminate_with_null(&current_directory); // Threads
replace_char(&current_directory, '\\', '/'); //
Command_Line_Parameters clparams; work_system_init();
clparams.argv = argv;
clparams.argc = argc;
char **files = 0; //
i32 *file_count = 0; // Coroutines
//
app.read_command_line(&sysfunc, &memory_vars, current_directory, &plat_settings, &files, &file_count, clparams); {
init_coroutine_system(&coroutines);
sysshared_filter_real_files(files, file_count);
LOG("Loaded system code, read command line.\n"); umem size = COROUTINE_SLOT_SIZE*18;
void *mem = system_memory_allocate(size);
coroutine_system_provide_memory(&coroutines, mem, size);
coroutine_system_force_init(&coroutines, 4);
}
// //
// Window and GL Initialization // Window and GL Initialization
@ -1254,10 +1195,17 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
// Main Loop // Main Loop
// //
LOG("Initializing application variables\n"); char cwd[4096];
app.init(&sysfunc, &target, &memory_vars, win32vars.clipboard_contents, current_directory, win32vars.custom_api); u32 size = sysfunc.get_current_path(cwd, sizeof(cwd));
if (size == 0 || size >= sizeof(cwd)){
system_error_box("Could not get current directory at launch.");
}
String curdir = make_string(cwd, size);
terminate_with_null(&curdir);
replace_char(&curdir, '\\', '/');
system_memory_free(current_directory.str, 0); LOG("Initializing application variables\n");
app.init(&sysfunc, &target, &memory_vars, win32vars.clipboard_contents, curdir, custom_api);
b32 keep_running = true; b32 keep_running = true;
win32vars.first = true; win32vars.first = true;
@ -1450,7 +1398,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
win32vars.send_exit_signal = false; win32vars.send_exit_signal = false;
} }
app.step(&sysfunc, &target, &memory_vars, &input, &result, clparams); app.step(&sysfunc, &target, &memory_vars, &input, &result);
if (result.perform_kill){ if (result.perform_kill){
keep_running = false; keep_running = false;

View File

@ -13,6 +13,12 @@
// 4ed path // 4ed path
// //
internal
Sys_Get_Current_Path_Sig(system_get_current_path){
i32 result = GetCurrentDirectory_utf8(capacity, (u8*)out);
return(result);
}
internal internal
Sys_Get_4ed_Path_Sig(system_get_4ed_path){ Sys_Get_4ed_Path_Sig(system_get_4ed_path){
i32 size = GetModuleFileName_utf8(0, (u8*)out, capacity); i32 size = GetModuleFileName_utf8(0, (u8*)out, capacity);