From b343a1c4aef7318bc0ac03bd47904213d27f8adf Mon Sep 17 00:00:00 2001 From: insofaras Date: Tue, 8 Mar 2016 21:10:33 +0000 Subject: [PATCH 1/2] all this talk of semaphores made me want to use posix semahpores linux side instead of pthread cond variables. I think they match the win32 semantics more closely --- linux_4ed.cpp | 48 +++++++++++++++--------------------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/linux_4ed.cpp b/linux_4ed.cpp index 3d0a9dab..b3a28234 100644 --- a/linux_4ed.cpp +++ b/linux_4ed.cpp @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -78,16 +79,6 @@ #include #endif -struct Linux_Semaphore { - pthread_mutex_t mutex; - pthread_cond_t cond; -}; - -struct Linux_Semaphore_Handle { - pthread_mutex_t *mutex_p; - pthread_cond_t *cond_p; -}; - struct Linux_Coroutine { Coroutine coroutine; Linux_Coroutine *next; @@ -145,7 +136,7 @@ struct Linux_Vars{ Thread_Memory *thread_memory; Thread_Group groups[THREAD_GROUP_COUNT]; - Linux_Semaphore thread_locks[THREAD_GROUP_COUNT]; + sem_t thread_semaphores[THREAD_GROUP_COUNT]; pthread_mutex_t locks[LOCK_COUNT]; Plat_Settings settings; @@ -526,8 +517,6 @@ Sys_Yield_Coroutine_Sig(system_yield_coroutine){ } Sys_CLI_Call_Sig(system_cli_call){ - // TODO(allen): Implement - // fprintf(stderr, "cli call: %s, %s\n", path, script_name); int pipe_fds[2]; @@ -622,12 +611,16 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){ return close_me; } -static_assert(sizeof(Plat_Handle) >= sizeof(Linux_Semaphore_Handle), "Plat_Handle not big enough"); +static_assert(sizeof(Plat_Handle) >= sizeof(sem_t*), "Plat_Handle not big enough"); internal Plat_Handle -LinuxSemToHandle(Linux_Semaphore* sem){ - Linux_Semaphore_Handle h = { &sem->mutex, &sem->cond }; - return *(Plat_Handle*)&h; +LinuxSemToHandle(sem_t* sem){ + return *(Plat_Handle*)&sem; +} + +internal sem_t* +LinuxHandleToSem(Plat_Handle h){ + return *(sem_t**)&h; } internal void* @@ -680,19 +673,13 @@ ThreadProc(void* arg){ } } else{ - Linux_Semaphore_Handle* h = (Linux_Semaphore_Handle*)&(queue->semaphore); - pthread_mutex_lock(h->mutex_p); - pthread_cond_wait(h->cond_p, h->mutex_p); - pthread_mutex_unlock(h->mutex_p); + sem_wait(LinuxHandleToSem(queue->semaphore)); } } } Sys_Post_Job_Sig(system_post_job){ - // TODO(allen): Implement - AllowLocal(group_id); - AllowLocal(job); Work_Queue *queue = exchange_vars.thread.queues + group_id; @@ -716,11 +703,8 @@ Sys_Post_Job_Sig(system_post_job){ } } - Linux_Semaphore_Handle* h = (Linux_Semaphore_Handle*)&(queue->semaphore); - pthread_mutex_lock(h->mutex_p); - pthread_cond_broadcast(h->cond_p); - pthread_mutex_unlock(h->mutex_p); - + sem_post(LinuxHandleToSem(queue->semaphore)); + return result; } @@ -929,7 +913,6 @@ out: internal Sys_Save_File_Sig(system_save_file){ b32 result = 0; - DBG_FN; const size_t save_fsz = strlen(filename); const char tmp_end[] = ".4ed.XXXXXX"; @@ -1858,11 +1841,10 @@ main(int argc, char **argv) Thread_Memory thread_memory[ArrayCount(background)]; linuxvars.thread_memory = thread_memory; - pthread_mutex_init(&linuxvars.thread_locks[BACKGROUND_THREADS].mutex, NULL); - pthread_cond_init(&linuxvars.thread_locks[BACKGROUND_THREADS].cond, NULL); + sem_init(&linuxvars.thread_semaphores[BACKGROUND_THREADS], 0, 0); exchange_vars.thread.queues[BACKGROUND_THREADS].semaphore = - LinuxSemToHandle(&linuxvars.thread_locks[BACKGROUND_THREADS]); + LinuxSemToHandle(&linuxvars.thread_semaphores[BACKGROUND_THREADS]); for(i32 i = 0; i < linuxvars.groups[BACKGROUND_THREADS].count; ++i){ Thread_Context *thread = linuxvars.groups[BACKGROUND_THREADS].threads + i; From 5538468eabb5e8b2b15bee3555c23e2a0363f548 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Tue, 8 Mar 2016 18:06:27 -0500 Subject: [PATCH 2/2] windows unique file hash --- 4coder_custom.cpp | 2 +- 4ed.cpp | 197 +++++++++++++----------------- 4ed_file.cpp | 296 ++++++++++++++++++++++++++++++---------------- 4ed_file_view.cpp | 2 +- 4ed_mem.cpp | 4 + 4ed_system.h | 5 - win32_4ed.cpp | 22 +++- 7 files changed, 298 insertions(+), 230 deletions(-) diff --git a/4coder_custom.cpp b/4coder_custom.cpp index fe3c4c89..dca8651a 100644 --- a/4coder_custom.cpp +++ b/4coder_custom.cpp @@ -1,5 +1,5 @@ // Set which customization you want to use with this define or write your own -#define Custom_Current Custom_HandmadeHero +#define Custom_Current Custom_Default #define Custom_Default 0 diff --git a/4ed.cpp b/4ed.cpp index 9b42d16c..958da58e 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -975,7 +975,7 @@ COMMAND_DECL(reopen){ i32 index = 0; if (file_id){ file_set_to_loading(file); - index = (i32)(file - models->working_set.files); + index = file->id.id; app_push_file_binding(vars, file_id, index); view_set_file(view, file, models, system, @@ -1026,8 +1026,8 @@ COMMAND_DECL(save){ } } else{ - file = models->working_set.files + buffer_id; - + file = working_set_get_active_file(&models->working_set, buffer_id); + if (!file->state.is_dummy && file_is_ready(file)){ delayed_save(delay, name, file); } @@ -1096,7 +1096,7 @@ COMMAND_DECL(kill_buffer){ } if (buffer_id != 0){ - file = working_set_get_file(&models->working_set, buffer_id, 1).file; + file = working_set_get_active_file(&models->working_set, buffer_id); if (file){ delayed_kill(delay, file); } @@ -1730,47 +1730,46 @@ COMMAND_DECL(command_line){ { Working_Set *working_set = &models->working_set; CLI_Process *procs = vars->cli_processes.procs, *proc = 0; - Get_File_Result file = {}; + Editing_File *file = 0; b32 bind_to_new_view = !do_in_background; if (vars->cli_processes.count < vars->cli_processes.max){ if (buffer_id){ - file = working_set_get_file(working_set, buffer_id, 1); + file = working_set_get_active_file(working_set, buffer_id); } else if (buffer_name){ - file.file = working_set_contains(working_set, make_string(buffer_name, buffer_name_len)); - file.index = (i32)(file.file - working_set->files); - if (file.file == 0){ - file = working_set_get_available_file(working_set); - if (file.file == 0){ + file = working_set_contains(working_set, make_string(buffer_name, buffer_name_len)); + if (file == 0){ + file = working_set_alloc_always(working_set, &models->mem.general); + if (file == 0){ // TODO(allen): feedback message - no available file return; } } } - if (file.file){ + if (file){ i32 proc_count = vars->cli_processes.count; View_Iter iter; i32 i; - file_create_read_only(system, models, file.file, buffer_name); - file.file->settings.unimportant = 1; - table_add(&working_set->table, file.file->name.source_path, file.index); + file_create_read_only(system, models, file, buffer_name); + file->settings.unimportant = 1; + table_add(&working_set->table, file->name.source_path, file->id.id); for (i = 0; i < proc_count; ++i){ - if (procs[i].out_file == file.file){ + if (procs[i].out_file == file){ if (flags & CLI_OverlapWithConflict) procs[i].out_file = 0; else - file.file = 0; + file = 0; break; } } - if (file.file){ + if (file){ if (!(flags & CLI_AlwaysBindToView)){ - iter = file_view_iter_init(&models->layout, file.file, 0); + iter = file_view_iter_init(&models->layout, file, 0); if (file_view_iter_good(iter)){ bind_to_new_view = 0; } @@ -1809,11 +1808,11 @@ COMMAND_DECL(command_line){ } if (bind_to_new_view){ - view_file_in_panel(command, panel, file.file); + view_file_in_panel(command, panel, file); } proc = procs + vars->cli_processes.count++; - proc->out_file = file.file; + proc->out_file = file; if (!system->cli_call(path, script, &proc->cli)){ --vars->cli_processes.count; @@ -1844,7 +1843,7 @@ fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *wor buffer->ready = file_is_ready(file); buffer->is_lexed = file->settings.tokens_exist; - buffer->buffer_id = (int)(file - working_set->files); + buffer->buffer_id = file->id.id; buffer->size = file->state.buffer.size; buffer->buffer_cursor_pos = file->state.cursor_pos; @@ -1871,7 +1870,7 @@ fill_view_summary(View_Summary *view, View *vptr, Live_Views *live_set, Working_ if (vptr->file){ lock_level = view_lock_level(vptr); - buffer_id = (int)(vptr->file - working_set->files); + buffer_id = vptr->file->id.id; if (lock_level <= 0){ view->buffer_id = buffer_id; @@ -1981,7 +1980,7 @@ extern "C"{ Working_Set *working_set = &cmd->models->working_set; Editing_File *file; - file = working_set_get_file(working_set, buffer->buffer_id, 1).file; + file = working_set_get_active_file(working_set, buffer->buffer_id); if (file){ file = (Editing_File*)file->node.next; fill_buffer_summary(buffer, file, working_set); @@ -1995,11 +1994,11 @@ extern "C"{ Command_Data *cmd = (Command_Data*)app->cmd_context; Working_Set *working_set = &cmd->models->working_set; Buffer_Summary buffer = {}; - Get_File_Result file; + Editing_File *file; - file = working_set_get_file(working_set, index, 1); - if (file.file){ - fill_buffer_summary(&buffer, file.file, working_set); + file = working_set_get_active_file(working_set, index); + if (file){ + fill_buffer_summary(&buffer, file, working_set); } return(buffer); @@ -2037,12 +2036,11 @@ extern "C"{ Command_Data *cmd = (Command_Data*)app->cmd_context; Buffer_Summary buffer = {}; Editing_File *file; - Working_Set *working_set; - i32 index; + Working_Set *working_set = &cmd->models->working_set; + File_ID id; - working_set = &cmd->models->working_set; - if (table_find(&working_set->table, make_string(filename, len), &index)){ - file = working_set_get_file(working_set, index, 1).file; + if (table_find(&working_set->table, make_string(filename, len), &id)){ + file = working_set_get_active_file(working_set, id); if (file){ fill_buffer_summary(&buffer, file, working_set); } @@ -2060,7 +2058,7 @@ extern "C"{ if (buffer->exists){ working_set = &cmd->models->working_set; - file = working_set_get_file(working_set, buffer->buffer_id, 1).file; + file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ size = buffer_size(&file->state.buffer); result = 1; @@ -2097,7 +2095,7 @@ extern "C"{ if (buffer->exists){ models = cmd->models; working_set = &models->working_set; - file = working_set_get_file(working_set, buffer->buffer_id, 1).file; + file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ size = buffer_size(&file->state.buffer); @@ -2139,7 +2137,7 @@ extern "C"{ if (buffer->exists){ working_set = &cmd->models->working_set; - file = working_set_get_file(working_set, buffer->buffer_id, 1).file; + file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ size = buffer_size(&file->state.buffer); if (0 <= start && start <= end && end <= size){ @@ -2167,7 +2165,7 @@ extern "C"{ if (buffer->exists){ models = cmd->models; working_set = &models->working_set; - file = working_set_get_file(working_set, buffer->buffer_id, 1).file; + file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ size = buffer_size(&file->state.buffer); if (0 <= start && start <= end && end <= size){ @@ -2197,7 +2195,7 @@ extern "C"{ if (buffer->exists){ working_set = &cmd->models->working_set; - file = working_set_get_file(working_set, buffer->buffer_id, 1).file; + file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ result = 1; size = buffer_size(&file->state.buffer); @@ -2365,7 +2363,7 @@ extern "C"{ Command_Data *cmd = (Command_Data*)app->cmd_context; Live_Views *live_set; View *vptr; - Get_File_Result file; + Editing_File *file; Working_Set *working_set; Models *models; int result = 0; @@ -2378,13 +2376,13 @@ extern "C"{ if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; working_set = &models->working_set; - file = working_set_get_file(working_set, buffer_id, 1); + file = working_set_get_active_file(working_set, buffer_id); - if (file.file){ + if (file){ result = 1; - if (file.file != vptr->file){ - view_set_file(vptr, file.file, models, - cmd->system, models->hooks[hook_open_file], &app_links); + if (file != vptr->file){ + view_set_file(vptr, file, models, cmd->system, + models->hooks[hook_open_file], &app_links); } } @@ -3298,22 +3296,23 @@ App_Init_Sig(app_init){ // NOTE(allen): file setup { - models->working_set.file_count = 0; - models->working_set.file_max = 119; - models->working_set.files = push_array( - partition, Editing_File, models->working_set.file_max + 1); - - models->working_set.files[0].state.is_dummy = 1; + Editing_File *files, *null_file; + i16 init_count = 128; dll_init_sentinel(&models->working_set.free_sentinel); dll_init_sentinel(&models->working_set.used_sentinel); - - Editing_File *file = models->working_set.files + 1; - i32 max = models->working_set.file_max; - for (i32 i = 0; i < max; ++i, ++file){ - dll_insert(&models->working_set.free_sentinel, &file->node); - } - + + models->working_set.array_max = 128; + models->working_set.file_arrays = push_array(partition, File_Array, models->working_set.array_max); + + files = push_array(partition, Editing_File, init_count); + working_set_extend_memory(&models->working_set, files, init_count); + + null_file = working_set_index(&models->working_set, 0); + dll_remove(&null_file->node); + null_file->state.is_dummy = 1; + ++models->working_set.file_count; + models->working_set.table.max = models->working_set.file_max * 3 / 2; models->working_set.table.count = 0; models->working_set.table.table = push_array( @@ -3376,38 +3375,6 @@ App_Init_Sig(app_init){ models->buffer_param_indices = push_array(partition, i32, models->buffer_param_max); } -internal App_Open_File_Result -app_open_file_background(App_Vars *vars, Exchange *exchange, Working_Set *working_set, String filename){ - Get_File_Result file; - i32 file_id; - App_Open_File_Result result = {}; - - result.file = working_set_contains(working_set, filename); - if (result.file == 0){ - result.is_new = 1; - file = working_set_get_available_file(working_set); - if (file.file){ - result.file = file.file; - file_id = exchange_request_file(exchange, filename.str, filename.size); - if (file_id){ - file_init_strings(result.file); - file_set_name(working_set, result.file, filename.str); - file_set_to_loading(result.file); - table_add(&working_set->table, result.file->name.source_path, file.index); - - result.sys_id = file_id; - result.file_index = file.index; - } - else{ - working_set_free_file(working_set, file.file); - file.file = 0; - } - } - } - - return(result); -} - App_Step_Sig(app_step){ ProfileStart(OS_syncing); Application_Step_Result app_result = *result; @@ -4064,7 +4031,7 @@ App_Step_Sig(app_step){ Working_Set *working_set = &models->working_set; if (exchange_file_ready(exchange, binding->sys_id, &data, &size, &max)){ - ed_file = working_set_get_file(working_set, binding->app_id, 1).file; + ed_file = working_set_get_active_file(working_set, binding->app_id); Assert(ed_file); filename = exchange_file_filename(exchange, binding->sys_id); @@ -4118,7 +4085,7 @@ App_Step_Sig(app_step){ exchange_clear_file(exchange, binding->sys_id); } - Editing_File *file = working_set_get_file(working_set, binding->app_id, 1).file; + Editing_File *file = working_set_get_active_file(working_set, binding->app_id); if (file){ file_synchronize_times(system, file, file->name.source_path.str); } @@ -4172,7 +4139,6 @@ App_Step_Sig(app_step){ App_Open_File_Result result = {}; { String filename = string; - Get_File_Result file; i32 file_id; filename.str[0] = char_to_lower(filename.str[0]); @@ -4180,22 +4146,22 @@ App_Step_Sig(app_step){ result.file = working_set_contains(working_set, filename); if (result.file == 0){ result.is_new = 1; - file = working_set_get_available_file(working_set); - if (file.file){ - result.file = file.file; + result.file = working_set_alloc_always(working_set, general); + if (result.file){ file_id = exchange_request_file(exchange, filename.str, filename.size); if (file_id){ file_init_strings(result.file); file_set_name(working_set, result.file, filename.str); file_set_to_loading(result.file); - table_add(&working_set->table, result.file->name.source_path, file.index); + table_add(&working_set->table, result.file->name.source_path, result.file->id.id); result.sys_id = file_id; - result.file_index = file.index; + result.file_index = result.file->id.id; } else{ - working_set_free_file(working_set, file.file); - file.file = 0; + working_set_free_file(working_set, result.file); + delayed_action_repush(&models->delay2, act); + break; } } } @@ -4203,15 +4169,11 @@ App_Step_Sig(app_step){ if (result.is_new){ if (result.file){ - if (result.sys_id){ - Sys_App_Binding *binding = app_push_file_binding(vars, result.sys_id, result.file_index); - binding->success = (act->type == DACT_OPEN) ? SysAppCreateView : 0; - binding->fail = 0; - binding->panel = panel; - } - else{ - delayed_action_repush(&models->delay2, act); - } + Assert(result.sys_id); + Sys_App_Binding *binding = app_push_file_binding(vars, result.sys_id, result.file_index); + binding->success = (act->type == DACT_OPEN) ? SysAppCreateView : 0; + binding->fail = 0; + binding->panel = panel; } } else{ @@ -4257,7 +4219,7 @@ App_Step_Sig(app_step){ if (file){ i32 sys_id = file_save_and_set_names(system, exchange, mem, working_set, file, string.str); if (sys_id){ - app_push_file_binding(vars, sys_id, (i32)(file - working_set->files)); + app_push_file_binding(vars, sys_id, file->id.id); } else{ delayed_action_repush(&models->delay2, act); @@ -4284,7 +4246,7 @@ App_Step_Sig(app_step){ if (sys_id){ // TODO(allen): This is fishy! Shouldn't we bind it to a file name instead? This file // might be killed before we get notified that the saving is done! - app_push_file_binding(vars, sys_id, (i32)(file - working_set->files)); + app_push_file_binding(vars, sys_id, file->id.id); } else{ delayed_action_repush(&models->delay2, act); @@ -4294,18 +4256,17 @@ App_Step_Sig(app_step){ case DACT_NEW: { - Get_File_Result file = working_set_get_available_file(working_set); - file_create_empty(system, models, file.file, string.str); - table_add(&working_set->table, file.file->name.source_path, file.index); + Editing_File *file = working_set_alloc_always(working_set, general); + file_create_empty(system, models, file, string.str); + table_add(&working_set->table, file->name.source_path, file->id.id); View *view = panel->view; - view_set_file(view, file.file, models, system, - models->hooks[hook_open_file], &app_links); - view->map = app_get_map(models, file.file->settings.base_map_id); + view_set_file(view, file, models, system, models->hooks[hook_open_file], &app_links); + view->map = app_get_map(models, file->settings.base_map_id); #if BUFFER_EXPERIMENT_SCALPEL <= 0 - if (file.file->settings.tokens_exist) - file_first_lex_parallel(system, general, file.file); + if (file->settings.tokens_exist) + file_first_lex_parallel(system, general, file); #endif }break; diff --git a/4ed_file.cpp b/4ed_file.cpp index bb474a71..76470057 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -106,7 +106,7 @@ struct Editing_File_Settings{ struct Editing_File_State{ b32 is_dummy; b32 is_loading; - + i16 font_id; Buffer_Type buffer; @@ -133,10 +133,9 @@ struct Editing_File_Preload{ struct Editing_File_Name{ char live_name_[256]; - String live_name; - char source_path_[256]; char extension_[16]; + String live_name; String source_path; String extension; }; @@ -145,7 +144,20 @@ struct File_Node{ File_Node *next, *prev; }; +union File_ID{ + i32 id; + i16 part[2]; +}; + +inline File_ID +to_file_id(i32 id){ + File_ID result; + result.id = id; + return(result); +} + struct Editing_File{ + // NOTE(allen): node must be the first member of Editing_File! File_Node node; Editing_File_Settings settings; union{ @@ -153,14 +165,18 @@ struct Editing_File{ Editing_File_Preload preload; }; Editing_File_Name name; + File_ID id; }; struct File_Table_Entry{ String name; u32 hash; - i32 id; + File_ID id; }; +// TODO(allen): +// Remove this File_Table and instead use the table in 4tech_table.cpp +// Instead of hashing by file name use the new Unique_Hash in the system. struct File_Table{ File_Table_Entry *table; i32 count, max; @@ -186,7 +202,7 @@ table_add(File_Table *table, String name, i32 id){ i32 i; entry.name = name; - entry.id = id; + entry.id.id = id; entry.hash = get_file_hash(name); i = entry.hash % table->max; while ((e = table->table[i]).name.str){ @@ -221,7 +237,7 @@ table_find_pos(File_Table *table, String name, i32 *index){ } inline b32 -table_find(File_Table *table, String name, i32 *id){ +table_find(File_Table *table, String name, File_ID *id){ i32 pos; b32 r = table_find_pos(table, name, &pos); if (r) *id = table->table[pos].id; @@ -239,10 +255,17 @@ table_remove(File_Table *table, String name){ return r; } +struct File_Array{ + Editing_File *files; + i32 size; +}; + struct Working_Set{ - Editing_File *files; + File_Array *file_arrays; i32 file_count, file_max; - File_Node free_sentinel; + i16 array_count, array_max; + + File_Node free_sentinel; File_Node used_sentinel; File_Table table; @@ -252,6 +275,167 @@ struct Working_Set{ i32 clipboard_current, clipboard_rolling; }; +internal void +working_set_extend_memory(Working_Set *working_set, Editing_File *new_space, i16 number_of_files){ + File_ID id; + i16 i, high_part; + Editing_File *file_ptr; + File_Node *free_sentinel; + + Assert(working_set->array_count < working_set->array_max); + + high_part = working_set->array_count++; + working_set->file_arrays[high_part].files = new_space; + working_set->file_arrays[high_part].size = number_of_files; + + working_set->file_max += number_of_files; + + id.part[1] = high_part; + + file_ptr = new_space; + free_sentinel = &working_set->free_sentinel; + for (i = 0; i < number_of_files; ++i, ++file_ptr){ + id.part[0] = i; + file_ptr->id = id; + dll_insert(free_sentinel, &file_ptr->node); + } +} + +internal Editing_File* +working_set_alloc(Working_Set *working_set){ + Editing_File *result = 0; + File_Node *node; + File_ID id; + + if (working_set->file_count < working_set->file_max){ + node = working_set->free_sentinel.next; + Assert(node != &working_set->free_sentinel); + result = (Editing_File*)node; + + dll_remove(node); + // NOTE(allen): What I really want to do here is clear everything + // except id, but writing that out will be a pain to maintain. + id = result->id; + *result = {}; + result->id = id; + dll_insert(&working_set->used_sentinel, node); + ++working_set->file_count; + } + + return result; +} + +internal Editing_File* +working_set_alloc_always(Working_Set *working_set, General_Memory *general){ + Editing_File *result = 0; + Editing_File *new_chunk; + i16 new_count = 128; + + if (working_set->file_count == working_set->file_max && + working_set->array_count < working_set->array_max){ + new_chunk = gen_array(general, Editing_File, new_count); + working_set_extend_memory(working_set, new_chunk, new_count); + } + result = working_set_alloc(working_set); + + return(result); +} + +inline void +working_set_free_file(Working_Set *working_set, Editing_File *file){ + file->state.is_dummy = 1; + dll_remove(&file->node); + dll_insert(&working_set->free_sentinel, &file->node); + --working_set->file_count; +} + +inline Editing_File* +working_set_index(Working_Set *working_set, File_ID id){ + Editing_File *result = 0; + File_Array *array; + + if (id.part[1] >= 0 && id.part[1] < working_set->array_count){ + array = working_set->file_arrays + id.part[1]; + if (id.part[0] >= 0 && id.part[0] < array->size){ + result = array->files + id.part[0]; + } + } + + return(result); +} + +inline Editing_File* +working_set_index(Working_Set *working_set, i32 id){ + Editing_File *result; + result = working_set_index(working_set, to_file_id(id)); + return(result); +} + +inline Editing_File* +working_set_get_active_file(Working_Set *working_set, File_ID id){ + Editing_File *result = 0; + + result = working_set_index(working_set, id); + if (result && result->state.is_dummy){ + result = 0; + } + + return(result); +} + +inline Editing_File* +working_set_get_active_file(Working_Set *working_set, i32 id){ + Editing_File *result; + result = working_set_get_active_file(working_set, to_file_id(id)); + return(result); +} + +inline Editing_File* +working_set_contains(Working_Set *working_set, String filename){ + Editing_File *result = 0; + File_ID id; + + replace_char(filename, '\\', '/'); + if (table_find(&working_set->table, filename, &id)){ + result = working_set_index(working_set, id); + } + return (result); +} + +// TODO(allen): Pick better first options. +internal Editing_File* +working_set_lookup_file(Working_Set *working_set, String string){ + Editing_File *file = 0; + + replace_char(string, '\\', '/'); + + { + File_Node *node, *used_nodes; + used_nodes = &working_set->used_sentinel; + for (dll_items(node, used_nodes)){ + file = (Editing_File*)node; + if (string.size == 0 || match(string, file->name.live_name)){ + break; + } + } + if (node == used_nodes) file = 0; + } + + if (!file){ + File_Node *node, *used_nodes; + used_nodes = &working_set->used_sentinel; + for (dll_items(node, used_nodes)){ + file = (Editing_File*)node; + if (string.size == 0 || has_substr(file->name.live_name, string)){ + break; + } + } + if (node == used_nodes) file = 0; + } + + return (file); +} + // Hot Directory struct Hot_Directory{ @@ -423,102 +607,6 @@ file_is_ready(Editing_File *file){ return(result); } -inline Editing_File* -working_set_contains(Working_Set *working, String filename){ - Editing_File *result = 0; - i32 id; - replace_char(filename, '\\', '/'); - if (table_find(&working->table, filename, &id)){ - if (id >= 0 && id <= working->file_max){ - result = working->files + id; - } - } - return (result); -} - -// TODO(allen): Pick better first options. -internal Editing_File* -working_set_lookup_file(Working_Set *working_set, String string){ - Editing_File *file = 0; - - replace_char(string, '\\', '/'); - - { - File_Node *node, *used_nodes; - used_nodes = &working_set->used_sentinel; - for (dll_items(node, used_nodes)){ - file = (Editing_File*)node; - if (string.size == 0 || match(string, file->name.live_name)){ - break; - } - } - if (node == used_nodes) file = 0; - } - - if (!file){ - File_Node *node, *used_nodes; - used_nodes = &working_set->used_sentinel; - for (dll_items(node, used_nodes)){ - file = (Editing_File*)node; - if (string.size == 0 || has_substr(file->name.live_name, string)){ - break; - } - } - if (node == used_nodes) file = 0; - } - - return (file); -} - -struct Get_File_Result{ - Editing_File *file; - i32 index; -}; - -internal Get_File_Result -working_set_get_available_file(Working_Set *working_set){ - Get_File_Result result = {}; - File_Node *node; - - if (working_set->file_count < working_set->file_max){ - node = working_set->free_sentinel.next; - Assert(node != &working_set->free_sentinel); - - result.file = (Editing_File*)node; - result.index = (i32)(result.file - working_set->files); - - ++working_set->file_count; - - dll_remove(node); - *result.file = {}; - dll_insert(&working_set->used_sentinel, node); - } - - return result; -} - -inline void -working_set_free_file(Working_Set *working_set, Editing_File *file){ - file->state.is_dummy = 1; - dll_remove(&file->node); - dll_insert(&working_set->free_sentinel, &file->node); - --working_set->file_count; -} - -inline Get_File_Result -working_set_get_file(Working_Set *working_set, i32 id, b32 require_active){ - Get_File_Result result = {}; - if (id > 0 && id <= working_set->file_max){ - result.file = working_set->files + id; - result.index = id; - if (result.file->state.is_dummy && require_active){ - result.file = 0; - result.index = 0; - } - } - return(result); -} - inline void file_set_to_loading(Editing_File *file){ file->state = {}; diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index cb1ba823..f342f3bc 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -1297,7 +1297,7 @@ view_set_file( // Just accept it and pass the file to the open hook when it is loaded. if (file){ if (open_hook && file->settings.is_initialized == 0){ - models->buffer_param_indices[models->buffer_param_count++] = (i32)(file - models->working_set.files); + models->buffer_param_indices[models->buffer_param_count++] = file->id.id; open_hook(app); models->buffer_param_count = 0; file->settings.is_initialized = 1; diff --git a/4ed_mem.cpp b/4ed_mem.cpp index 84120e7d..57e4ccd8 100644 --- a/4ed_mem.cpp +++ b/4ed_mem.cpp @@ -252,5 +252,9 @@ end_temp_memory(Temp_Memory temp){ #define reset_temp_memory end_temp_memory +#define gen_struct(g, T) (T*)general_memory_allocate(g, sizeof(T), 0) +#define gen_array(g, T, size) (T*)general_memory_allocate(g, sizeof(T)*(size), 0) +#define gen_block(g, size) general_memory_open(g, size, 0) + // BOTTOM diff --git a/4ed_system.h b/4ed_system.h index ae6775a6..76e1c760 100644 --- a/4ed_system.h +++ b/4ed_system.h @@ -24,11 +24,6 @@ typedef Sys_File_Time_Stamp_Sig(System_File_Time_Stamp); #define Sys_Set_File_List_Sig(name) void name(File_List *file_list, String directory) typedef Sys_Set_File_List_Sig(System_Set_File_List); -#if 0 -#define Sys_File_Paths_Equal_Sig(name) b32 name(char *path_a, char *path_b) -typedef Sys_File_Paths_Equal_Sig(System_File_Paths_Equal); -#endif - #define Sys_File_Unique_Hash_Sig(name) Unique_Hash name(char *filename) typedef Sys_File_Unique_Hash_Sig(System_File_Unique_Hash); diff --git a/win32_4ed.cpp b/win32_4ed.cpp index ab0a6537..9b53a733 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -461,6 +461,25 @@ Sys_Set_File_List_Sig(system_set_file_list){ } } +internal +Sys_File_Unique_Hash_Sig(system_file_unique_hash){ + Unique_Hash hash; + BY_HANDLE_FILE_INFORMATION info; + HANDLE handle; + + handle = CreateFile(filename, GENERIC_READ, 0, 0, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + + hash = {0}; + if (GetFileInformationByHandle(handle, &info)){ + hash.d[2] = info.dwVolumeSerialNumber; + hash.d[1] = info.nFileIndexHigh; + hash.d[0] = info.nFileIndexLow; + } + + return(hash); +} + internal FILE_EXISTS_SIG(system_file_exists){ char full_filename_space[1024]; @@ -1052,6 +1071,7 @@ Win32LoadAppCode(){ internal void Win32LoadSystemCode(){ win32vars.system->file_time_stamp = system_file_time_stamp; + win32vars.system->file_unique_hash = system_file_unique_hash; win32vars.system->set_file_list = system_set_file_list; win32vars.system->file_exists = system_file_exists; @@ -1933,7 +1953,7 @@ main(int argc, char **argv){ } - File_Slot file_slots[32]; + File_Slot file_slots[4]; sysshared_init_file_exchange(&exchange_vars, file_slots, ArrayCount(file_slots), 0); Font_Load_Parameters params[32];