hot reload works with tick lanes and job worker loops!
This commit is contained in:
@@ -18,6 +18,7 @@ ModuleAPI :: struct {
|
||||
|
||||
startup: type_of( startup ),
|
||||
tick_lane_startup: type_of( tick_lane_startup),
|
||||
job_worker_startup: type_of( job_worker_startup),
|
||||
hot_reload: type_of( hot_reload ),
|
||||
tick_lane: type_of( tick_lane ),
|
||||
clean_frame: type_of( clean_frame),
|
||||
@@ -47,21 +48,46 @@ Threads will eventually return to their tick_lane upon completion.
|
||||
@export
|
||||
hot_reload :: proc(host_mem: ^ProcessMemory, thread_mem: ^ThreadMemory)
|
||||
{
|
||||
profile(#procedure)
|
||||
thread = thread_mem
|
||||
if thread.id == .Master_Prepper {
|
||||
grime_set_profiler_module_context(& memory.spall_context)
|
||||
sync_store(& memory, host_mem, .Release)
|
||||
// Critical reference synchronization
|
||||
{
|
||||
thread = thread_mem
|
||||
if thread.id == .Master_Prepper {
|
||||
sync_store(& memory, host_mem, .Release)
|
||||
grime_set_profiler_module_context(& memory.spall_context)
|
||||
}
|
||||
else {
|
||||
for ; memory == nil; {
|
||||
sync_load(& memory, .Acquire)
|
||||
}
|
||||
for ; thread == nil; {
|
||||
thread = thread_mem
|
||||
}
|
||||
}
|
||||
grime_set_profiler_thread_buffer(& thread.spall_buffer)
|
||||
}
|
||||
profile(#procedure)
|
||||
// Do hot-reload stuff...
|
||||
{
|
||||
|
||||
}
|
||||
// Critical reference synchronization
|
||||
{
|
||||
leader := barrier_wait(& memory.lane_job_sync)
|
||||
if thread.id == .Master_Prepper {
|
||||
sync_store(& memory.client_api_hot_reloaded, false, .Release)
|
||||
}
|
||||
else {
|
||||
for ; memory.client_api_hot_reloaded == true; {
|
||||
sync_load(& memory.client_api_hot_reloaded, .Acquire)
|
||||
}
|
||||
}
|
||||
leader = barrier_wait(& memory.lane_job_sync)
|
||||
}
|
||||
grime_set_profiler_thread_buffer(& thread.spall_buffer)
|
||||
}
|
||||
|
||||
/*
|
||||
Called by host_tick_lane_startup
|
||||
Used for lane specific startup operations
|
||||
|
||||
The lane tick cannot be handled it, its call must be done by the host module.
|
||||
(We need threads to not be within a client callstack in the even of a hot-reload)
|
||||
*/
|
||||
@export
|
||||
tick_lane_startup :: proc(thread_mem: ^ThreadMemory)
|
||||
@@ -73,8 +99,19 @@ tick_lane_startup :: proc(thread_mem: ^ThreadMemory)
|
||||
profile(#procedure)
|
||||
}
|
||||
|
||||
/*
|
||||
@export
|
||||
job_worker_startup :: proc(thread_mem: ^ThreadMemory)
|
||||
{
|
||||
if thread_mem.id != .Master_Prepper {
|
||||
thread = thread_mem
|
||||
grime_set_profiler_thread_buffer(& thread.spall_buffer)
|
||||
}
|
||||
profile(#procedure)
|
||||
}
|
||||
|
||||
/*
|
||||
Host handles the loop.
|
||||
(We need threads to be outside of client callstack in the event of a hot-reload)
|
||||
*/
|
||||
@export
|
||||
tick_lane :: proc(host_delta_time_ms: f64, host_delta_ns: Duration) -> (should_close: b64 = false)
|
||||
|
||||
@@ -17,39 +17,42 @@ ProcessMemory :: struct {
|
||||
// Host
|
||||
host_persist_buf: [32 * Mega]byte,
|
||||
host_scratch_buf: [64 * Mega]byte,
|
||||
host_persist: Odin_Arena,
|
||||
host_scratch: Odin_Arena,
|
||||
host_api: Host_API,
|
||||
host_persist: Odin_Arena, // Host Persistent (Non-Wipeable), for bad third-party static object allocation
|
||||
host_scratch: Odin_Arena, // Host Temporary Wipable
|
||||
host_api: Host_API, // Client -> Host Interface
|
||||
|
||||
// Textual Logging
|
||||
logger: Logger,
|
||||
logger: Logger,
|
||||
path_logger_finalized: string,
|
||||
|
||||
// Profiling
|
||||
spall_context: Spall_Context,
|
||||
// TODO(Ed): Try out Superluminal's API!
|
||||
|
||||
// Multi-threading
|
||||
threads: [MAX_THREADS](^SysThread),
|
||||
job_system: JobSystemContext,
|
||||
tick_lanes: int,
|
||||
lane_sync: sync.Barrier,
|
||||
job_hot_reload_sync: sync.Barrier, // Used to sync jobs with main thread during hot-reload junction.
|
||||
tick_running: b64,
|
||||
threads: [MAX_THREADS](^SysThread), // All threads are tracked here.
|
||||
job_system: JobSystemContext, // State tracking for job system.
|
||||
tick_running: b64, // When disabled will lead to shutdown of the process.
|
||||
tick_lanes: int, // Runtime tracker of live tick lane threads
|
||||
lane_sync: sync.Barrier, // Used to sync tick lanes during wide junctions.
|
||||
job_hot_reload_sync: sync.Barrier, // Used to sync jobs with main thread during hot-reload junction.
|
||||
lane_job_sync: sync.Barrier, // Used to sync tick lanes and job workers during hot-reload.
|
||||
|
||||
// Client Module
|
||||
client_api_hot_reloaded: b64,
|
||||
client_api: ModuleAPI,
|
||||
client_memory: State,
|
||||
client_api_hot_reloaded: b64, // Used to signal to threads when hot-reload paths should be taken.
|
||||
client_api: ModuleAPI, // Host -> Client Interface
|
||||
client_memory: State,
|
||||
}
|
||||
|
||||
Host_API :: struct {
|
||||
request_virtual_memory: #type proc(),
|
||||
request_virtual_mapped_io: #type proc(),
|
||||
request_virtual_memory: #type proc(), // All dynamic allocations will utilize vmem interfaces
|
||||
request_virtual_mapped_io: #type proc(), // TODO(Ed): Figure out usage constraints of this.
|
||||
}
|
||||
|
||||
ThreadMemory :: struct {
|
||||
using _: ThreadWorkerContext,
|
||||
|
||||
// Per-thread profiling
|
||||
spall_buffer_backing: [SPALL_BUFFER_DEFAULT_SIZE * 2]byte,
|
||||
spall_buffer: Spall_Buffer,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user