dramatic cleanup of threading code

This commit is contained in:
Allen Webster 2017-07-18 13:44:54 -04:00
parent bfc6fc689d
commit 7737ee8bc1
6 changed files with 199 additions and 265 deletions

View File

@ -11,7 +11,7 @@
// TODO(allen): Should auto-gen this!
#define SYSLINK(name) system->name = system_##name
#define SYSLINK(name) sysfunc.name = system_##name
internal void
link_system_code(System_Functions *system){

View File

@ -9,6 +9,28 @@
// TOP
struct Thread_Context{
u32 job_id;
b32 running;
b32 cancel;
Work_Queue *queue;
u32 id;
u32 group_id;
u32 windows_id;
Thread thread;
};
struct Thread_Group{
Thread_Context *threads;
i32 count;
Unbounded_Work_Queue queue;
i32 cancel_lock0;
i32 cancel_cv0;
};
struct Threading_Vars{
Thread_Memory *thread_memory;
Work_Queue queues[THREAD_GROUP_COUNT];
@ -28,8 +50,10 @@ Sys_Release_Lock_Sig(system_release_lock){
system_release_lock(&threadvars.locks[id]);
}
internal void
job_thread_proc(System_Functions *system, Thread_Context *thread){
internal
PLAT_THREAD_SIG(job_thread_proc){
Thread_Context *thread = (Thread_Context*)ptr;
Work_Queue *queue = threadvars.queues + thread->group_id;
Thread_Group *group = threadvars.groups + thread->group_id;
@ -66,7 +90,7 @@ job_thread_proc(System_Functions *system, Thread_Context *thread){
if (safe_running_thread == THREAD_NOT_ASSIGNED){
thread->job_id = full_job->id;
thread->running = true;
full_job->job.callback(system, thread, thread_memory, full_job->job.data);
full_job->job.callback(&sysfunc, thread, thread_memory, full_job->job.data);
system_schedule_step();
thread->running = false;

View File

@ -76,6 +76,7 @@
#include <linux/fs.h>
#include <linux/input.h>
#include "4ed_link_system_functions.cpp"
//
// Linux macros
@ -112,34 +113,15 @@ struct Linux_Coroutine {
b32 done;
};
struct Thread_Context{
u32 job_id;
b32 running;
b32 cancel;
//
// Linux forward declarations
//
Work_Queue *queue;
u32 id;
u32 group_id;
pthread_t handle;
};
internal void LinuxScheduleStep(void);
struct Thread_Group{
Thread_Context *threads;
i32 count;
Unbounded_Work_Queue queue;
i32 cancel_lock0;
i32 cancel_cv0;
};
struct Mutex{
pthread_mutex_t crit;
};
struct Condition_Variable{
pthread_cond_t cv;
};
internal void LinuxStringDup(String*, void*, size_t);
internal void LinuxToggleFullscreen(Display*, Window);
internal void LinuxFatalErrorMsg(const char* msg);
struct Linux_Vars{
Display *XDisplay;
@ -195,7 +177,6 @@ struct Linux_Vars{
i32 dpi_x, dpi_y;
Plat_Settings settings;
System_Functions system;
App_Functions app;
Custom_API custom_api;
b32 vsync;
@ -208,30 +189,85 @@ struct Linux_Vars{
// Linux globals
//
global System_Functions sysfunc;
global Linux_Vars linuxvars;
global Application_Memory memory_vars;
//
// Linux forward declarations
//
////////////////////////////////
internal void LinuxScheduleStep(void);
internal Plat_Handle
handle_sem(sem_t *sem){
return(*(Plat_Handle*)&sem);
}
internal Plat_Handle LinuxSemToHandle(sem_t*);
internal sem_t* LinuxHandleToSem(Plat_Handle);
internal sem_t*
handle_sem(Plat_Handle h){
return(*(sem_t**)&h);
}
internal Plat_Handle LinuxFDToHandle(int);
internal int LinuxHandleToFD(Plat_Handle);
internal Plat_Handle
handle_fd(int fd){
return(*(Plat_Handle*)&fd);
}
internal void LinuxStringDup(String*, void*, size_t);
internal void LinuxToggleFullscreen(Display*, Window);
internal void LinuxFatalErrorMsg(const char* msg);
internal int
handle_fd(Plat_Handle h){
return(*(int*)&h);
}
internal Sys_Acquire_Lock_Sig(system_acquire_lock);
internal Sys_Release_Lock_Sig(system_release_lock);
////////////////////////////////
internal void system_wait_cv(i32, i32);
internal void system_signal_cv(i32, i32);
struct Thread{
pthread_t t;
};
struct Mutex{
pthread_mutex_t crit;
};
struct Condition_Variable{
pthread_cond_t cv;
};
internal void
system_acquire_lock(Mutex *m){
pthread_mutex_lock(m->crit);
}
internal void
system_release_lock(Mutex *m){
pthread_mutex_unlock(m->crit);
}
internal void
system_wait_cv(Condition_Variable *cv, Mutex *m){
pthread_cond_wait(cv->cv, m->crit);
}
internal void
system_signal_cv(Condition_Variable *cv, Mutex *m){
pthread_cond_signal(cv->cv);
}
// HACK(allen): Reduce this down to just one layer of call.
internal void
system_schedule_step(){
LinuxScheduleStep();
}
internal void
system_wait_on(Plat_Handle handle){
sem_wait(handle_sem(handle));
}
internal void
system_release_semaphore(Plat_Handle handle){
sem_post(handle_sem(handle));
}
#define PLAT_THREAD_SIG(n) void* n(void *ptr)
////////////////////////////////
internal
Sys_Show_Mouse_Cursor_Sig(system_show_mouse_cursor){
@ -482,56 +518,8 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
return(close_me);
}
//
// Multithreading
//
internal void
system_acquire_lock(Mutex *m){
pthread_mutex_lock(m->crit);
}
internal void
system_release_lock(Mutex *m){
pthread_mutex_unlock(m->crit);
}
internal void
system_wait_cv(Condition_Variable *cv, Mutex *m){
pthread_cond_wait(cv->cv, m->crit);
}
internal void
system_signal_cv(Condition_Variable *cv, Mutex *m){
pthread_cond_signal(cv->cv);
}
// HACK(allen): Reduce this down to just one layer of call.
internal void
system_schedule_step(){
LinuxScheduleStep();
}
internal void
system_wait_on(Plat_Handle handle){
sem_wait(LinuxHandleToSem(handle));
}
internal void
system_release_semaphore(Plat_Handle handle){
sem_post(LinuxHandleToSem(handle));
}
#include "4ed_work_queues.cpp"
internal void*
JobThreadProc(void* lpParameter){
Thread_Context *thread = (Thread_Context*)lpParameter;
job_thread_proc(&linuxvars.system, thread);
InvalidCodePath;
return(0);
}
//
// Linux rendering/font system functions
//
@ -585,7 +573,7 @@ LinuxLoadRenderCode(){
internal void
LinuxRedrawTarget(){
launch_rendering(&linuxvars.system, &linuxvars.target);
launch_rendering(&sysfunc, &linuxvars.target);
//glFlush();
glXSwapBuffers(linuxvars.XDisplay, linuxvars.XWindow);
}
@ -1077,26 +1065,6 @@ LinuxPushKey(Key_Code code, Key_Code chr, Key_Code chr_nocaps, b8 (*mods)[MDFR_I
// Misc utility funcs
//
internal Plat_Handle
LinuxSemToHandle(sem_t* sem){
return *(Plat_Handle*)&sem;
}
internal sem_t*
LinuxHandleToSem(Plat_Handle h){
return *(sem_t**)&h;
}
internal Plat_Handle
LinuxFDToHandle(int fd){
return *(Plat_Handle*)&fd;
}
internal int
LinuxHandleToFD(Plat_Handle h){
return *(int*)&h;
}
internal void
LinuxStringDup(String* str, void* data, size_t size){
if (str->memory_size < size){
@ -1946,7 +1914,7 @@ main(int argc, char **argv){
return 99;
}
link_system_code(&linuxvars.system);
link_system_code(&sysfunc);
LinuxLoadRenderCode();
memory_vars.vars_memory_size = MB(2);
@ -1988,7 +1956,7 @@ main(int argc, char **argv){
i32 *file_count;
i32 output_size;
output_size = linuxvars.app.read_command_line(&linuxvars.system, &memory_vars, current_directory, &linuxvars.settings, &files, &file_count, clparams);
output_size = linuxvars.app.read_command_line(&sysfunc, &memory_vars, current_directory, &linuxvars.settings, &files, &file_count, clparams);
if (output_size > 0){
LOGF("%.*s", output_size, (char*)memory_vars.target_memory);
@ -2099,7 +2067,7 @@ main(int argc, char **argv){
memory->id = thread->id;
thread->queue = &threadvars.queues[BACKGROUND_THREADS];
pthread_create(&thread->handle, NULL, &JobThreadProc, thread);
pthread_create(&thread->handle, NULL, &job_thread_proc, thread);
}
initialize_unbounded_queue(&threadvars.groups[BACKGROUND_THREADS].queue);
@ -2208,7 +2176,7 @@ main(int argc, char **argv){
// Font System Init
//
system_font_init(&linuxvars.system.font, 0, 0, linuxvars.settings.font_size, linuxvars.settings.use_hinting);
system_font_init(&sysfunc.font, 0, 0, linuxvars.settings.font_size, linuxvars.settings.use_hinting);
//
// Epoll init
@ -2241,7 +2209,7 @@ main(int argc, char **argv){
XAddConnectionWatch(linuxvars.XDisplay, &LinuxX11ConnectionWatch, NULL);
linuxvars.app.init(&linuxvars.system, &linuxvars.target, &memory_vars, linuxvars.clipboard_contents, current_directory, linuxvars.custom_api);
linuxvars.app.init(&sysfunc, &linuxvars.target, &memory_vars, linuxvars.clipboard_contents, current_directory, linuxvars.custom_api);
LinuxResizeTarget(window_width, window_height);
@ -2319,14 +2287,7 @@ main(int argc, char **argv){
linuxvars.last_step = system_now_time();
if (linuxvars.input.first_step || !linuxvars.has_xfixes){
XConvertSelection(
linuxvars.XDisplay,
linuxvars.atom_CLIPBOARD,
linuxvars.atom_UTF8_STRING,
linuxvars.atom_CLIPBOARD,
linuxvars.XWindow,
CurrentTime
);
XConvertSelection(linuxvars.XDisplay, linuxvars.atom_CLIPBOARD, linuxvars.atom_UTF8_STRING, linuxvars.atom_CLIPBOARD, linuxvars.XWindow, CurrentTime);
}
Application_Step_Result result = {};
@ -2342,14 +2303,7 @@ main(int argc, char **argv){
b32 keep_running = linuxvars.keep_running;
linuxvars.app.step(
&linuxvars.system,
&linuxvars.target,
&memory_vars,
&linuxvars.input,
&result,
clparams
);
linuxvars.app.step(&sysfunc, &linuxvars.target, &memory_vars, &linuxvars.input, &result, clparams);
if (result.perform_kill){
break;

View File

@ -71,7 +71,7 @@ Sys_Font_Get_Render_Data_By_ID_Sig(system_font_get_render_data_by_id){
internal
Sys_Font_Load_Page_Sig(system_font_load_page){
system_set_page(&linuxvars.system, &linux_fonts.part, font, page, page_number, linuxvars.settings.font_size, linuxvars.settings.use_hinting);
system_set_page(&sysfunc, &linux_fonts.part, font, page, page_number, linuxvars.settings.font_size, linuxvars.settings.use_hinting);
}
internal
@ -157,7 +157,7 @@ Sys_Font_Init_Sig(system_font_init){
if (i < font_count_max){
Render_Font *render_font = &linux_fonts.fonts[i];
system_set_font(&linuxvars.system, &linux_fonts.part, render_font, ptr->c_filename, font_size, use_hinting);
system_set_font(&sysfunc, &linux_fonts.part, render_font, ptr->c_filename, font_size, use_hinting);
}
++font_count;

View File

@ -135,38 +135,7 @@ enum CV_ID{
CV_COUNT
};
struct Thread_Context{
u32 job_id;
b32 running;
b32 cancel;
Work_Queue *queue;
u32 id;
u32 group_id;
u32 windows_id;
HANDLE handle;
};
struct Thread_Group{
Thread_Context *threads;
i32 count;
Unbounded_Work_Queue queue;
i32 cancel_lock0;
i32 cancel_cv0;
};
struct Mutex{
CRITICAL_SECTION crit;
};
struct Condition_Variable{
CONDITION_VARIABLE cv;
};
struct Win32_Vars{
System_Functions system;
App_Functions app;
Custom_API custom_api;
HMODULE app_code;
@ -208,9 +177,79 @@ struct Win32_Vars{
};
global System_Functions sysfunc;
global Win32_Vars win32vars;
global Application_Memory memory_vars;
////////////////////////////////
internal HANDLE
handle_type(Plat_Handle h){
HANDLE result;
memcpy(&result, &h, sizeof(result));
return(result);
}
internal Plat_Handle
handle_type(HANDLE h){
Plat_Handle result = {0};
memcpy(&result, &h, sizeof(h));
return(result);
}
////////////////////////////////
struct Thread{
HANDLE t;
};
struct Mutex{
CRITICAL_SECTION crit;
};
struct Condition_Variable{
CONDITION_VARIABLE cv;
};
internal void
system_acquire_lock(Mutex *m){
EnterCriticalSection(&m->crit);
}
internal void
system_release_lock(Mutex *m){
LeaveCriticalSection(&m->crit);
}
internal void
system_wait_cv(Condition_Variable *cv, Mutex *lock){
SleepConditionVariableCS(&cv->cv, &lock->crit, INFINITE);
}
internal void
system_signal_cv(Condition_Variable *cv, Mutex *lock){
WakeConditionVariable(&cv->cv);
}
internal void
system_schedule_step(){
PostMessage(win32vars.window_handle, WM_4coder_ANIMATE, 0, 0);
}
internal void
system_wait_on(Plat_Handle handle){
WaitForSingleObject(handle_type(handle), INFINITE);
}
internal void
system_release_semaphore(Plat_Handle handle){
ReleaseSemaphore(handle_type(handle), 1, 0);
}
#define PLAT_THREAD_SIG(n) DWORD CALL_CONVENTION n(LPVOID ptr)
////////////////////////////////
//
// 4ed path
//
@ -254,40 +293,6 @@ Sys_Log_Sig(system_log){
}
}
//
// Helpers
//
internal HANDLE
Win32Handle(Plat_Handle h){
HANDLE result;
memcpy(&result, &h, sizeof(result));
return(result);
}
internal Plat_Handle
Win32Handle(HANDLE h){
Plat_Handle result = {0};
Assert(sizeof(Plat_Handle) >= sizeof(h));
memcpy(&result, &h, sizeof(h));
return(result);
}
internal void*
Win32Ptr(Plat_Handle h){
void *result;
memcpy(&result, &h, sizeof(result));
return(result);
}
internal Plat_Handle
Win32Ptr(void *h){
Plat_Handle result = {0};
memcpy(&result, &h, sizeof(h));
return(result);
}
//
// Memory (not exposed to application, but needed in system_shared.cpp)
//
@ -333,55 +338,8 @@ Sys_Memory_Free_Sig(system_memory_free){
VirtualFree(ptr, 0, MEM_RELEASE);
}
//
// Multithreading
//
internal void
system_acquire_lock(Mutex *m){
EnterCriticalSection(&m->crit);
}
internal void
system_release_lock(Mutex *m){
LeaveCriticalSection(&m->crit);
}
internal void
system_wait_cv(Condition_Variable *cv, Mutex *lock){
SleepConditionVariableCS(&cv->cv, &lock->crit, INFINITE);
}
internal void
system_signal_cv(Condition_Variable *cv, Mutex *lock){
WakeConditionVariable(&cv->cv);
}
internal void
system_schedule_step(){
PostMessage(win32vars.window_handle, WM_4coder_ANIMATE, 0, 0);
}
internal void
system_wait_on(Plat_Handle handle){
WaitForSingleObject(Win32Handle(handle), INFINITE);
}
internal void
system_release_semaphore(Plat_Handle handle){
ReleaseSemaphore(Win32Handle(handle), 1, 0);
}
#include "4ed_work_queues.cpp"
internal DWORD CALL_CONVENTION
JobThreadProc(LPVOID lpParameter){
Thread_Context *thread = (Thread_Context*)lpParameter;
job_thread_proc(&win32vars.system, thread);
InvalidCodePath;
return(0);
}
//
// Coroutines
//
@ -422,7 +380,7 @@ Sys_Create_Coroutine_Sig(system_create_coroutine){
fiber = CreateFiber(0, Win32CoroutineMain, coroutine);
coroutine->plat_handle = Win32Handle(fiber);
coroutine->plat_handle = handle_type(fiber);
coroutine->func = func;
return(coroutine);
@ -433,7 +391,7 @@ Sys_Launch_Coroutine_Sig(system_launch_coroutine){
Win32_Coroutine *c = (Win32_Coroutine*)coroutine;
void *fiber;
fiber = Win32Handle(coroutine->plat_handle);
fiber = handle_type(coroutine->plat_handle);
coroutine->yield_handle = GetCurrentFiber();
coroutine->in = in;
coroutine->out = out;
@ -459,7 +417,7 @@ Sys_Resume_Coroutine_Sig(system_resume_coroutine){
coroutine->in = in;
coroutine->out = out;
fiber = Win32Ptr(coroutine->plat_handle);
fiber = handle_type(coroutine->plat_handle);
SwitchToFiber(fiber);
@ -1207,7 +1165,7 @@ Win32KeycodeInit(){
internal void
Win32RedrawScreen(HDC hdc){
launch_rendering(&win32vars.system, &win32vars.target);
launch_rendering(&sysfunc, &win32vars.target);
glFlush();
SwapBuffers(hdc);
}
@ -1677,7 +1635,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
Thread_Memory thread_memory[ArrayCount(background)];
threadvars.thread_memory = thread_memory;
threadvars.queues[BACKGROUND_THREADS].semaphore =Win32Handle(CreateSemaphore(0, 0, threadvars.groups[BACKGROUND_THREADS].count, 0));
threadvars.queues[BACKGROUND_THREADS].semaphore =handle_type(CreateSemaphore(0, 0, threadvars.groups[BACKGROUND_THREADS].count, 0));
u32 creation_flag = 0;
for (i32 i = 0; i < threadvars.groups[BACKGROUND_THREADS].count; ++i){
@ -1691,7 +1649,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
thread->queue = &threadvars.queues[BACKGROUND_THREADS];
thread->handle = CreateThread(0, 0, JobThreadProc, thread, creation_flag, (LPDWORD)&thread->windows_id);
thread->thread.t = CreateThread(0, 0, job_thread_proc, thread, creation_flag, (LPDWORD)&thread->windows_id);
}
initialize_unbounded_queue(&threadvars.groups[BACKGROUND_THREADS].queue);
@ -1754,11 +1712,9 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
}
link_system_code(&win32vars.system);
link_system_code(&sysfunc);
Win32LoadRenderCode();
System_Functions *system = &win32vars.system;
//
// Shared Systems Init
//
@ -1785,7 +1741,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
char **files = 0;
i32 *file_count = 0;
win32vars.app.read_command_line(system, &memory_vars, current_directory, &win32vars.settings, &files, &file_count, clparams);
win32vars.app.read_command_line(&sysfunc, &memory_vars, current_directory, &win32vars.settings, &files, &file_count, clparams);
sysshared_filter_real_files(files, file_count);
LOG("Loaded system code, read command line.\n");
@ -1907,7 +1863,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
//
LOG("Initializing fonts\n");
system_font_init(&system->font, 0, 0, win32vars.settings.font_size, win32vars.settings.use_hinting);
system_font_init(&sysfunc.font, 0, 0, win32vars.settings.font_size, win32vars.settings.use_hinting);
//
// Misc System Initializations
@ -1956,7 +1912,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
//
LOG("Initializing application variables\n");
win32vars.app.init(system, &win32vars.target, &memory_vars, win32vars.clipboard_contents, current_directory, win32vars.custom_api);
win32vars.app.init(&sysfunc, &win32vars.target, &memory_vars, win32vars.clipboard_contents, current_directory, win32vars.custom_api);
system_memory_free(current_directory.str, 0);
@ -2157,7 +2113,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
win32vars.send_exit_signal = 0;
}
win32vars.app.step(system, &win32vars.target, &memory_vars, &input, &result, clparams);
win32vars.app.step(&sysfunc, &win32vars.target, &memory_vars, &input, &result, clparams);
if (result.perform_kill){
keep_playing = 0;

View File

@ -71,7 +71,7 @@ Sys_Font_Get_Render_Data_By_ID_Sig(system_font_get_render_data_by_id){
internal
Sys_Font_Load_Page_Sig(system_font_load_page){
system_set_page(&win32vars.system, &win32_fonts.part, font, page, page_number, win32vars.settings.font_size, win32vars.settings.use_hinting);
system_set_page(&sysfunc, &win32_fonts.part, font, page, page_number, win32vars.settings.font_size, win32vars.settings.use_hinting);
}
internal
@ -157,7 +157,7 @@ Sys_Font_Init_Sig(system_font_init){
if (i < font_count_max){
Render_Font *render_font = &win32_fonts.fonts[i];
system_set_font(&win32vars.system, &win32_fonts.part, render_font, ptr->c_filename, font_size, use_hinting);
system_set_font(&sysfunc, &win32_fonts.part, render_font, ptr->c_filename, font_size, use_hinting);
}
++font_count;