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

10
4ed.h
View File

@ -46,11 +46,6 @@ struct Input_Summary{
f32 dt;
};
struct Command_Line_Parameters{
char **argv;
int32_t argc;
};
typedef u8 Log_To_Type;
enum{
LogTo_Nothing,
@ -77,7 +72,7 @@ struct Plat_Settings{
};
#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);
@ -123,8 +118,7 @@ name(System_Functions *system, \
Render_Target *target, \
Application_Memory *memory, \
Application_Step_Input *input, \
Application_Step_Result *app_result_, \
Command_Line_Parameters params)
Application_Step_Result *app_result_)
typedef App_Step_Sig(App_Step);

View File

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

View File

@ -57,7 +57,7 @@ struct Models{
Command_Binding prev_command;
Coroutine *command_coroutine;
Coroutine_Head *command_coroutine;
u32 command_coroutine_flags[2];
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);
// 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;
struct Coroutine_Head{
void *in;
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);
#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);
#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);
#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);
// thread

View File

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

View File

@ -1,8 +1,11 @@
/*
4tech_file_moving.h - Code for moving files around on the file system.
By Allen Webster
21.01.2017 (dd.mm.yyyy)
*/
* Mr. 4th Dimention - Allen Webster
*
* 21.01.2017
*
* Moving files around on the file system.
*
*/
// TOP
@ -302,9 +305,9 @@ extern "C"{
#define FILE_ATTRIBUTE_NORMAL 0x00000080
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
static u64 perf_frequency;
global u64 perf_frequency;
static void
internal void
fm_init_system(){
LARGE_INTEGER lint;
if (QueryPerformanceFrequency(&lint)){
@ -313,7 +316,7 @@ fm_init_system(){
fm__init_memory();
}
static Temp_Dir
internal Temp_Dir
fm_pushdir(char *dir){
Temp_Dir temp = {0};
GetCurrentDirectoryA(sizeof(temp.dir), temp.dir);
@ -321,12 +324,12 @@ fm_pushdir(char *dir){
return(temp);
}
static void
internal void
fm_popdir(Temp_Dir temp){
SetCurrentDirectoryA(temp.dir);
}
static u64
internal u64
fm_get_time(){
u64 time = 0;
LARGE_INTEGER lint;
@ -337,13 +340,13 @@ fm_get_time(){
return(time);
}
static i32
internal i32
fm_get_current_directory(char *buffer, i32 max){
i32 result = GetCurrentDirectoryA(max, buffer);
return(result);
}
static void
internal void
fm_execute_in_dir(char *dir, char *str, char *args){
if (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){
if (path != 0){
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){
char *path = fm_str(dir);
char *p = path;
@ -388,23 +391,23 @@ fm_make_folder_if_missing(char *dir){
CreateDirectoryA(path, 0);
}
static void
internal void
fm_clear_folder(char *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);
}
static void
internal void
fm_delete_file(char *file){
systemf("del %s", file);
}
static void
internal void
fm_copy_file(char *file, char *newname){
CopyFileA(file, newname, 0);
}
static void
internal void
fm_copy_all(char *source, char *tag, char *folder){
if (source){
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){
char cdir[512];
fm_get_current_directory(cdir, sizeof(cdir));
@ -454,7 +457,7 @@ fm_zip(char *parent, char *folder, char *dest){
#include <time.h>
#include <unistd.h>
static Temp_Dir
internal Temp_Dir
fm_pushdir(char *dir){
Temp_Dir temp;
char *result = getcwd(temp.dir, sizeof(temp.dir));
@ -467,17 +470,17 @@ fm_pushdir(char *dir){
return(temp);
}
static void
internal void
fm_popdir(Temp_Dir temp){
chdir(temp.dir);
}
static void
internal void
fm_init_system(){
fm__init_memory();
}
static u64
internal u64
fm_get_time(){
struct timespec spec;
u64 result;
@ -486,7 +489,7 @@ fm_get_time(){
return(result);
}
static i32
internal i32
fm_get_current_directory(char *buffer, i32 max){
i32 result = 0;
char *d = getcwd(buffer, max);
@ -496,7 +499,7 @@ fm_get_current_directory(char *buffer, i32 max){
return(result);
}
static void
internal void
fm_execute_in_dir(char *dir, char *str, char *args){
if (dir){
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){}
static void
internal void
fm_make_folder_if_missing(char *dir){
systemf("mkdir -p %s", dir);
}
static void
internal void
fm_clear_folder(char *folder){
fprintf(stdout, "clearing folder %s\n", folder);
systemf("rm -rf %s* > /dev/null", folder);
}
static void
internal void
fm_delete_file(char *file){
systemf("rm %s", file);
}
static void
internal void
fm_copy_file(char *file, char *newname){
systemf("cp %s %s", file, newname);
}
static void
internal void
fm_copy_all(char *source, char *tag, char *folder){
if (source){
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){
Temp_Dir temp = fm_pushdir(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
internal void
system_memory_init(){
memory_init(){
#if defined(FRED_INTERNAL)
# if defined(FTECH_64_BIT)
void *bases[] = { (void*)TB(1), (void*)TB(2), };
@ -120,5 +120,25 @@ load_custom_code(){
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

View File

@ -85,7 +85,8 @@ system_load_library(Library *library, char *name, Load_Library_Location location
internal b32
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

View File

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

View File

@ -105,14 +105,6 @@ enum {
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
//
@ -129,6 +121,8 @@ global System_Functions sysfunc;
#include "linux_library_wrapper.h"
#include "4ed_standard_libraries.cpp"
#include "4ed_coroutine.cpp"
////////////////////////////////
struct Linux_Vars{
@ -183,9 +177,6 @@ struct Linux_Vars{
i32 dpi_x, dpi_y;
b32 vsync;
Linux_Coroutine coroutine_data[18];
Linux_Coroutine *coroutine_free;
};
////////////////////////////////
@ -199,6 +190,8 @@ global Libraries libraries;
global App_Functions app;
global Custom_API custom_api;
global Coroutine_System_Auto_Alloc coroutines;
////////////////////////////////
#include "linux_icon.h"
@ -326,91 +319,57 @@ Sys_Post_Clipboard_Sig(system_post_clipboard){
// 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
Sys_Create_Coroutine_Sig(system_create_coroutine){
Linux_Coroutine *c = LinuxAllocCoroutine();
c->done = 0;
makecontext(&c->ctx, (void (*)())LinuxCoroutineMain, 1, &c->coroutine);
*(ucontext_t**)&c->coroutine.plat_handle = &c->ctx;
c->coroutine.func = func;
return(&c->coroutine);
Coroutine *coroutine = coroutine_system_alloc(&coroutines);
Coroutine_Head *result = 0;
if (coroutine != 0){
coroutine_set_function(coroutine, func);
result = &coroutine->head;
}
return(result);
}
internal
Sys_Launch_Coroutine_Sig(system_launch_coroutine){
Linux_Coroutine *c = (Linux_Coroutine*)coroutine;
ucontext_t* ctx = *(ucontext**)&coroutine->plat_handle;
Coroutine *coroutine = (Coroutine*)head;
coroutine->head.in = in;
coroutine->head.out = out;
coroutine->yield_handle = &c->yield_ctx;
coroutine->in = in;
coroutine->out = out;
Coroutine *active = coroutine->sys->active;
Assert(active != 0);
coroutine_launch(active, coroutine);
Assert(active == coroutine->sys->active);
swapcontext(&c->yield_ctx, ctx);
if (c->done){
LinuxFreeCoroutine(c);
coroutine = 0;
Coroutine_Head *result = &coroutine->head;
if (coroutine->state == CoroutineState_Dead){
coroutine_system_free(&coroutines, coroutine);
result = 0;
}
return(coroutine);
return(result);
}
internal
Sys_Resume_Coroutine_Sig(system_resume_coroutine){
Linux_Coroutine *c = (Linux_Coroutine*)coroutine;
void *fiber;
Coroutine *coroutine = (Coroutine*)head;
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->in = in;
coroutine->out = out;
ucontext *ctx = *(ucontext**)&coroutine->plat_handle;
swapcontext(&c->yield_ctx, ctx);
if (c->done){
LinuxFreeCoroutine(c);
coroutine = 0;
Coroutine_Head *result = &coroutine->head;
if (coroutine->state == CoroutineState_Dead){
coroutine_system_free(&coroutines, coroutine);
result = 0;
}
return(coroutine);
return(result);
}
internal
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
//
system_memory_init();
memory_init();
//
// Read command line
//
char* cwd = get_current_dir_name();
if (!cwd){
char buf[1024];
snprintf(buf, sizeof(buf), "Call to get_current_dir_name failed: %s", strerror(errno));
system_error_box(buf);
}
read_command_line(argc, argv);
String current_directory = make_string_slowly(cwd);
//
// Threads
//
Command_Line_Parameters clparams;
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);
work_system_init();
//
// Coroutines
@ -1692,7 +1631,7 @@ main(int argc, char **argv){
linuxvars.coroutine_free = linuxvars.coroutine_data;
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);
@ -1701,12 +1640,6 @@ main(int argc, char **argv){
linuxvars.coroutine_data[i].stack.ss_sp = system_memory_allocate(stack_size);
}
//
// Threads
//
system_init_threaded_work_system();
//
// X11 init
//
@ -1715,7 +1648,7 @@ main(int argc, char **argv){
if (!linuxvars.XDisplay){
// NOTE(inso): probably not worth trying the popup in this case...
LOG("Can't open display!\n");
return(1);
exit(1);
}
#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;
app.step(&sysfunc, &target, &memory_vars, &linuxvars.input, &result, clparams);
app.step(&sysfunc, &target, &memory_vars, &linuxvars.input, &result);
if (result.perform_kill){
break;

View File

@ -105,12 +105,6 @@ struct Win32_Input_Chunk{
Win32_Input_Chunk_Persistent pers;
};
struct Win32_Coroutine{
Coroutine coroutine;
Win32_Coroutine *next;
i32 done;
};
////////////////////////////////
#define SLASH '\\'
@ -121,14 +115,11 @@ global System_Functions sysfunc;
#include "win32_library_wrapper.h"
#include "4ed_standard_libraries.cpp"
#include "4ed_coroutine.cpp"
////////////////////////////////
struct Win32_Vars{
Custom_API custom_api;
Win32_Coroutine coroutine_data[18];
Win32_Coroutine *coroutine_free;
Win32_Input_Chunk input_chunk;
b32 lctrl_lalt_is_altgr;
b32 got_useful_event;
@ -168,6 +159,9 @@ global Plat_Settings plat_settings;
global Libraries libraries;
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
//
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
Sys_Create_Coroutine_Sig(system_create_coroutine){
Win32_Coroutine *c;
Coroutine *coroutine;
void *fiber;
c = Win32AllocCoroutine();
c->done = 0;
coroutine = &c->coroutine;
fiber = CreateFiber(0, Win32CoroutineMain, coroutine);
coroutine->plat_handle = handle_type(fiber);
coroutine->func = func;
return(coroutine);
Coroutine *coroutine = coroutine_system_alloc(&coroutines);
Coroutine_Head *result = 0;
if (coroutine != 0){
coroutine_set_function(coroutine, func);
result = &coroutine->head;
}
return(result);
}
internal
Sys_Launch_Coroutine_Sig(system_launch_coroutine){
Win32_Coroutine *c = (Win32_Coroutine*)coroutine;
void *fiber;
Coroutine *coroutine = (Coroutine*)head;
coroutine->head.in = in;
coroutine->head.out = out;
fiber = handle_type(coroutine->plat_handle);
coroutine->yield_handle = GetCurrentFiber();
coroutine->in = in;
coroutine->out = out;
Coroutine *active = coroutine->sys->active;
Assert(active != 0);
coroutine_launch(active, coroutine);
Assert(active == coroutine->sys->active);
SwitchToFiber(fiber);
if (c->done){
DeleteFiber(fiber);
Win32FreeCoroutine(c);
coroutine = 0;
Coroutine_Head *result = &coroutine->head;
if (coroutine->state == CoroutineState_Dead){
coroutine_system_free(&coroutines, coroutine);
result = 0;
}
return(coroutine);
return(result);
}
Sys_Resume_Coroutine_Sig(system_resume_coroutine){
Win32_Coroutine *c = (Win32_Coroutine*)coroutine;
void *fiber;
Coroutine *coroutine = (Coroutine*)head;
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->in = in;
coroutine->out = out;
fiber = handle_type(coroutine->plat_handle);
SwitchToFiber(fiber);
if (c->done){
DeleteFiber(fiber);
Win32FreeCoroutine(c);
coroutine = 0;
Coroutine_Head *result = &coroutine->head;
if (coroutine->state == CoroutineState_Dead){
coroutine_system_free(&coroutines, coroutine);
result = 0;
}
return(coroutine);
return(result);
}
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;
char **argv = __argv;
memset(&linuxvars, 0, sizeof(linuxvars));
memset(&win32vars, 0, sizeof(win32vars));
memset(&target, 0, sizeof(target));
memset(&memory_vars, 0, sizeof(memory_vars));
memset(&plat_settings, 0, sizeof(plat_settings));
@ -1087,51 +1044,35 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
#endif
//
// Memory Initialization
// Memory init
//
system_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];
}
memory_init();
//
// Read Command Line
//
LOG("Reading command line\n");
DWORD required = (GetCurrentDirectory(0, 0)*4) + 1;
u8 *current_directory_mem = (u8*)system_memory_allocate(required);
DWORD written = GetCurrentDirectory_utf8(required, current_directory_mem);
read_command_line(argc, argv);
String current_directory = make_string_cap(current_directory_mem, written, required);
terminate_with_null(&current_directory);
replace_char(&current_directory, '\\', '/');
//
// Threads
//
Command_Line_Parameters clparams;
clparams.argv = argv;
clparams.argc = argc;
work_system_init();
char **files = 0;
i32 *file_count = 0;
//
// Coroutines
//
app.read_command_line(&sysfunc, &memory_vars, current_directory, &plat_settings, &files, &file_count, clparams);
sysshared_filter_real_files(files, file_count);
LOG("Loaded system code, read command line.\n");
{
init_coroutine_system(&coroutines);
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
@ -1254,10 +1195,17 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
// Main Loop
//
LOG("Initializing application variables\n");
app.init(&sysfunc, &target, &memory_vars, win32vars.clipboard_contents, current_directory, win32vars.custom_api);
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(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;
win32vars.first = true;
@ -1450,7 +1398,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
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){
keep_running = false;

View File

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