feat: config variables, mutex abstraction

- Mutex abstraction (create, destroy, lock, unlock)
- Config variables (cvars)
This commit is contained in:
Kevin Trogant 2023-10-14 00:15:05 +02:00
parent 1dba3d2d63
commit 63e3f973b2
9 changed files with 259 additions and 8 deletions

43
include/config.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef VY_CONFIG_H
#define VY_CONFIG_H
typedef enum
{
VY_CVAR_TYPE_INT,
VY_CVAR_TYPE_FLOAT,
VY_CVAR_TYPE_STRING,
} vy_cvar_type;
typedef struct
{
const char *name;
const char *description;
union {
int i;
float f;
const char *s;
};
vy_cvar_type type;
} vy_cvar;
#define VY_CVAR_I(n, d, v) \
vy_cvar n = {.name = #n, \
.description = d, \
.i = (v), \
.type = VY_CVAR_TYPE_INT}
#define VY_CVAR_F(n, d, v) \
vy_cvar n = {.name = #n, \
.description = d, \
.f = (v), \
.type = VY_CVAR_TYPE_FLOAT}
#define VY_CVAR_S(n, d, v) \
vy_cvar n = {.name = #n, \
.description = d, \
.s = (v), \
.type = VY_CVAR_TYPE_STRING}
void vyRegisterCVAR(vy_cvar *cvar);
vy_cvar *vyGetCVAR(const char *name);
#endif

18
include/threading.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef VY_THREADING_H
#define VY_THREADING_H
/* platform independent threading */
#include <stdbool.h>
typedef struct vy_mutex_s vy_mutex;
vy_mutex *vyCreateMutex(void);
void vyDestroyMutex(vy_mutex *mutex);
bool vyLockMutex(vy_mutex *mutex);
bool vyUnlockMutex(vy_mutex *mutex);
#endif

View File

@ -6,6 +6,7 @@
#include <stddef.h> #include <stddef.h>
#define VY_UNUSED(x) ((void)sizeof((x))) #define VY_UNUSED(x) ((void)sizeof((x)))
#define VY_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
typedef struct { typedef struct {
const char *start; const char *start;

View File

@ -13,9 +13,12 @@ if compiler.get_argument_syntax() == 'gcc'
) )
elif compiler.get_argument_syntax() == 'msvc' elif compiler.get_argument_syntax() == 'msvc'
add_project_arguments( add_project_arguments(
['/wd4146', '/wd4245', '/wd4100', '/D_CRT_SECURE_NO_WARNINGS', '/RTCsu'], ['/wd4146', '/wd4245', '/wd4100', '/D_CRT_SECURE_NO_WARNINGS'],
language: 'c' language: 'c'
) )
if buildtype == 'debug'
add_project_arguments(['/RTCsu'], language : 'c')
endif
endif endif
# Debug specific flags # Debug specific flags
@ -41,6 +44,8 @@ executable('voyage',
'include/gfx.h', 'include/gfx.h',
'include/gfx_backend.h', 'include/gfx_backend.h',
'include/fio.h', 'include/fio.h',
'include/config.h',
'include/threading.h',
'src/voyage.c', 'src/voyage.c',
'src/fio.c', 'src/fio.c',
@ -48,6 +53,8 @@ executable('voyage',
'src/gfx_main.c', 'src/gfx_main.c',
'src/gfx_shader_loading.c', 'src/gfx_shader_loading.c',
'src/gfx_pipelines.c', 'src/gfx_pipelines.c',
'src/config.c',
'src/threading.c',
# Contrib Sources # Contrib Sources
'contrib/glad/glad.c', 'contrib/glad/glad.c',

39
src/config.c Normal file
View File

@ -0,0 +1,39 @@
#include "config.h"
#include "threading.h"
#include "voyage.h"
#include <stddef.h>
#include <string.h>
#define VY_MAX_CVARS 1024
static vy_cvar *_vars[VY_MAX_CVARS];
static unsigned int _next = 0;
static vy_mutex *_mutex = NULL;
void vyRegisterCVAR(vy_cvar *cvar) {
if (!_mutex)
_mutex = vyCreateMutex();
vyLockMutex(_mutex);
if (_next < VY_MAX_CVARS) {
_vars[_next++] = cvar;
} else {
vyReportError("cvar", "Ran out of space for CVars");
}
vyUnlockMutex(_mutex);
}
vy_cvar *vyGetCVAR(const char *name) {
if (!_mutex)
_mutex = vyCreateMutex();
vy_cvar *var = NULL;
vyLockMutex(_mutex);
for (unsigned int i = 0; i < _next; ++i) {
if (strcmp(name, _vars[i]->name) == 0) {
var = _vars[i];
break;
}
}
vyUnlockMutex(_mutex);
return var;
}

View File

@ -3,22 +3,66 @@
#include "voyage.h" #include "voyage.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
/* TODO(Kevin): Log to file, show error message box, ... */ /* TODO(Kevin): Log to file, show error message box, ... */
static void DisplayErrorBox(const char *text)
{
#ifdef _WIN32
WCHAR msg[256];
MultiByteToWideChar(CP_UTF8,
MB_PRECOMPOSED,
text,
-1,
msg,
VY_ARRAY_COUNT(msg));
MessageBoxW(NULL, msg, L"Error", MB_ICONERROR);
#endif
}
static void LogOut(const char *text)
{
#ifdef _WIN32
WCHAR msg[256];
MultiByteToWideChar(CP_UTF8,
MB_PRECOMPOSED,
text,
-1,
msg,
VY_ARRAY_COUNT(msg));
OutputDebugStringW(msg);
#elif defined(__linux__)
fprintf(stderr, "%s", text);
#endif
}
void vyReportError(const char *subsystem, const char *fmt, ...) { void vyReportError(const char *subsystem, const char *fmt, ...) {
char buf[256];
int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
fprintf(stderr, "[%s] ", subsystem); at += vsnprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, fmt, ap);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap); va_end(ap);
at += snprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, "\n");
LogOut(buf);
DisplayErrorBox(buf);
} }
void vyLog(const char *subsystem, const char *fmt, ...) { void vyLog(const char *subsystem, const char *fmt, ...) {
char buf[256];
int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
fprintf(stderr, "[%s] ", subsystem); at += vsnprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, fmt, ap);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap); va_end(ap);
at += snprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, "\n");
LogOut(buf);
} }

