From b049a56a28128779ed8922fd16a0d9786116380a Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 19 Feb 2025 08:51:20 -0600 Subject: [PATCH] faster app shutdown --- src/app.c | 15 +++++++++++---- src/sim.c | 13 ------------- src/sim_snapshot.c | 37 ++++++++++++++++++++++++++++++++----- src/sim_snapshot.h | 39 ++++----------------------------------- src/sys_win32.c | 15 ++++++++++++--- src/user.c | 41 +++++++++++++---------------------------- 6 files changed, 72 insertions(+), 88 deletions(-) diff --git a/src/app.c b/src/app.c index 7b86c5a7..8a98bea6 100644 --- a/src/app.c +++ b/src/app.c @@ -257,13 +257,19 @@ void app_entry_point(struct string args_str) struct sys_lock lock = sys_mutex_lock_e(&G.exit_callbacks_mutex); /* Start callback threads */ - for (struct exit_callback *callback = G.exit_callbacks_head; callback; callback = callback->next) { - callback->thread = sys_thread_alloc(&exit_callback_thread_entry_point, callback, LIT("[P1] Exit callback thread")); + { + __profscope(app_start_exit_callbacks); + for (struct exit_callback *callback = G.exit_callbacks_head; callback; callback = callback->next) { + callback->thread = sys_thread_alloc(&exit_callback_thread_entry_point, callback, LIT("[P1] Exit callback thread")); + } } /* Wait on callback threads */ - for (struct exit_callback *callback = G.exit_callbacks_head; callback; callback = callback->next) { - sys_thread_wait_release(&callback->thread); + { + __profscope(app_wait_on_exit_callbacks); + for (struct exit_callback *callback = G.exit_callbacks_head; callback; callback = callback->next) { + sys_thread_wait_release(&callback->thread); + } } sys_mutex_unlock(&lock); @@ -271,6 +277,7 @@ void app_entry_point(struct string args_str) /* Write window settings to file */ { + __profscope(app_write_to_settings_file); struct temp_arena temp = arena_temp_begin(scratch.arena); struct string window_settings_path = app_write_path_cat(temp.arena, LIT(SETTINGS_FILENAME)); diff --git a/src/sim.c b/src/sim.c index 463a5138..2fb0411d 100644 --- a/src/sim.c +++ b/src/sim.c @@ -448,19 +448,6 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct struct sim_snapshot *world = sim_snapshot_alloc(snapshot_store, prev_snapshot, prev_snapshot->tick + 1); -#if 0 - /* Release old snapshots */ - { - /* TODO: Something better */ - i64 release_tick = (i64)ss_blended->tick - 25; /* Arbitrary tick offset */ - if (release_tick > 0) { - struct sim_snapshot *old = sim_snapshot_from_tick(snapshot_store, release_tick); - if (old->valid) { - sim_snapshot_release(old); - } - } - } -#endif diff --git a/src/sim_snapshot.c b/src/sim_snapshot.c index 9064ecb7..09925d43 100644 --- a/src/sim_snapshot.c +++ b/src/sim_snapshot.c @@ -80,6 +80,7 @@ struct sim_snapshot_startup_receipt sim_snapshot_startup(void) struct sim_snapshot_store *sim_snapshot_store_alloc(void) { + __prof; struct sim_snapshot_store *store; { struct arena arena = arena_alloc(GIGABYTE(64)); @@ -94,6 +95,7 @@ struct sim_snapshot_store *sim_snapshot_store_alloc(void) void sim_snapshot_store_release(struct sim_snapshot_store *store) { + __prof; /* Release snapshot internal memory */ for (u64 i = 0; i < store->num_lookup_buckets; ++i) { struct sim_snapshot_lookup_bucket *bucket = &store->lookup_buckets[i]; @@ -120,6 +122,30 @@ void sim_snapshot_store_release(struct sim_snapshot_store *store) arena_release(&store->arena); } +/* Releases all snapshots with tick in range [start, end] */ +void sim_snapshot_store_release_ticks_in_range(struct sim_snapshot_store *store, u64 start, u64 end) +{ + if (start > end) { + u64 swp = start; + start = end; + end = swp; + } + + struct sim_snapshot *ss = sim_snapshot_from_tick(store, store->first_tick); + while (ss->valid) { + u64 tick = ss->tick; + u64 next_tick = ss->next_tick; + if (tick >= start) { + if (tick <= end) { + sim_snapshot_release(ss); + } else { + break; + } + } + ss = sim_snapshot_from_tick(store, next_tick); + } +} + /* ========================== * * Alloc * ========================== */ @@ -276,8 +302,6 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_snapshot_store *store, struct return ss; } -/* NOTE: Only releases snapshot into store's free list. - * Use `sim_snapshot_release_internal` to release allocated snapshot memory back to system */ void sim_snapshot_release(struct sim_snapshot *ss) { struct sim_snapshot_store *store = ss->store; @@ -415,7 +439,6 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_snapshot_store *sto void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_snapshot *ss0, struct sim_snapshot *ss1, struct sim_client *client) { __prof; - bw_write_uv(bw, ss1->continuity_gen); bw_write_iv(bw, ss1->real_dt_ns); bw_write_iv(bw, ss1->real_time_ns); @@ -424,6 +447,9 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_snapshot *ss0, st bw_write_iv(bw, ss1->world_dt_ns); bw_write_iv(bw, ss1->world_time_ns); + bw_write_uv(bw, ss1->continuity_gen); + bw_write_uv(bw, ss1->phys_iteration); + bw_write_uv(bw, client->handle.gen); bw_write_uv(bw, client->handle.idx); @@ -480,8 +506,6 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss) { __prof; - ss->continuity_gen = br_read_uv(br); - ss->real_dt_ns = br_read_iv(br); ss->real_time_ns = br_read_iv(br); @@ -489,6 +513,9 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss) ss->world_dt_ns = br_read_iv(br); ss->world_time_ns = br_read_iv(br); + ss->continuity_gen = br_read_uv(br); + ss->phys_iteration = br_read_uv(br); + ss->local_client.gen = br_read_uv(br); ss->local_client.idx = br_read_uv(br); diff --git a/src/sim_snapshot.h b/src/sim_snapshot.h index a6d888c8..4390cd4f 100644 --- a/src/sim_snapshot.h +++ b/src/sim_snapshot.h @@ -42,41 +42,6 @@ struct sim_snapshot { struct arena arena; - - - - - - - - - - - - - - - - - /* FIXME: Encode / decode */ - - u64 phys_iteration; - - - - - - - - - - - - - - - - /* Real time (increases with clock assuming no lag) */ i64 real_dt_ns; i64 real_time_ns; @@ -92,6 +57,9 @@ struct sim_snapshot { /* If != previous tick's continuity then don't lerp */ u64 continuity_gen; + /* The last physics iteration (used for tracking contact lifetime) */ + u64 phys_iteration; + /* Which client in the client store represents the local host in the original snapshot */ struct sim_client_handle local_client; @@ -127,6 +95,7 @@ struct sim_snapshot_startup_receipt sim_snapshot_startup(void); struct sim_snapshot_store *sim_snapshot_store_alloc(void); void sim_snapshot_store_release(struct sim_snapshot_store *store); +void sim_snapshot_store_release_ticks_in_range(struct sim_snapshot_store *store, u64 start, u64 end); /* ========================== * * Nil diff --git a/src/sys_win32.c b/src/sys_win32.c index f822f853..a0386ec8 100644 --- a/src/sys_win32.c +++ b/src/sys_win32.c @@ -82,7 +82,7 @@ struct win32_window { struct v2 cursor_set_position; struct rect cursor_clip_bounds; - b32 event_thread_shutdown; + struct atomic_i32 event_thread_shutdown; struct sys_thread event_thread; struct sys_mutex event_callbacks_mutex; @@ -667,6 +667,7 @@ void sys_file_filter_end(struct sys_file_filter *filter) * ========================== */ INTERNAL void win32_update_window_from_system(struct win32_window *window); +INTERNAL void win32_window_wake(struct win32_window *window); INTERNAL void win32_window_process_event(struct win32_window *window, struct sys_event event) { @@ -727,10 +728,14 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(window_thread_entry_point, arg) sync_flag_set(&window->ready_sf); - while (!window->event_thread_shutdown) { + while (!atomic_i32_eval(&window->event_thread_shutdown)) { MSG msg = ZI; GetMessageW(&msg, 0, 0, 0); + if (atomic_i32_eval(&window->event_thread_shutdown)) { + break; + } + /* Update cursor */ if (GetFocus() == window->hwnd) { u32 cursor_flags = window->cursor_set_flags; @@ -833,7 +838,8 @@ INTERNAL void win32_window_release(struct win32_window *window) G.first_free_window = window; /* Stop window thread */ - window->event_thread_shutdown = true; + atomic_i32_eval_exchange(&window->event_thread_shutdown, 1); + win32_window_wake(window); sys_thread_wait_release(&window->event_thread); /* Release mutexes */ @@ -1207,6 +1213,7 @@ struct sys_window sys_window_alloc(void) void sys_window_release(struct sys_window *sys_window) { + __prof; struct win32_window *window = (struct win32_window *)sys_window->handle; win32_window_release(window); } @@ -1705,6 +1712,7 @@ INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt) struct sys_thread sys_thread_alloc(sys_thread_entry_point_func *entry_point, void *thread_data, struct string thread_name) { + __prof; ASSERT(entry_point != NULL); logf_info("Creating thread \"%F\"", FMT_STR(thread_name)); @@ -1737,6 +1745,7 @@ struct sys_thread sys_thread_alloc(sys_thread_entry_point_func *entry_point, voi void sys_thread_wait_release(struct sys_thread *thread) { + __prof; struct win32_thread *t = (struct win32_thread *)thread->handle; HANDLE handle = t->handle; diff --git a/src/user.c b/src/user.c index 44a11db4..3257e768 100644 --- a/src/user.c +++ b/src/user.c @@ -255,6 +255,9 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr, INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(user_shutdown) { __prof; + + sys_window_unregister_event_callback(G.window, &window_event_callback); + atomic_i32_eval_exchange(&G.user_thread_shutdown, true); sys_thread_wait_release(&G.user_thread); @@ -585,7 +588,7 @@ INTERNAL void user_update(void) G.ss_blended = sim_snapshot_alloc(G.blended_snapshot_store, right_snapshot, right_snapshot->tick); } - /* Release all other render snapshots */ + /* Release all other blended snapshots */ { struct sim_snapshot *ss = sim_snapshot_from_tick(G.blended_snapshot_store, G.blended_snapshot_store->first_tick); while (ss->valid) { @@ -1473,19 +1476,20 @@ INTERNAL void user_update(void) if (!G.debug_camera) { control.move = input_move_dir; control.focus = input_aim_dir; + + struct bind_state fire_state = G.bind_states[USER_BIND_KIND_FIRE]; + if (fire_state.num_presses || fire_state.is_held) { + control.flags |= SIM_CONTROL_FLAG_FIRING; + } } - struct bind_state fire_state = G.bind_states[USER_BIND_KIND_FIRE]; struct bind_state drag_state = G.bind_states[USER_BIND_KIND_DEBUG_DRAG]; struct bind_state clear_state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR]; struct bind_state pause_state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE]; struct bind_state step_state = G.bind_states[USER_BIND_KIND_DEBUG_STEP]; struct bind_state spawn_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN]; - if ((fire_state.num_presses - fire_state.num_releases > 0) || fire_state.is_held) { - control.flags |= SIM_CONTROL_FLAG_FIRING; - } - if ((drag_state.num_presses - drag_state.num_releases > 0) || drag_state.is_held) { + if (drag_state.num_presses || drag_state.is_held) { control.flags |= SIM_CONTROL_FLAG_DRAGGING; } if (clear_state.num_presses) { @@ -1826,16 +1830,8 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) { u64 keep_count = 50; u64 keep_tick = prev_ss->tick > keep_count ? prev_ss->tick - keep_count : 0; - - struct sim_snapshot *remss = sim_snapshot_from_tick(snapshot_store, snapshot_store->first_tick); - while (remss->valid) { - u64 next_tick = remss->next_tick; - if (remss->tick < keep_tick) { - sim_snapshot_release(remss); - } else { - break; - } - remss = sim_snapshot_from_tick(snapshot_store, next_tick); + if (keep_tick > 0) { + sim_snapshot_store_release_ticks_in_range(snapshot_store, 0, keep_tick); } } @@ -1885,18 +1881,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) { struct sys_lock lock = sys_mutex_lock_e(&G.local_sim_ss_mutex); sim_snapshot_alloc(G.local_sim_ss_store, ss, ss->tick); - - struct sim_snapshot *remss = sim_snapshot_from_tick(G.local_sim_ss_store, G.local_sim_ss_store->first_tick); - while (remss) { - u64 next_tick = remss->next_tick; - if (remss->tick < ss->tick) { - sim_snapshot_release(remss); - } else { - break; - } - remss = sim_snapshot_from_tick(G.local_sim_ss_store, next_tick); - } - + sim_snapshot_store_release_ticks_in_range(G.local_sim_ss_store, 0, ss->tick - 1); sys_mutex_unlock(&lock); }