feat: config variables, mutex abstraction
- Mutex abstraction (create, destroy, lock, unlock) - Config variables (cvars)
This commit is contained in:
		
							parent
							
								
									1dba3d2d63
								
							
						
					
					
						commit
						63e3f973b2
					
				
							
								
								
									
										43
									
								
								include/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								include/config.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										18
									
								
								include/threading.h
									
									
									
									
									
										Normal 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
 | 
			
		||||
@ -6,6 +6,7 @@
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
#define VY_UNUSED(x) ((void)sizeof((x)))
 | 
			
		||||
#define VY_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    const char *start;
 | 
			
		||||
 | 
			
		||||
@ -13,9 +13,12 @@ if compiler.get_argument_syntax() == 'gcc'
 | 
			
		||||
    )
 | 
			
		||||
elif compiler.get_argument_syntax() == 'msvc'
 | 
			
		||||
  add_project_arguments(
 | 
			
		||||
    ['/wd4146', '/wd4245', '/wd4100', '/D_CRT_SECURE_NO_WARNINGS', '/RTCsu'],
 | 
			
		||||
    ['/wd4146', '/wd4245', '/wd4100', '/D_CRT_SECURE_NO_WARNINGS'],
 | 
			
		||||
    language:  'c'
 | 
			
		||||
    )
 | 
			
		||||
  if buildtype == 'debug'
 | 
			
		||||
    add_project_arguments(['/RTCsu'], language : 'c')
 | 
			
		||||
  endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# Debug specific flags
 | 
			
		||||
@ -41,6 +44,8 @@ executable('voyage',
 | 
			
		||||
  'include/gfx.h',
 | 
			
		||||
  'include/gfx_backend.h',
 | 
			
		||||
  'include/fio.h',
 | 
			
		||||
  'include/config.h',
 | 
			
		||||
  'include/threading.h',
 | 
			
		||||
 | 
			
		||||
  'src/voyage.c',
 | 
			
		||||
  'src/fio.c',
 | 
			
		||||
@ -48,6 +53,8 @@ executable('voyage',
 | 
			
		||||
  'src/gfx_main.c',
 | 
			
		||||
  'src/gfx_shader_loading.c',
 | 
			
		||||
  'src/gfx_pipelines.c',
 | 
			
		||||
  'src/config.c',
 | 
			
		||||
  'src/threading.c',
 | 
			
		||||
 | 
			
		||||
  # Contrib Sources
 | 
			
		||||
  'contrib/glad/glad.c',
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										39
									
								
								src/config.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/config.c
									
									
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
@ -3,22 +3,66 @@
 | 
			
		||||
 | 
			
		||||
#include "voyage.h"
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#define WIN32_LEAN_AND_MEAN
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* 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, ...) {
 | 
			
		||||
    char buf[256];
 | 
			
		||||
 | 
			
		||||
    int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
 | 
			
		||||
    va_list ap;
 | 
			
		||||
    va_start(ap, fmt);
 | 
			
		||||
    fprintf(stderr, "[%s] ", subsystem);
 | 
			
		||||
    vfprintf(stderr, fmt, ap);
 | 
			
		||||
    fprintf(stderr, "\n");
 | 
			
		||||
    at += vsnprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, fmt, 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, ...) {
 | 
			
		||||
    char buf[256];
 | 
			
		||||
 | 
			
		||||
    int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
 | 
			
		||||
    va_list ap;
 | 
			
		||||
    va_start(ap, fmt);
 | 
			
		||||
    fprintf(stderr, "[%s] ", subsystem);
 | 
			
		||||
    vfprintf(stderr, fmt, ap);
 | 
			
		||||
    fprintf(stderr, "\n");
 | 
			
		||||
    at += vsnprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, fmt, ap);
 | 
			
		||||
    va_end(ap);
 | 
			
		||||
    at += snprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, "\n");
 | 
			
		||||
 | 
			
		||||
    LogOut(buf);
 | 
			
		||||
}
 | 
			
		||||
@ -233,7 +233,7 @@ static void DbgPrintShaderFile(const vy_parse_state *state,
 | 
			
		||||
        }
 | 
			
		||||
        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) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										98
									
								
								src/threading.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/threading.c
									
									
									
									
									
										Normal 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
 | 
			
		||||
@ -7,6 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include "fio.h"
 | 
			
		||||
#include "gfx.h"
 | 
			
		||||
#include "threading.h"
 | 
			
		||||
 | 
			
		||||
static void glfw_error_cb(int err, const char *description) {
 | 
			
		||||
    fprintf(stderr, "[GLFW] %u: %s\n", err, description);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user