mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
context system
This commit is contained in:
parent
9483f1ea02
commit
e69d48e37b
@ -2,11 +2,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
nn_screen *nn_newScreen(nn_Alloc *alloc, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors) {
|
nn_screen *nn_newScreen(nn_Context *context, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors) {
|
||||||
|
nn_Alloc *alloc = &context->allocator;
|
||||||
nn_screen *screen = nn_alloc(alloc, sizeof(nn_screen));
|
nn_screen *screen = nn_alloc(alloc, sizeof(nn_screen));
|
||||||
screen->alloc = *alloc;
|
screen->ctx = *context;
|
||||||
screen->buffer = nn_alloc(alloc, sizeof(nn_scrchr_t) * maxWidth * maxHeight);
|
screen->buffer = nn_alloc(alloc, sizeof(nn_scrchr_t) * maxWidth * maxHeight);
|
||||||
screen->lock = nn_newGuard(alloc);
|
screen->lock = nn_newGuard(context);
|
||||||
screen->refc = 1;
|
screen->refc = 1;
|
||||||
screen->width = maxWidth;
|
screen->width = maxWidth;
|
||||||
screen->height = maxHeight;
|
screen->height = maxHeight;
|
||||||
@ -36,19 +37,19 @@ void nn_retainScreen(nn_screen *screen) {
|
|||||||
|
|
||||||
void nn_destroyScreen(nn_screen *screen) {
|
void nn_destroyScreen(nn_screen *screen) {
|
||||||
if(!nn_decRef(&screen->refc)) return;
|
if(!nn_decRef(&screen->refc)) return;
|
||||||
nn_Alloc a = screen->alloc;
|
nn_Alloc a = screen->ctx.allocator;
|
||||||
nn_deleteGuard(&a, screen->lock);
|
nn_deleteGuard(&screen->ctx, screen->lock);
|
||||||
nn_dealloc(&a, screen->buffer, sizeof(nn_scrchr_t) * screen->maxWidth * screen->maxHeight);
|
nn_dealloc(&a, screen->buffer, sizeof(nn_scrchr_t) * screen->maxWidth * screen->maxHeight);
|
||||||
nn_dealloc(&a, screen->palette, sizeof(int) * screen->paletteColors);
|
nn_dealloc(&a, screen->palette, sizeof(int) * screen->paletteColors);
|
||||||
nn_dealloc(&a, screen, sizeof(nn_screen));
|
nn_dealloc(&a, screen, sizeof(nn_screen));
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_lockScreen(nn_screen *screen) {
|
void nn_lockScreen(nn_screen *screen) {
|
||||||
nn_lock(screen->lock);
|
nn_lock(&screen->ctx, screen->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_unlockScreen(nn_screen *screen) {
|
void nn_unlockScreen(nn_screen *screen) {
|
||||||
nn_unlock(screen->lock);
|
nn_unlock(&screen->ctx, screen->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_getResolution(nn_screen *screen, int *width, int *height) {
|
void nn_getResolution(nn_screen *screen, int *width, int *height) {
|
||||||
@ -88,7 +89,7 @@ void nn_setAspectRatio(nn_screen *screen, int width, int height) {
|
|||||||
|
|
||||||
void nn_addKeyboard(nn_screen *screen, nn_address address) {
|
void nn_addKeyboard(nn_screen *screen, nn_address address) {
|
||||||
if(screen->keyboardCount == NN_MAX_SCREEN_KEYBOARDS) return;
|
if(screen->keyboardCount == NN_MAX_SCREEN_KEYBOARDS) return;
|
||||||
char *kb = nn_strdup(&screen->alloc, address);
|
char *kb = nn_strdup(&screen->ctx.allocator, address);
|
||||||
if(kb == NULL) return;
|
if(kb == NULL) return;
|
||||||
screen->keyboards[screen->keyboardCount++] = kb;
|
screen->keyboards[screen->keyboardCount++] = kb;
|
||||||
}
|
}
|
||||||
@ -97,7 +98,7 @@ void nn_removeKeyboard(nn_screen *screen, nn_address address) {
|
|||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for(size_t i = 0; i < screen->keyboardCount; i++) {
|
for(size_t i = 0; i < screen->keyboardCount; i++) {
|
||||||
if(strcmp(screen->keyboards[i], address) == 0) {
|
if(strcmp(screen->keyboards[i], address) == 0) {
|
||||||
nn_deallocStr(&screen->alloc, screen->keyboards[i]);
|
nn_deallocStr(&screen->ctx.allocator, screen->keyboards[i]);
|
||||||
} else {
|
} else {
|
||||||
screen->keyboards[j] = screen->keyboards[i];
|
screen->keyboards[j] = screen->keyboards[i];
|
||||||
j++;
|
j++;
|
||||||
@ -212,12 +213,12 @@ void nn_screenComp_destroy(void *_, nn_component *component, nn_screen *screen)
|
|||||||
|
|
||||||
void nn_screenComp_getKeyboards(nn_screen *screen, void *_, nn_component *component, nn_computer *computer) {
|
void nn_screenComp_getKeyboards(nn_screen *screen, void *_, nn_component *component, nn_computer *computer) {
|
||||||
nn_lockScreen(screen);
|
nn_lockScreen(screen);
|
||||||
nn_value arr = nn_values_array(&screen->alloc, nn_getKeyboardCount(screen));
|
nn_value arr = nn_values_array(&screen->ctx.allocator, nn_getKeyboardCount(screen));
|
||||||
|
|
||||||
size_t len = arr.array->len;
|
size_t len = arr.array->len;
|
||||||
for(size_t i = 0; i < len; i++) {
|
for(size_t i = 0; i < len; i++) {
|
||||||
size_t addrlen = strlen(nn_getKeyboard(screen, i));
|
size_t addrlen = strlen(nn_getKeyboard(screen, i));
|
||||||
nn_value addr = nn_values_string(&screen->alloc, nn_getKeyboard(screen, i), addrlen);
|
nn_value addr = nn_values_string(&screen->ctx.allocator, nn_getKeyboard(screen, i), addrlen);
|
||||||
nn_values_set(arr, i, addr);
|
nn_values_set(arr, i, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "../neonucleus.h"
|
#include "../neonucleus.h"
|
||||||
|
|
||||||
typedef struct nn_screen {
|
typedef struct nn_screen {
|
||||||
nn_Alloc alloc;
|
nn_Context ctx;
|
||||||
nn_scrchr_t *buffer;
|
nn_scrchr_t *buffer;
|
||||||
nn_guard *lock;
|
nn_guard *lock;
|
||||||
nn_refc refc;
|
nn_refc refc;
|
||||||
|
@ -5,23 +5,24 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit) {
|
nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit) {
|
||||||
nn_computer *c = nn_alloc(&universe->alloc, sizeof(nn_computer));
|
nn_Alloc *alloc = &universe->ctx.allocator;
|
||||||
c->components = nn_alloc(&universe->alloc, sizeof(nn_component) * componentLimit);
|
nn_computer *c = nn_alloc(alloc, sizeof(nn_computer));
|
||||||
|
c->components = nn_alloc(alloc, sizeof(nn_component) * componentLimit);
|
||||||
if(c->components == NULL) {
|
if(c->components == NULL) {
|
||||||
nn_dealloc(&universe->alloc, c, sizeof(nn_computer));
|
nn_dealloc(alloc, c, sizeof(nn_computer));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
c->address = nn_strdup(&universe->alloc, address);
|
c->address = nn_strdup(alloc, address);
|
||||||
if(c->address == NULL) {
|
if(c->address == NULL) {
|
||||||
nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit);
|
nn_dealloc(alloc, c->components, sizeof(nn_component) * componentLimit);
|
||||||
nn_dealloc(&universe->alloc, c, sizeof(nn_computer));
|
nn_dealloc(alloc, c, sizeof(nn_computer));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
c->lock = nn_newGuard(&universe->alloc);
|
c->lock = nn_newGuard(&universe->ctx);
|
||||||
if(c->lock == NULL) {
|
if(c->lock == NULL) {
|
||||||
nn_deallocStr(&universe->alloc, c->address);
|
nn_deallocStr(alloc, c->address);
|
||||||
nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit);
|
nn_dealloc(alloc, c->components, sizeof(nn_component) * componentLimit);
|
||||||
nn_dealloc(&universe->alloc, c, sizeof(nn_computer));
|
nn_dealloc(alloc, c, sizeof(nn_computer));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
c->timeOffset = nn_getTime(universe);
|
c->timeOffset = nn_getTime(universe);
|
||||||
@ -51,10 +52,10 @@ nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_archit
|
|||||||
// Setup Architecture
|
// Setup Architecture
|
||||||
c->archState = c->arch->setup(c, c->arch->userdata);
|
c->archState = c->arch->setup(c, c->arch->userdata);
|
||||||
if(c->archState == NULL) {
|
if(c->archState == NULL) {
|
||||||
nn_deleteGuard(&universe->alloc, c->lock);
|
nn_deleteGuard(&universe->ctx, c->lock);
|
||||||
nn_deallocStr(&universe->alloc, c->address);
|
nn_deallocStr(alloc, c->address);
|
||||||
nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit);
|
nn_dealloc(alloc, c->components, sizeof(nn_component) * componentLimit);
|
||||||
nn_dealloc(&universe->alloc, c, sizeof(nn_computer));
|
nn_dealloc(alloc, c, sizeof(nn_computer));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,8 +67,8 @@ nn_universe *nn_getUniverse(nn_computer *computer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nn_setTmpAddress(nn_computer *computer, nn_address tmp) {
|
void nn_setTmpAddress(nn_computer *computer, nn_address tmp) {
|
||||||
nn_deallocStr(&computer->universe->alloc, computer->tmpAddress);
|
nn_deallocStr(&computer->universe->ctx.allocator, computer->tmpAddress);
|
||||||
computer->tmpAddress = nn_strdup(&computer->universe->alloc, tmp);
|
computer->tmpAddress = nn_strdup(&computer->universe->ctx.allocator, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
nn_address nn_getComputerAddress(nn_computer *computer) {
|
nn_address nn_getComputerAddress(nn_computer *computer) {
|
||||||
@ -131,12 +132,12 @@ void nn_deleteComputer(nn_computer *computer) {
|
|||||||
while(computer->signalCount > 0) {
|
while(computer->signalCount > 0) {
|
||||||
nn_popSignal(computer);
|
nn_popSignal(computer);
|
||||||
}
|
}
|
||||||
nn_Alloc *a = &computer->universe->alloc;
|
nn_Alloc *a = &computer->universe->ctx.allocator;
|
||||||
for(size_t i = 0; i < computer->userCount; i++) {
|
for(size_t i = 0; i < computer->userCount; i++) {
|
||||||
nn_deallocStr(a, computer->users[i]);
|
nn_deallocStr(a, computer->users[i]);
|
||||||
}
|
}
|
||||||
computer->arch->teardown(computer, computer->archState, computer->arch->userdata);
|
computer->arch->teardown(computer, computer->archState, computer->arch->userdata);
|
||||||
nn_deleteGuard(a, computer->lock);
|
nn_deleteGuard(&computer->universe->ctx, computer->lock);
|
||||||
nn_deallocStr(a, computer->address);
|
nn_deallocStr(a, computer->address);
|
||||||
nn_deallocStr(a, computer->tmpAddress);
|
nn_deallocStr(a, computer->tmpAddress);
|
||||||
nn_dealloc(a, computer->components, sizeof(nn_component) * computer->componentCap);
|
nn_dealloc(a, computer->components, sizeof(nn_component) * computer->componentCap);
|
||||||
@ -185,7 +186,7 @@ void nn_popSignal(nn_computer *computer) {
|
|||||||
|
|
||||||
const char *nn_addUser(nn_computer *computer, const char *name) {
|
const char *nn_addUser(nn_computer *computer, const char *name) {
|
||||||
if(computer->userCount == NN_MAX_USERS) return "too many users";
|
if(computer->userCount == NN_MAX_USERS) return "too many users";
|
||||||
char *user = nn_strdup(&computer->universe->alloc, name);
|
char *user = nn_strdup(&computer->universe->ctx.allocator, name);
|
||||||
if(user == NULL) return "out of memory";
|
if(user == NULL) return "out of memory";
|
||||||
computer->users[computer->userCount] = user;
|
computer->users[computer->userCount] = user;
|
||||||
computer->userCount++;
|
computer->userCount++;
|
||||||
@ -197,7 +198,7 @@ void nn_deleteUser(nn_computer *computer, const char *name) {
|
|||||||
for(size_t i = 0; i < computer->userCount; i++) {
|
for(size_t i = 0; i < computer->userCount; i++) {
|
||||||
char *user = computer->users[i];
|
char *user = computer->users[i];
|
||||||
if(strcmp(user, name) == 0) {
|
if(strcmp(user, name) == 0) {
|
||||||
nn_deallocStr(&computer->universe->alloc, user);
|
nn_deallocStr(&computer->universe->ctx.allocator, user);
|
||||||
} else {
|
} else {
|
||||||
computer->users[j] = user;
|
computer->users[j] = user;
|
||||||
j++;
|
j++;
|
||||||
@ -329,7 +330,7 @@ const char *nn_getError(nn_computer *computer) {
|
|||||||
|
|
||||||
void nn_clearError(nn_computer *computer) {
|
void nn_clearError(nn_computer *computer) {
|
||||||
if(computer->allocatedError) {
|
if(computer->allocatedError) {
|
||||||
nn_deallocStr(&computer->universe->alloc, computer->err);
|
nn_deallocStr(&computer->universe->ctx.allocator, computer->err);
|
||||||
}
|
}
|
||||||
computer->err = NULL;
|
computer->err = NULL;
|
||||||
computer->allocatedError = false;
|
computer->allocatedError = false;
|
||||||
@ -337,7 +338,7 @@ void nn_clearError(nn_computer *computer) {
|
|||||||
|
|
||||||
void nn_setError(nn_computer *computer, const char *err) {
|
void nn_setError(nn_computer *computer, const char *err) {
|
||||||
nn_clearError(computer);
|
nn_clearError(computer);
|
||||||
char *copy = nn_strdup(&computer->universe->alloc, err);
|
char *copy = nn_strdup(&computer->universe->ctx.allocator, err);
|
||||||
if(copy == NULL) {
|
if(copy == NULL) {
|
||||||
nn_setCError(computer, "out of memory");
|
nn_setCError(computer, "out of memory");
|
||||||
return;
|
return;
|
||||||
@ -367,7 +368,7 @@ nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slo
|
|||||||
computer->componentLen++;
|
computer->componentLen++;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->address = nn_strdup(&computer->universe->alloc, address);
|
c->address = nn_strdup(&computer->universe->ctx.allocator, address);
|
||||||
if(c->address == NULL) return NULL;
|
if(c->address == NULL) return NULL;
|
||||||
c->table = table;
|
c->table = table;
|
||||||
c->slot = slot;
|
c->slot = slot;
|
||||||
@ -389,7 +390,7 @@ void nn_removeComponent(nn_computer *computer, nn_address address) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nn_destroyComponent(nn_component *component) {
|
void nn_destroyComponent(nn_component *component) {
|
||||||
nn_deallocStr(&component->computer->universe->alloc, component->address);
|
nn_deallocStr(&component->computer->universe->ctx.allocator, component->address);
|
||||||
if(component->table->destructor != NULL) {
|
if(component->table->destructor != NULL) {
|
||||||
component->table->destructor(component->table->userdata, component, component->statePtr);
|
component->table->destructor(component->table->userdata, component, component->statePtr);
|
||||||
}
|
}
|
||||||
@ -467,11 +468,11 @@ void nn_deserializeProgram(nn_computer *computer, const char *memory, size_t len
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nn_lockComputer(nn_computer *computer) {
|
void nn_lockComputer(nn_computer *computer) {
|
||||||
nn_lock(computer->lock);
|
nn_lock(&computer->universe->ctx, computer->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_unlockComputer(nn_computer *computer) {
|
void nn_unlockComputer(nn_computer *computer) {
|
||||||
nn_unlock(computer->lock);
|
nn_unlock(&computer->universe->ctx, computer->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_return_nil(nn_computer *computer) {
|
void nn_return_nil(nn_computer *computer) {
|
||||||
@ -495,7 +496,7 @@ void nn_return_cstring(nn_computer *computer, const char *cstr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nn_return_string(nn_computer *computer, const char *str, size_t len) {
|
void nn_return_string(nn_computer *computer, const char *str, size_t len) {
|
||||||
nn_value val = nn_values_string(&computer->universe->alloc, str, len);
|
nn_value val = nn_values_string(&computer->universe->ctx.allocator, str, len);
|
||||||
if(val.tag == NN_VALUE_NIL) {
|
if(val.tag == NN_VALUE_NIL) {
|
||||||
nn_setCError(computer, "out of memory");
|
nn_setCError(computer, "out of memory");
|
||||||
}
|
}
|
||||||
@ -503,7 +504,7 @@ void nn_return_string(nn_computer *computer, const char *str, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nn_value nn_return_array(nn_computer *computer, size_t len) {
|
nn_value nn_return_array(nn_computer *computer, size_t len) {
|
||||||
nn_value val = nn_values_array(&computer->universe->alloc, len);
|
nn_value val = nn_values_array(&computer->universe->ctx.allocator, len);
|
||||||
if(val.tag == NN_VALUE_NIL) {
|
if(val.tag == NN_VALUE_NIL) {
|
||||||
nn_setCError(computer, "out of memory");
|
nn_setCError(computer, "out of memory");
|
||||||
}
|
}
|
||||||
@ -512,7 +513,7 @@ nn_value nn_return_array(nn_computer *computer, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nn_value nn_return_table(nn_computer *computer, size_t len) {
|
nn_value nn_return_table(nn_computer *computer, size_t len) {
|
||||||
nn_value val = nn_values_table(&computer->universe->alloc, len);
|
nn_value val = nn_values_table(&computer->universe->ctx.allocator, len);
|
||||||
if(val.tag == NN_VALUE_NIL) {
|
if(val.tag == NN_VALUE_NIL) {
|
||||||
nn_setCError(computer, "out of memory");
|
nn_setCError(computer, "out of memory");
|
||||||
}
|
}
|
||||||
|
@ -579,8 +579,9 @@ typedef struct ne_pressedKey {
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
printf("Setting up universe\n");
|
printf("Setting up universe\n");
|
||||||
nn_Alloc alloc = nn_libcAllocator();
|
nn_Context ctx = nn_libcContext();
|
||||||
nn_universe *universe = nn_newUniverse(alloc);
|
nn_Alloc alloc = ctx.allocator;
|
||||||
|
nn_universe *universe = nn_newUniverse(ctx);
|
||||||
if(universe == NULL) {
|
if(universe == NULL) {
|
||||||
printf("Failed to create universe\n");
|
printf("Failed to create universe\n");
|
||||||
return 1;
|
return 1;
|
||||||
@ -669,7 +670,7 @@ int main() {
|
|||||||
|
|
||||||
int maxWidth = 80, maxHeight = 32;
|
int maxWidth = 80, maxHeight = 32;
|
||||||
|
|
||||||
nn_screen *s = nn_newScreen(&alloc, maxWidth, maxHeight, 24, 16, 256);
|
nn_screen *s = nn_newScreen(&ctx, maxWidth, maxHeight, 24, 16, 256);
|
||||||
nn_setDepth(s, 4); // looks cool
|
nn_setDepth(s, 4); // looks cool
|
||||||
nn_addKeyboard(s, "shitty keyboard");
|
nn_addKeyboard(s, "shitty keyboard");
|
||||||
nn_mountKeyboard(computer, "shitty keyboard", 2);
|
nn_mountKeyboard(computer, "shitty keyboard", 2);
|
||||||
|
73
src/lock.c
73
src/lock.c
@ -1,31 +1,73 @@
|
|||||||
#include "neonucleus.h"
|
#include "neonucleus.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef NN_BAREMETAL
|
||||||
#include "tinycthread.h"
|
#include "tinycthread.h"
|
||||||
|
|
||||||
typedef struct nn_guard {
|
static bool nni_libcLock(void *_, mtx_t *lock, int action, int flags) {
|
||||||
mtx_t m;
|
if(action == NN_LOCK_INIT) {
|
||||||
} nn_guard;
|
mtx_init(lock, mtx_recursive);
|
||||||
|
} else if(action == NN_LOCK_DEINIT) {
|
||||||
|
mtx_destroy(lock);
|
||||||
|
} else if(action == NN_LOCK_RETAIN) {
|
||||||
|
if(flags & NN_LOCK_IMMEDIATE) {
|
||||||
|
return mtx_trylock(lock) == thrd_success;
|
||||||
|
}
|
||||||
|
return mtx_lock(lock);
|
||||||
|
} else if(action == NN_LOCK_RELEASE) {
|
||||||
|
mtx_unlock(lock);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
nn_guard *nn_newGuard(nn_Alloc *alloc) {
|
nn_LockManager nn_libcMutex() {
|
||||||
nn_guard *g = nn_alloc(alloc, sizeof(nn_guard));
|
nn_LockManager mgr = {};
|
||||||
|
mgr.lockSize = sizeof(mtx_t);
|
||||||
|
mgr.userdata = NULL;
|
||||||
|
mgr.proc = (nn_LockProc *)nni_libcLock;
|
||||||
|
return mgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool nni_noLock(void *_, void *__, int action, int flags) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_LockManager nn_noMutex() {
|
||||||
|
return (nn_LockManager) {
|
||||||
|
.userdata = NULL,
|
||||||
|
.lockSize = 0,
|
||||||
|
.proc = (nn_LockProc *)nni_noLock,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_guard *nn_newGuard(nn_Context *ctx) {
|
||||||
|
nn_guard *g = nn_alloc(&ctx->allocator, ctx->lockManager.lockSize);
|
||||||
if(g == NULL) return NULL;
|
if(g == NULL) return NULL;
|
||||||
mtx_init(&g->m, mtx_recursive);
|
ctx->lockManager.proc(ctx->lockManager.userdata, g, NN_LOCK_INIT, NN_LOCK_DEFAULT);
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_lock(nn_guard *guard) {
|
void nn_lock(nn_Context *context, nn_guard *guard) {
|
||||||
if(guard == NULL) return;
|
if(guard == NULL) return;
|
||||||
mtx_lock(&guard->m);
|
context->lockManager.proc(context->lockManager.userdata, guard, NN_LOCK_RETAIN, NN_LOCK_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_unlock(nn_guard *guard) {
|
bool nn_tryLock(nn_Context *context, nn_guard *guard) {
|
||||||
if(guard == NULL) return;
|
if(guard == NULL) return true;
|
||||||
mtx_unlock(&guard->m);
|
return context->lockManager.proc(context->lockManager.userdata, guard, NN_LOCK_RETAIN, NN_LOCK_IMMEDIATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_deleteGuard(nn_Alloc *alloc, nn_guard *guard) {
|
void nn_unlock(nn_Context *context, nn_guard *guard) {
|
||||||
if(guard == NULL) return;
|
if(guard == NULL) return;
|
||||||
mtx_destroy(&guard->m);
|
context->lockManager.proc(context->lockManager.userdata, guard, NN_LOCK_RELEASE, NN_LOCK_DEFAULT);
|
||||||
nn_dealloc(alloc, guard, sizeof(nn_guard));
|
}
|
||||||
|
|
||||||
|
void nn_deleteGuard(nn_Context *context, nn_guard *guard) {
|
||||||
|
if(guard == NULL) return;
|
||||||
|
context->lockManager.proc(context->lockManager.userdata, guard, NN_LOCK_DEINIT, NN_LOCK_DEFAULT);
|
||||||
|
nn_dealloc(&context->allocator, guard, context->lockManager.lockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_addRef(nn_refc *refc, size_t count) {
|
void nn_addRef(nn_refc *refc, size_t count) {
|
||||||
@ -37,8 +79,7 @@ void nn_incRef(nn_refc *refc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool nn_removeRef(nn_refc *refc, size_t count) {
|
bool nn_removeRef(nn_refc *refc, size_t count) {
|
||||||
(*refc) -= count;
|
return ((*refc) -= count) == 0;
|
||||||
return *refc == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nn_decRef(nn_refc *refc) {
|
bool nn_decRef(nn_refc *refc) {
|
||||||
|
@ -105,12 +105,46 @@ typedef struct nn_Alloc {
|
|||||||
nn_AllocProc *proc;
|
nn_AllocProc *proc;
|
||||||
} nn_Alloc;
|
} nn_Alloc;
|
||||||
|
|
||||||
|
#define NN_LOCK_DEFAULT 0
|
||||||
|
#define NN_LOCK_IMMEDIATE 1
|
||||||
|
|
||||||
|
#define NN_LOCK_INIT 0
|
||||||
|
#define NN_LOCK_DEINIT 1
|
||||||
|
#define NN_LOCK_RETAIN 2
|
||||||
|
#define NN_LOCK_RELEASE 3
|
||||||
|
|
||||||
|
typedef bool nn_LockProc(void *userdata, void *lock, int action, int flags);
|
||||||
|
|
||||||
|
typedef struct nn_LockManager {
|
||||||
|
void *userdata;
|
||||||
|
size_t lockSize;
|
||||||
|
nn_LockProc *proc;
|
||||||
|
} nn_LockManager;
|
||||||
|
|
||||||
|
typedef double nn_ClockProc(void *userdata);
|
||||||
|
|
||||||
|
typedef struct nn_Clock {
|
||||||
|
void *userdata;
|
||||||
|
nn_ClockProc *proc;
|
||||||
|
} nn_Clock;
|
||||||
|
|
||||||
|
typedef struct nn_Context {
|
||||||
|
nn_Alloc allocator;
|
||||||
|
nn_LockManager lockManager;
|
||||||
|
nn_Clock clock;
|
||||||
|
} nn_Context;
|
||||||
|
|
||||||
// TODO: write a bunch of utils so this *can* work on baremetal.
|
// TODO: write a bunch of utils so this *can* work on baremetal.
|
||||||
|
|
||||||
#ifndef NN_BAREMETAL
|
#ifndef NN_BAREMETAL
|
||||||
nn_Alloc nn_libcAllocator();
|
nn_Alloc nn_libcAllocator();
|
||||||
|
nn_Clock nn_libcRealTime();
|
||||||
|
nn_LockManager nn_libcMutex();
|
||||||
|
nn_Context nn_libcContext();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
nn_LockManager nn_noMutex();
|
||||||
|
|
||||||
// Values for architectures
|
// Values for architectures
|
||||||
|
|
||||||
#define NN_VALUE_INT 0
|
#define NN_VALUE_INT 0
|
||||||
@ -171,10 +205,11 @@ char *nn_strdup(nn_Alloc *alloc, const char *s);
|
|||||||
void *nn_memdup(nn_Alloc *alloc, const void *buf, size_t len);
|
void *nn_memdup(nn_Alloc *alloc, const void *buf, size_t len);
|
||||||
void nn_deallocStr(nn_Alloc *alloc, char *s);
|
void nn_deallocStr(nn_Alloc *alloc, char *s);
|
||||||
|
|
||||||
nn_guard *nn_newGuard(nn_Alloc *alloc);
|
nn_guard *nn_newGuard(nn_Context *context);
|
||||||
void nn_lock(nn_guard *guard);
|
void nn_lock(nn_Context *context, nn_guard *guard);
|
||||||
void nn_unlock(nn_guard *guard);
|
bool nn_tryLock(nn_Context *context, nn_guard *guard);
|
||||||
void nn_deleteGuard(nn_Alloc *alloc, nn_guard *guard);
|
void nn_unlock(nn_Context *context, nn_guard *guard);
|
||||||
|
void nn_deleteGuard(nn_Context *context, nn_guard *guard);
|
||||||
|
|
||||||
void nn_addRef(nn_refc *refc, size_t count);
|
void nn_addRef(nn_refc *refc, size_t count);
|
||||||
void nn_incRef(nn_refc *refc);
|
void nn_incRef(nn_refc *refc);
|
||||||
@ -201,17 +236,16 @@ unsigned int nn_unicode_lowerCodepoint(unsigned int codepoint);
|
|||||||
// returned string must be nn_deallocStr()'d
|
// returned string must be nn_deallocStr()'d
|
||||||
char *nn_unicode_lower(nn_Alloc *alloc, const char *s);
|
char *nn_unicode_lower(nn_Alloc *alloc, const char *s);
|
||||||
|
|
||||||
double nn_realTime();
|
|
||||||
double nn_realTimeClock(void *_);
|
|
||||||
|
|
||||||
typedef double nn_clock_t(void *_);
|
|
||||||
|
|
||||||
nn_universe *nn_newUniverse(nn_Alloc alloc);
|
nn_universe *nn_newUniverse(nn_Context context);
|
||||||
|
nn_Context *nn_getContext(nn_universe *universe);
|
||||||
nn_Alloc *nn_getAllocator(nn_universe *universe);
|
nn_Alloc *nn_getAllocator(nn_universe *universe);
|
||||||
|
nn_Clock *nn_getClock(nn_universe *universe);
|
||||||
|
nn_LockManager *nn_getLockManager(nn_universe *universe);
|
||||||
void nn_unsafeDeleteUniverse(nn_universe *universe);
|
void nn_unsafeDeleteUniverse(nn_universe *universe);
|
||||||
void *nn_queryUserdata(nn_universe *universe, const char *name);
|
void *nn_queryUserdata(nn_universe *universe, const char *name);
|
||||||
void nn_storeUserdata(nn_universe *universe, const char *name, void *data);
|
void nn_storeUserdata(nn_universe *universe, const char *name, void *data);
|
||||||
void nn_setClock(nn_universe *universe, nn_clock_t *clock, void *userdata);
|
|
||||||
double nn_getTime(nn_universe *universe);
|
double nn_getTime(nn_universe *universe);
|
||||||
|
|
||||||
nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit);
|
nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit);
|
||||||
@ -587,7 +621,7 @@ typedef struct nn_scrchr_t {
|
|||||||
bool isBgPalette;
|
bool isBgPalette;
|
||||||
} nn_scrchr_t;
|
} nn_scrchr_t;
|
||||||
|
|
||||||
nn_screen *nn_newScreen(nn_Alloc *alloc, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors);
|
nn_screen *nn_newScreen(nn_Context *context, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors);
|
||||||
nn_componentTable *nn_getScreenTable(nn_universe *universe);
|
nn_componentTable *nn_getScreenTable(nn_universe *universe);
|
||||||
|
|
||||||
void nn_retainScreen(nn_screen *screen);
|
void nn_retainScreen(nn_screen *screen);
|
||||||
|
@ -2,26 +2,24 @@
|
|||||||
#include "universe.h"
|
#include "universe.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
nn_universe *nn_newUniverse(nn_Alloc alloc) {
|
nn_universe *nn_newUniverse(nn_Context ctx) {
|
||||||
nn_universe *u = nn_alloc(&alloc, sizeof(nn_universe));
|
nn_universe *u = nn_alloc(&ctx.allocator, sizeof(nn_universe));
|
||||||
if(u == NULL) return u;
|
if(u == NULL) return u;
|
||||||
u->alloc = alloc;
|
u->ctx = ctx;
|
||||||
// we leave udata uninitialized because it does not matter
|
// we leave udata uninitialized because it does not matter
|
||||||
u->udataLen = 0;
|
u->udataLen = 0;
|
||||||
u->clockUserdata = NULL;
|
|
||||||
u->currentClock = nn_realTimeClock;
|
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
nn_Alloc *nn_getAllocator(nn_universe *universe) {
|
nn_Alloc *nn_getAllocator(nn_universe *universe) {
|
||||||
return &universe->alloc;
|
return &universe->ctx.allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_unsafeDeleteUniverse(nn_universe *universe) {
|
void nn_unsafeDeleteUniverse(nn_universe *universe) {
|
||||||
for(size_t i = 0; i < universe->udataLen; i++) {
|
for(size_t i = 0; i < universe->udataLen; i++) {
|
||||||
nn_deallocStr(&universe->alloc, universe->udata[i].name);
|
nn_deallocStr(&universe->ctx.allocator, universe->udata[i].name);
|
||||||
}
|
}
|
||||||
nn_dealloc(&universe->alloc, universe, sizeof(nn_universe));
|
nn_dealloc(&universe->ctx.allocator, universe, sizeof(nn_universe));
|
||||||
}
|
}
|
||||||
|
|
||||||
void *nn_queryUserdata(nn_universe *universe, const char *name) {
|
void *nn_queryUserdata(nn_universe *universe, const char *name) {
|
||||||
@ -37,7 +35,7 @@ void nn_storeUserdata(nn_universe *universe, const char *name, void *data) {
|
|||||||
if(universe->udataLen == NN_MAX_USERDATA) return; // prevent overflow
|
if(universe->udataLen == NN_MAX_USERDATA) return; // prevent overflow
|
||||||
|
|
||||||
size_t idx = universe->udataLen;
|
size_t idx = universe->udataLen;
|
||||||
char *allocName = nn_strdup(&universe->alloc, name);
|
char *allocName = nn_strdup(&universe->ctx.allocator, name);
|
||||||
if(allocName == NULL) return;
|
if(allocName == NULL) return;
|
||||||
|
|
||||||
universe->udata[idx].name = allocName;
|
universe->udata[idx].name = allocName;
|
||||||
@ -46,7 +44,7 @@ void nn_storeUserdata(nn_universe *universe, const char *name, void *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double nn_getTime(nn_universe *universe) {
|
double nn_getTime(nn_universe *universe) {
|
||||||
return universe->currentClock(universe->clockUserdata);
|
return universe->ctx.clock.proc(universe->ctx.clock.userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_loadCoreComponentTables(nn_universe *universe) {
|
void nn_loadCoreComponentTables(nn_universe *universe) {
|
||||||
|
@ -9,11 +9,9 @@ typedef struct nn_universe_udata {
|
|||||||
} nn_universe_udata;
|
} nn_universe_udata;
|
||||||
|
|
||||||
typedef struct nn_universe {
|
typedef struct nn_universe {
|
||||||
nn_Alloc alloc;
|
nn_Context ctx;
|
||||||
nn_universe_udata udata[NN_MAX_USERDATA];
|
nn_universe_udata udata[NN_MAX_USERDATA];
|
||||||
size_t udataLen;
|
size_t udataLen;
|
||||||
nn_clock_t *currentClock;
|
|
||||||
void *clockUserdata;
|
|
||||||
} nn_universe;
|
} nn_universe;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
38
src/utils.c
38
src/utils.c
@ -40,6 +40,8 @@ void nn_dealloc(nn_Alloc *alloc, void *memory, size_t size) {
|
|||||||
alloc->proc(alloc->userdata, memory, size, 0, NULL);
|
alloc->proc(alloc->userdata, memory, size, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NN_BAREMETAL
|
||||||
|
|
||||||
static void *nn_libcAllocProc(void *_, void *ptr, size_t oldSize, size_t newSize, void *__) {
|
static void *nn_libcAllocProc(void *_, void *ptr, size_t oldSize, size_t newSize, void *__) {
|
||||||
if(newSize == 0) {
|
if(newSize == 0) {
|
||||||
//printf("Freed %lu bytes from %p\n", oldSize, ptr);
|
//printf("Freed %lu bytes from %p\n", oldSize, ptr);
|
||||||
@ -59,6 +61,15 @@ nn_Alloc nn_libcAllocator() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nn_Context nn_libcContext() {
|
||||||
|
return (nn_Context) {
|
||||||
|
.allocator = nn_libcAllocator(),
|
||||||
|
.clock = nn_libcRealTime(),
|
||||||
|
.lockManager = nn_libcMutex(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Utilities, both internal and external
|
// Utilities, both internal and external
|
||||||
char *nn_strdup(nn_Alloc *alloc, const char *s) {
|
char *nn_strdup(nn_Alloc *alloc, const char *s) {
|
||||||
size_t l = strlen(s);
|
size_t l = strlen(s);
|
||||||
@ -78,17 +89,11 @@ void nn_deallocStr(nn_Alloc *alloc, char *s) {
|
|||||||
nn_dealloc(alloc, s, strlen(s)+1);
|
nn_dealloc(alloc, s, strlen(s)+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NN_BAREMETAL
|
#ifndef NN_BAREMETAL
|
||||||
|
|
||||||
double nn_realTime() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifdef NN_POSIX
|
#ifdef NN_POSIX
|
||||||
|
|
||||||
double nn_realTime() {
|
static double nni_realTime() {
|
||||||
struct timespec time;
|
struct timespec time;
|
||||||
if(clock_gettime(CLOCK_MONOTONIC, &time) < 0) return 0; // oh no
|
if(clock_gettime(CLOCK_MONOTONIC, &time) < 0) return 0; // oh no
|
||||||
return time.tv_sec + ((double)time.tv_nsec) / 1e9;
|
return time.tv_sec + ((double)time.tv_nsec) / 1e9;
|
||||||
@ -96,7 +101,7 @@ double nn_realTime() {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
double nn_realTime() {
|
static double nni_realTime() {
|
||||||
LARGE_INTEGER frequency = {0};
|
LARGE_INTEGER frequency = {0};
|
||||||
if(!QueryPerformanceFrequency(&frequency)) return 0;
|
if(!QueryPerformanceFrequency(&frequency)) return 0;
|
||||||
|
|
||||||
@ -108,12 +113,19 @@ double nn_realTime() {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
static double nni_realTimeClock(void *_) {
|
||||||
|
return nni_realTime();
|
||||||
double nn_realTimeClock(void *_) {
|
|
||||||
return nn_realTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nn_Clock nn_libcRealTime() {
|
||||||
|
return (nn_Clock) {
|
||||||
|
.userdata = NULL,
|
||||||
|
.proc = nni_realTimeClock,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO: use OKLAB the color space for more accurate results.
|
// TODO: use OKLAB the color space for more accurate results.
|
||||||
|
|
||||||
typedef struct nn_rgbColor {
|
typedef struct nn_rgbColor {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user