View File

@ -233,7 +233,7 @@ static void DbgPrintShaderFile(const vy_parse_state *state,
} }
stmt_index = stmt->next; stmt_index = stmt->next;
} }
assert(stmt_index == UINT_MAX); assert(stmt_index == UINT_MAX || stmt_index == 0);
} }
static bool CompareSpanToString(vy_text_span span, const char *cmp) { static bool CompareSpanToString(vy_text_span span, const char *cmp) {

98
src/threading.c Normal file
View File

@ -0,0 +1,98 @@
#include "threading.h"
#include "voyage.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
struct vy_mutex_s {
HANDLE handle;
ptrdiff_t next_reusable;
};
#define MAX_MUTEX 1024
static vy_mutex _mutex[MAX_MUTEX];
static ptrdiff_t _first_reusable = MAX_MUTEX;
static ptrdiff_t _next = 0;
vy_mutex *vyCreateMutex(void) {
if (_first_reusable < MAX_MUTEX) {
vy_mutex *mtx = &_mutex[_first_reusable];
_first_reusable = mtx->next_reusable;
return mtx;
} else if (_next < MAX_MUTEX) {
vy_mutex *mtx = &_mutex[_next];
mtx->handle = CreateMutexW(NULL, FALSE, NULL);
if (!mtx->handle) {
vyLog("core", "Mutex creation failed: %u", GetLastError());
return NULL;
}
mtx->next_reusable = MAX_MUTEX;
++_next;
return mtx;
}
vyReportError("core", "Ran out of mutex objects");
return NULL;
}
void vyDestroyMutex(vy_mutex *mutex) {
ptrdiff_t index = mutex - &_mutex[0];
mutex->next_reusable = _first_reusable;
_first_reusable = index;
}
bool vyLockMutex(vy_mutex *mutex) {
return WaitForSingleObject(mutex->handle, INFINITE) == WAIT_OBJECT_0;
}
bool vyUnlockMutex(vy_mutex *mutex) {
return ReleaseMutex(mutex) != 0;
}
#elif defined(__linux__)
#include <pthread.h>
struct vy_mutex_s {
pthread_mutex_t handle;
ptrdiff_t next_reusable;
};
#define MAX_MUTEX 1024
static vy_mutex _mutex[MAX_MUTEX];
static ptrdiff_t _first_reusable = MAX_MUTEX;
static ptrdiff_t _next = 0;
vy_mutex *vyCreateMutex(void) {
if (_first_reusable < MAX_MUTEX) {
vy_mutex *mtx = &_mutex[_first_reusable];
_first_reusable = mtx->next_reusable;
return mtx;
} else if (_next < MAX_MUTEX) {
vy_mutex *mtx = &_mutex[_next];
if (pthread_mutex_init(&mtx->handle, NULL) != 0) {
vyLog("core", "Mutex creation failed: %u", GetLastError());
return NULL;
}
mtx->next_reusable = MAX_MUTEX;
++_next;
return mtx;
}
vyReportError("core", "Ran out of mutex objects");
return NULL;
}
void vyDestroyMutex(vy_mutex *mutex) {
ptrdiff_t index = mutex - &_mutex[0];
mutex->next_reusable = _first_reusable;
_first_reusable = index;
}
bool vyLockMutex(vy_mutex *mutex) {
return pthread_mutex_lock(&mutex->handle) == 0;
}
bool vyUnlockMutex(vy_mutex *mutex) {
return pthread_mutex_unlock(&mutex->handle) == 0;
}
#endif

View File

@ -7,6 +7,7 @@
#include "fio.h" #include "fio.h"
#include "gfx.h" #include "gfx.h"
#include "threading.h"
static void glfw_error_cb(int err, const char *description) { static void glfw_error_cb(int err, const char *description) {
fprintf(stderr, "[GLFW] %u: %s\n", err, description); fprintf(stderr, "[GLFW] %u: %s\n", err, description);