From 37b348ef13f141c2bc2cca1eac7870be0ab62189 Mon Sep 17 00:00:00 2001 From: IonutParau Date: Mon, 6 Jul 2026 17:00:32 +0200 Subject: [PATCH] made it work better for GC languages --- src/luaarch.c | 6 +++++- src/neonucleus.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ src/neonucleus.h | 15 ++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/luaarch.c b/src/luaarch.c index b97d08e..7adbcdc 100644 --- a/src/luaarch.c +++ b/src/luaarch.c @@ -792,7 +792,7 @@ static void luaArch_loadEnv(lua_State *L) { static nn_Exit luaArch_handler(nn_ArchitectureRequest *req) { nn_Computer *computer = req->computer; luaArch *arch = req->localState; - nn_Context *ctx = nn_getComputerContext(computer); + nn_Context *ctx = computer == NULL ? NULL : nn_getComputerContext(computer); // the memory scale, used to give Lua extra memory in 64-bit systems // due to it also using more memory. double memScale = sizeof(void *) > 4 ? 1.8 : 1; @@ -857,6 +857,10 @@ static nn_Exit luaArch_handler(nn_ArchitectureRequest *req) { case NN_ARCH_DESERIALIZE: // do nothing return NN_OK; + case NN_ARCH_RETAIN: + return NN_OK; + case NN_ARCH_DROP: + return NN_OK; } return NN_OK; } diff --git a/src/neonucleus.c b/src/neonucleus.c index 74e4853..062430c 100644 --- a/src/neonucleus.c +++ b/src/neonucleus.c @@ -1229,6 +1229,8 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char c->signalCount = 0; c->userCount = 0; c->idleTimestamp = 0; + c->arch.handler = NULL; + c->desiredArch.handler = NULL; // set to empty string c->errorBuffer[0] = '\0'; for(size_t i = 0; i < NN_MAX_USERDATA; i++) c->uservals[i].state = NULL; @@ -1314,9 +1316,29 @@ bool nn_isComputerOn(nn_Computer *computer) { } void nn_setComputerEnvironment(nn_Computer *computer, nn_Environment env) { + nn_retainComputerEnvironment(env); + nn_dropComputerEnvironment(computer->env); computer->env = env; } +void nn_retainComputerEnvironment(nn_Environment env) { + if(env.handler == NULL) return; + nn_EnvironmentRequest req; + req.userdata = env.userdata; + req.computer = NULL; + req.action = NN_ENV_RETAIN; + env.handler(&req); +} + +void nn_dropComputerEnvironment(nn_Environment env) { + if(env.handler == NULL) return; + nn_EnvironmentRequest req; + req.userdata = env.userdata; + req.computer = NULL; + req.action = NN_ENV_DROP; + env.handler(&req); +} + void nn_setDirectCost(nn_Computer *computer, double directCost) { computer->directCost = directCost; } @@ -1465,6 +1487,12 @@ void nn_destroyComputerN(nn_Computer *computer, size_t n) { for(size_t i = 0; i < computer->userCount; i++) { nn_strfree(ctx, computer->users[i]); } + + nn_dropArchitecture(computer->arch); + for(size_t i = 0; i < computer->archCount; i++) { + nn_dropArchitecture(computer->archs[i]); + } + nn_dropComputerEnvironment(computer->env); for(size_t i = 0; i < NN_MAX_USERDATA; i++) nn_freeUserdata(computer, i); @@ -1571,6 +1599,8 @@ bool nn_hasUser(nn_Computer *computer, const char *user) { } void nn_setArchitecture(nn_Computer *computer, const nn_Architecture *arch) { + nn_retainArchitecture(*arch); + nn_dropArchitecture(computer->arch); computer->arch = *arch; } @@ -1578,7 +1608,29 @@ nn_Architecture nn_getArchitecture(nn_Computer *computer) { return computer->arch; } +void nn_retainArchitecture(nn_Architecture arch) { + if(arch.handler == NULL) return; + nn_ArchitectureRequest req; + req.computer = NULL; + req.action = NN_ARCH_RETAIN; + req.globalState = arch.state; + req.localState = NULL; + arch.handler(&req); +} + +void nn_dropArchitecture(nn_Architecture arch) { + if(arch.handler == NULL) return; + nn_ArchitectureRequest req; + req.computer = NULL; + req.action = NN_ARCH_DROP; + req.globalState = arch.state; + req.localState = NULL; + arch.handler(&req); +} + void nn_setDesiredArchitecture(nn_Computer *computer, const nn_Architecture *arch) { + nn_retainArchitecture(*arch); + nn_dropArchitecture(computer->desiredArch); computer->desiredArch = *arch; } @@ -1588,6 +1640,7 @@ nn_Architecture nn_getDesiredArchitecture(nn_Computer *computer) { nn_Exit nn_addSupportedArchitecture(nn_Computer *computer, const nn_Architecture *arch) { if(computer->archCount == NN_MAX_ARCHITECTURES) return NN_ELIMIT; + nn_retainArchitecture(*arch); computer->archs[computer->archCount++] = *arch; return NN_OK; } diff --git a/src/neonucleus.h b/src/neonucleus.h index c8aa30a..a253f0e 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -354,6 +354,10 @@ typedef enum nn_ArchitectureAction { NN_ARCH_DESERIALIZE, // serialize to an encoded state, pushed it as a string NN_ARCH_SERIALIZE, + // information about usage, for GC languages to know when it is safe to reclaim references. + // computer and localState are both NULL when these are emitted. + NN_ARCH_RETAIN, + NN_ARCH_DROP, } nn_ArchitectureAction; typedef struct nn_ArchitectureRequest { @@ -423,6 +427,9 @@ typedef enum nn_EnvironmentAction { NN_ENV_CRASHED, NN_ENV_BEEP, NN_ENV_BEEPMORSE, + // information about usage, for GC languages to know when it is safe to reclaim references + NN_ENV_RETAIN, + NN_ENV_DROP, } nn_EnvironmentAction; typedef struct nn_EnvironmentRequest { @@ -473,6 +480,8 @@ void nn_forceCrashComputer(nn_Computer *computer, const char *s); // returns whether an architecture state is present bool nn_isComputerOn(nn_Computer *computer); void nn_setComputerEnvironment(nn_Computer *computer, nn_Environment env); +void nn_retainComputerEnvironment(nn_Environment env); +void nn_dropComputerEnvironment(nn_Environment env); void nn_setDirectCost(nn_Computer *computer, double directCost); double nn_getDirectCost(nn_Computer *computer); @@ -601,6 +610,12 @@ bool nn_hasUser(nn_Computer *computer, const char *user); void nn_setArchitecture(nn_Computer *computer, const nn_Architecture *arch); // Gets the current architecture. nn_Architecture nn_getArchitecture(nn_Computer *computer); +// Notify the architecture it is being retained. This is to help GC'd languages that provide architectures know +// when the garbage collector can safely reclaim the memory again. +void nn_retainArchitecture(nn_Architecture arch); +// Notify the architecture it is being dropped. This is to help GC'd languages that provide architectures know +// when the garbage collector can safely reclaim the memory again. +void nn_dropArchitecture(nn_Architecture arch); // Sets the computer's desired architecture. // The desired architecture indicates, when the computer state is CHARCH, what the new architecture should be. // This is set even if it is not in the supported architecture list, *you must check if it is in that list first.*