actors in C now
Some checks failed
Build and Deploy / package-dist (push) Blocked by required conditions
Build and Deploy / deploy-itch (push) Blocked by required conditions
Build and Deploy / deploy-gitea (push) Blocked by required conditions
Build and Deploy / build-linux (push) Successful in 1m15s
Build and Deploy / build-windows (CLANG64) (push) Failing after 11m46s
Some checks failed
Build and Deploy / package-dist (push) Blocked by required conditions
Build and Deploy / deploy-itch (push) Blocked by required conditions
Build and Deploy / deploy-gitea (push) Blocked by required conditions
Build and Deploy / build-linux (push) Successful in 1m15s
Build and Deploy / build-windows (CLANG64) (push) Failing after 11m46s
This commit is contained in:
@@ -31,10 +31,6 @@ if (os.trace)
|
||||
|
||||
var js = use_embed('js')
|
||||
|
||||
prosperon.on('exit', _ => {
|
||||
os.mailbox_destroy(prosperon.id);
|
||||
})
|
||||
|
||||
prosperon.on('SIGINT', function() {
|
||||
os.exit(1)
|
||||
})
|
||||
@@ -206,7 +202,7 @@ console.assert = function(op, str = `assertion failed [value '${op}']`) {
|
||||
if (!op) console.panic(str)
|
||||
}
|
||||
|
||||
os.on('uncaught_exception', function(e) { console.error(e) })
|
||||
//os.on('uncaught_exception', function(e) { console.log("HERRE!"); console.error(e); })
|
||||
|
||||
console[prosperon.DOC] = {
|
||||
doc: "The console object provides various logging, debugging, and output methods.",
|
||||
@@ -727,7 +723,7 @@ $_.start = function(cb, prg, arg) {
|
||||
if (prg) argv = argv.concat(['--program', prg])
|
||||
if (arg) argv = argv.concat(cmd.encode(arg))
|
||||
underlings.add(id)
|
||||
os.createthread(argv)
|
||||
os.createactor(argv)
|
||||
}
|
||||
$_.start[prosperon.DOC] = "The start function creates a new actor..."
|
||||
|
||||
@@ -758,12 +754,9 @@ $_.unneeded = function(fn, seconds = ar) {
|
||||
}
|
||||
$_.unneeded[prosperon.DOC] = "registers a function that is called when the actor..."
|
||||
|
||||
var timers = []
|
||||
var timer_id = 0
|
||||
|
||||
$_.delay = function(fn, seconds) {
|
||||
var id = os.os.addtimer(prosperon.id, fn, seconds);
|
||||
return function() { os.removetimer(id); }
|
||||
var id = os.addtimer(prosperon.id, fn, seconds);
|
||||
return function() { os.removetimer(prosperon.id, id); }
|
||||
}
|
||||
$_.delay[prosperon.DOC] = "used to schedule the invocation of a function..."
|
||||
|
||||
@@ -843,6 +836,8 @@ cmd.process(prosperon.argv)
|
||||
if (!prosperon.args.id) prosperon.id = util.guid()
|
||||
else prosperon.id = prosperon.args.id
|
||||
|
||||
os.register_actor(prosperon.id, handle_local);
|
||||
|
||||
tracy.thread_name(prosperon.id)
|
||||
|
||||
$_.__ACTORDATA__.id = prosperon.id
|
||||
@@ -851,13 +846,9 @@ if (prosperon.args.overling) overling = { __ACTORDATA__: {id: prosperon.args.ove
|
||||
if (prosperon.args.root) root = json.decode(prosperon.args.root)
|
||||
else root = $_
|
||||
|
||||
os.mailbox_start(prosperon.id)
|
||||
|
||||
if (overling) actor_send(overling, {type:'greet', id: prosperon.id})
|
||||
if (prosperon.args.program) actor.spawn(prosperon.args.program)
|
||||
|
||||
var unneeded_timer = $_.delay($_.stop, ar)
|
||||
|
||||
function destroyself() {
|
||||
console.log(`Got the message to destroy self.`)
|
||||
if (overling) actor_send(overling, { type: "stopped", id: prosperon.id })
|
||||
@@ -876,10 +867,12 @@ function handle_actor_disconnect(id) {
|
||||
}
|
||||
|
||||
function handle_local(msg) {
|
||||
console.log("LOCAL MESSAGE");
|
||||
handle_message(wota.decode(msg))
|
||||
}
|
||||
|
||||
function handle_message(msg) {
|
||||
console.log(`message was ${json.encode(msg)}`)
|
||||
if (msg.target) {
|
||||
if (msg.target !== prosperon.id) {
|
||||
os.mailbox_push(msg.target, wota.encode(msg))
|
||||
@@ -932,24 +925,6 @@ function handle_message(msg) {
|
||||
unneeded_timer = $_.delay(unneeded_fn, unneeded_time)
|
||||
}
|
||||
|
||||
var hang = 0.1
|
||||
var last_t = os.now()
|
||||
|
||||
var doexit = false
|
||||
while (!doexit) {
|
||||
if (portal) portal.service(handle_host, hang)
|
||||
if (contactor) contactor.service(handle_host, hang)
|
||||
os.mailbox_service(prosperon.id, handle_local, hang)
|
||||
var elapsed = os.now() - last_t
|
||||
last_t = os.now()
|
||||
for (var i in timers) {
|
||||
var t = timers[i]
|
||||
t.seconds -= elapsed
|
||||
if (t.seconds <= 0) {
|
||||
t.fn()
|
||||
delete timers[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
var unneeded_timer = $_.delay($_.stop, ar)
|
||||
|
||||
})()
|
||||
|
||||
374
source/jsffi.c
374
source/jsffi.c
@@ -23,10 +23,10 @@
|
||||
#include "par/par_shapes.h"
|
||||
#include <stdint.h>
|
||||
#include "timer.h"
|
||||
#include <signal.h>
|
||||
#include "cute_aseprite.h"
|
||||
#include "cgltf.h"
|
||||
#include "physfs.h"
|
||||
#include "prosperon.h"
|
||||
|
||||
#include "qjs_dmon.h"
|
||||
#include "qjs_nota.h"
|
||||
@@ -2483,9 +2483,6 @@ JSC_CCALL(os_engine_start,
|
||||
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_URL_STRING, url)
|
||||
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_TYPE_STRING, type)
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_CAMERA))
|
||||
return JS_ThrowReferenceError(js, "Couldn't initialize SDL: %s\n", SDL_GetError());
|
||||
|
||||
const char *title;
|
||||
JS_GETPROP(js,title,argv[0],title,cstring)
|
||||
|
||||
@@ -6505,20 +6502,56 @@ JSC_CCALL(os_value_id,
|
||||
return number2js(js,(intptr_t)JS_VALUE_GET_PTR(self));
|
||||
)
|
||||
|
||||
static double gc_t = 0;
|
||||
static double gc_mem = 0;
|
||||
static double gc_startmem = 0;
|
||||
void script_report_gc_time(double t, double startmem, double mem)
|
||||
{
|
||||
gc_t = t;
|
||||
gc_mem = mem;
|
||||
gc_startmem = startmem;
|
||||
}
|
||||
JSC_SSCALL(os_eval,
|
||||
ret = JS_Eval(js, str2, strlen(str2), str, JS_EVAL_FLAG_STRICT);
|
||||
)
|
||||
|
||||
JSC_SSCALL(os_eval, ret = script_eval(js,str, str2))
|
||||
JSC_CCALL(os_make_timer, return timer2js(js,timer_make(js,argv[0])))
|
||||
JSC_CCALL(os_update_timers, timer_update(js, js2number(js,argv[0])))
|
||||
|
||||
Uint32 timer_cb(prosperon_rt *actor, SDL_TimerID id, Uint32 interval)
|
||||
{
|
||||
int idx = hmgeti(actor->timers, id);
|
||||
if (idx == -1) return 0;
|
||||
|
||||
SDL_LockMutex(actor->mutex);
|
||||
JSValue cb = actor->timers[idx].value;
|
||||
hmdel(actor->timers, id);
|
||||
arrput(actor->events, cb);
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
|
||||
actor_signal(actor);
|
||||
}
|
||||
|
||||
JSC_CCALL(os_addtimer,
|
||||
char *guid = JS_ToCString(js,argv[0]);
|
||||
prosperon_rt *actor = get_actor(guid);
|
||||
JS_FreeCString(js, guid);
|
||||
if (!actor) return JS_ThrowInternalError(js, "Could not get actor from guid.");
|
||||
|
||||
Uint64 ns = js2number(js,argv[2]) * 1000000000.0f;
|
||||
Uint32 id = SDL_AddTimerNS(ns, timer_cb, actor);
|
||||
|
||||
// appropriately add it to the actor
|
||||
SDL_LockMutex(actor->mutex);
|
||||
hmput(actor->timers, id, JS_DupValue(js,argv[1]));
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_removetimer,
|
||||
char *guid = JS_ToCString(js,argv[0]);
|
||||
prosperon_rt *actor = get_actor(guid);
|
||||
JS_FreeCString(js, guid);
|
||||
if (!actor) return JS_ThrowInternalError(js, "Could not get actor from guid.");
|
||||
|
||||
Uint32 timer_id = js2number(js,argv[1]);
|
||||
SDL_RemoveTimer(timer_id);
|
||||
|
||||
SDL_LockMutex(actor->mutex);
|
||||
hmdel(actor->timers, timer_id);
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
)
|
||||
|
||||
// input: (encoded image data of jpg, png, bmp, tiff)
|
||||
JSC_CCALL(os_make_texture,
|
||||
size_t len;
|
||||
@@ -6956,8 +6989,9 @@ JSC_CCALL(os_rects_to_sprites,
|
||||
)
|
||||
|
||||
JSC_CCALL(os_on,
|
||||
JSValue *onexp = SDL_GetTLS(&on_exception);
|
||||
*onexp = JS_DupValue(js,argv[1]);
|
||||
prosperon_rt *rt = JS_GetContextOpaque(js);
|
||||
JS_FreeValue(js, rt->on_exception);
|
||||
rt->on_exception = JS_DupValue(js,argv[1]);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_clean_transforms,
|
||||
@@ -7086,83 +7120,30 @@ JSC_CCALL(os_createprocess,
|
||||
return JS_ThrowReferenceError(js, "Unable to create process: %s\n", SDL_GetError());
|
||||
)
|
||||
|
||||
typedef struct {
|
||||
int argc;
|
||||
char **argv;
|
||||
} cmdargs;
|
||||
JSC_CCALL(os_createactor,
|
||||
int margc = JS_ArrayLength(js, argv[0]);
|
||||
|
||||
int create_new_runtime(cmdargs *data)
|
||||
{
|
||||
script_startup(data->argc, data->argv);
|
||||
for (int i = 0; i < data->argc; i++) free(data->argv[i]);
|
||||
free(data->argv);
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
char **margv = malloc(margc*sizeof(char*));
|
||||
|
||||
JSC_CCALL(os_createthread,
|
||||
cmdargs *cmd = malloc(sizeof(cmdargs));
|
||||
if (!cmd) return JS_ThrowInternalError(js, "Out of memory");
|
||||
cmd->argc = JS_ArrayLength(js, argv[0]);
|
||||
cmd->argv = (char **)calloc(cmd->argc, sizeof(char *));
|
||||
if (!cmd->argv) {
|
||||
free(cmd);
|
||||
return JS_ThrowInternalError(js, "Out of memory");
|
||||
}
|
||||
for (int i = 0; i < cmd->argc; i++) {
|
||||
for (int i = 0; i < margc; i++) {
|
||||
JSValue val = JS_GetPropertyUint32(js, argv[0], i);
|
||||
if (JS_IsException(val)) {
|
||||
for (int j = 0; j < i; j++) free(cmd->argv[j]);
|
||||
free(cmd->argv);
|
||||
free(cmd);
|
||||
return val;
|
||||
}
|
||||
const char *str = JS_ToCString(js, val);
|
||||
if (!str) {
|
||||
for (int j = 0; j < i; j++) free(cmd->argv[j]);
|
||||
free(cmd->argv);
|
||||
free(cmd);
|
||||
JS_FreeValue(js, val);
|
||||
return JS_ThrowInternalError(js, "Could not convert argument to string");
|
||||
}
|
||||
cmd->argv[i] = strdup(str);
|
||||
JS_FreeCString(js, str);
|
||||
JS_FreeValue(js, val);
|
||||
char *cstr = JS_ToCString(js,val);
|
||||
margv[i] = strdup(cstr);
|
||||
JS_FreeCString(js,cstr);
|
||||
JS_FreeValue(js,val);
|
||||
}
|
||||
SDL_Thread *thread = SDL_CreateThread(create_new_runtime, "newrt", cmd);
|
||||
if (!thread) {
|
||||
for (int i = 0; i < cmd->argc; i++) free(cmd->argv[i]);
|
||||
free(cmd->argv);
|
||||
free(cmd);
|
||||
return JS_ThrowInternalError(js, "Could not create a new thread: %s", SDL_GetError());
|
||||
}
|
||||
SDL_DetachThread(thread);
|
||||
return JS_UNDEFINED;
|
||||
|
||||
create_actor(margc, margv);
|
||||
)
|
||||
|
||||
struct message {
|
||||
void *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
typedef struct mailbox {
|
||||
SDL_Mutex *mutex;
|
||||
SDL_Condition *cond;
|
||||
struct message *messages;
|
||||
} mailbox;
|
||||
|
||||
static struct { char *key; mailbox value; } *mailboxes = NULL;
|
||||
static SDL_Mutex *mailboxes_mutex = NULL;
|
||||
|
||||
JSC_CCALL(os_mailbox_push,
|
||||
if (argc < 2) return JS_ThrowInternalError(js, "Need an actor and a message");
|
||||
if (!JS_IsArrayBuffer(js, argv[1])) return JS_ThrowInternalError(js, "Object to push must be an array buffer");
|
||||
|
||||
const char *id = JS_ToCString(js, argv[0]);
|
||||
int mailbox_index = shgeti(mailboxes, id);
|
||||
JS_FreeCString(js, id);
|
||||
|
||||
if (mailbox_index == -1) return JS_ThrowInternalError(js, "No mailbox found for given ID");
|
||||
prosperon_rt *target = get_actor(id);
|
||||
if (!target)
|
||||
return JS_ThrowInternalError(js, "No mailbox found for given ID");
|
||||
|
||||
size_t size;
|
||||
uint8_t *buf = JS_GetArrayBuffer(js, &size, argv[1]);
|
||||
@@ -7173,116 +7154,41 @@ JSC_CCALL(os_mailbox_push,
|
||||
|
||||
memcpy(data, buf, size);
|
||||
|
||||
mailbox *mb = &mailboxes[mailbox_index].value;
|
||||
SDL_LockMutex(mb->mutex);
|
||||
struct message msg = {data, size};
|
||||
arrput(mb->messages, msg);
|
||||
SDL_SignalCondition(mb->cond); // Signal waiting threads
|
||||
SDL_UnlockMutex(mb->mutex);
|
||||
send_message(target, msg);
|
||||
)
|
||||
|
||||
void js_dofree(JSRuntime *rt, void *opaque, void *ptr)
|
||||
{
|
||||
js_free_rt(rt, ptr);
|
||||
}
|
||||
|
||||
JSC_CCALL(os_mailbox_service,
|
||||
if (!JS_IsFunction(js, argv[1])) return JS_ThrowInternalError(js, "Arg 2 must be a function");
|
||||
if (argc < 3 || !JS_IsNumber(argv[2])) return JS_ThrowInternalError(js, "Arg 3 must be a number (timeout in seconds)");
|
||||
|
||||
const char *id = JS_ToCString(js, argv[0]);
|
||||
int mb_index = shgeti(mailboxes, id);
|
||||
JS_FreeCString(js, id);
|
||||
|
||||
if (mb_index == -1) return JS_ThrowInternalError(js, "No mailbox found for given ID");
|
||||
|
||||
// Get timeout in seconds and convert to milliseconds
|
||||
int32_t timeout_seconds;
|
||||
if (JS_ToInt32(js, &timeout_seconds, argv[2]) != 0) return JS_ThrowInternalError(js, "Invalid timeout value");
|
||||
int timeout_ms = timeout_seconds * 1000; // Convert to milliseconds for SDL
|
||||
|
||||
mailbox *mb = &mailboxes[mb_index].value;
|
||||
struct message *temp = NULL;
|
||||
SDL_LockMutex(mb->mutex);
|
||||
|
||||
// Wait for messages if the mailbox is empty
|
||||
while (arrlen(mb->messages) == 0) {
|
||||
bool signaled = SDL_WaitConditionTimeout(mb->cond, mb->mutex, timeout_ms);
|
||||
if (!signaled) { // Timeout occurred
|
||||
SDL_UnlockMutex(mb->mutex);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
// Process messages after wait
|
||||
int count = arrlen(mb->messages);
|
||||
if (count > 0) {
|
||||
arrsetlen(temp, count);
|
||||
memcpy(temp, mb->messages, sizeof(*mb->messages) * count);
|
||||
arrsetlen(mb->messages, 0);
|
||||
}
|
||||
SDL_UnlockMutex(mb->mutex);
|
||||
|
||||
if (count == 0) return JS_UNDEFINED;
|
||||
|
||||
JSValue fn = JS_DupValue(js, argv[1]);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
JSValue arg = JS_NewArrayBuffer(js, temp[i].data, temp[i].size, js_dofree, NULL, 0);
|
||||
JSValue call = JS_Call(js, fn, JS_UNDEFINED, 1, &arg);
|
||||
uncaught_exception(js, call);
|
||||
JS_FreeValue(js, arg);
|
||||
}
|
||||
|
||||
arrfree(temp);
|
||||
JS_FreeValue(js, fn);
|
||||
JSC_CCALL(os_register_actor,
|
||||
printf("calling registera ctor for context %p\n", js);
|
||||
prosperon_rt *rt = JS_GetContextOpaque(js);
|
||||
printf("context after get_opaque: %p\n", js);
|
||||
char *id = JS_ToCString(js, argv[0]);
|
||||
printf("context after get_id: %p\n", js);
|
||||
char *err = register_actor(id, rt);
|
||||
printf("context after register_actor: %p\n", js);
|
||||
if (err) return JS_ThrowInternalError(js, "Could not register actor: %s", err);
|
||||
rt->message_handle = JS_DupValue(js, argv[1]);
|
||||
printf("context after dup_value: %p\n", js);
|
||||
const char *fnstr = JS_ToCString(js, rt->message_handle);
|
||||
printf("context after get_fnstr: %p\n", js);
|
||||
printf("registered %s\n", fnstr);
|
||||
JS_FreeCString(js, fnstr);
|
||||
rt->context = js;
|
||||
printf("jsvalue is in context %p\n", js);
|
||||
int tag = JS_VALUE_GET_TAG(rt->message_handle);
|
||||
printf("message_handle tag: %d\n", tag);
|
||||
if (tag == 0) printf(" as int: %d\n", JS_VALUE_GET_INT(rt->message_handle));
|
||||
else printf(" as ptr: %p\n", JS_VALUE_GET_PTR(rt->message_handle));
|
||||
|
||||
)
|
||||
|
||||
JSC_CCALL(os_mailbox_exist,
|
||||
const char *id = JS_ToCString(js, argv[0]);
|
||||
bool exists = shgeti(mailboxes, id) != -1;
|
||||
JS_FreeCString(js, id);
|
||||
return JS_NewBool(js, exists);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_mailbox_start,
|
||||
const char *id = JS_ToCString(js, argv[0]);
|
||||
mailbox mb;
|
||||
mb.mutex = SDL_CreateMutex();
|
||||
mb.cond = SDL_CreateCondition();
|
||||
mb.messages = NULL;
|
||||
if (!mailboxes_mutex) mailboxes_mutex = SDL_CreateMutex();
|
||||
|
||||
SDL_LockMutex(mailboxes_mutex);
|
||||
shput(mailboxes, id, mb);
|
||||
SDL_UnlockMutex(mailboxes_mutex);
|
||||
JS_FreeCString(js, id);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_mailbox_destroy,
|
||||
if (argc < 1) return JS_ThrowInternalError(js, "Need an actor/mailbox ID to destroy");
|
||||
|
||||
const char *id = JS_ToCString(js, argv[0]);
|
||||
int mailbox_index = shgeti(mailboxes, id);
|
||||
prosperon_rt *actor = get_actor(id);
|
||||
printf("actor from %s is %p\n", id, actor);
|
||||
JS_FreeCString(js, id);
|
||||
|
||||
if (mailbox_index != -1) {
|
||||
mailbox *mb = &mailboxes[mailbox_index].value;
|
||||
SDL_LockMutex(mb->mutex);
|
||||
|
||||
int count = arrlen(mb->messages);
|
||||
for (int i = 0; i < count; i++)
|
||||
js_free_rt(JS_GetRuntime(js), mb->messages[i].data);
|
||||
arrfree(mb->messages);
|
||||
SDL_UnlockMutex(mb->mutex);
|
||||
|
||||
SDL_DestroyMutex(mb->mutex);
|
||||
SDL_DestroyCondition(mb->cond);
|
||||
|
||||
SDL_LockMutex(mailboxes_mutex);
|
||||
shdel(mailboxes, id);
|
||||
SDL_UnlockMutex(mailboxes_mutex);
|
||||
}
|
||||
return JS_NewBool(js, actor ? 1 : 0);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_waitevent,
|
||||
@@ -7317,50 +7223,10 @@ JSValue js_os_set_trace(JSContext *js, JSValue self, JSValue value)
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *timer_id; // Unique timer identifier
|
||||
char *mailbox_id; // Mailbox to send the message to
|
||||
} timer_data;
|
||||
|
||||
typedef struct {
|
||||
char *timer_id; // Timer ID
|
||||
JSValue fn; // Function to invoke
|
||||
} timer_mapping;
|
||||
|
||||
static timer_mapping *timers = NULL; // Dynamic array of timer mappings
|
||||
static SDL_Mutex *timers_mutex = NULL; // Mutex for thread-safe access to timers
|
||||
|
||||
void init_timers(void)
|
||||
{
|
||||
if (!timers_mutex) timers_mutex = SDL_CreateMutex();
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
JSValue fn;
|
||||
const char *id;
|
||||
} timer_cb;
|
||||
|
||||
JSC_CCALL(os_addtimer,
|
||||
|
||||
Uint64 ns = js2number(js,argv[1])*1000000000.0;
|
||||
timer_cb cb;
|
||||
cb.fn = JS_DupValue(js,argv[0]);
|
||||
cb.id = JS_ToCString(js,argv[2]);
|
||||
|
||||
|
||||
)
|
||||
|
||||
JSC_CCALL(os_removetimer,
|
||||
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, make_transform, 0),
|
||||
MIST_FUNC_DEF(os, clean_transforms, 0),
|
||||
|
||||
MIST_FUNC_DEF(os, addtimer, 3),
|
||||
MIST_FUNC_DEF(os, removetimer, 1),
|
||||
|
||||
MIST_FUNC_DEF(os, platform, 0),
|
||||
MIST_FUNC_DEF(os, arch, 0),
|
||||
MIST_FUNC_DEF(os, totalmem, 0),
|
||||
@@ -7394,14 +7260,14 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, env, 1),
|
||||
MIST_FUNC_DEF(os, system, 1),
|
||||
MIST_FUNC_DEF(os, createprocess, 0),
|
||||
MIST_FUNC_DEF(os, createactor, 1),
|
||||
MIST_FUNC_DEF(os, waitevent, 2),
|
||||
|
||||
MIST_FUNC_DEF(os, mailbox_push, 2),
|
||||
MIST_FUNC_DEF(os, mailbox_service, 2),
|
||||
MIST_FUNC_DEF(os, mailbox_start, 1),
|
||||
MIST_FUNC_DEF(os, mailbox_exist, 1),
|
||||
MIST_FUNC_DEF(os, mailbox_destroy, 1),
|
||||
MIST_FUNC_DEF(os, createthread, 1),
|
||||
MIST_FUNC_DEF(os, addtimer, 3),
|
||||
MIST_FUNC_DEF(os, removetimer, 2),
|
||||
MIST_FUNC_DEF(os, register_actor, 2),
|
||||
};
|
||||
|
||||
JSC_CCALL(js_dump_class, return js_get_object_class_distribution(js))
|
||||
@@ -7750,41 +7616,6 @@ JSValue js_miniz_use(JSContext *js);
|
||||
JSValue js_tracy_use(JSContext *js);
|
||||
#endif
|
||||
|
||||
static void signal_handler(int sig) {
|
||||
const char *str = NULL;
|
||||
switch(sig) {
|
||||
case SIGABRT:
|
||||
str = "SIGABRT";
|
||||
break;
|
||||
case SIGFPE:
|
||||
str = "SIGFPE";
|
||||
break;
|
||||
case SIGILL:
|
||||
str = "SIGILL";
|
||||
break;
|
||||
case SIGINT:
|
||||
str = "SIGINT";
|
||||
break;
|
||||
case SIGSEGV:
|
||||
str = "SIGSEGV";
|
||||
break;
|
||||
case SIGTERM:
|
||||
str = "SIGTERM";
|
||||
break;
|
||||
}
|
||||
if (!str) return;
|
||||
|
||||
JSContext *js = SDL_GetTLS(&js_id);
|
||||
|
||||
script_evalf(js, "prosperon.dispatch('%s')", str);
|
||||
}
|
||||
|
||||
static void exit_handler()
|
||||
{
|
||||
// JSContext *js = SDL_GetTLS(&js_id);
|
||||
// script_evalf(js, "prosperon.dispatch('exit')");
|
||||
}
|
||||
|
||||
#include "monocypher.h"
|
||||
|
||||
// randombytes.c - Minimal cross-platform CSPRNG shim (single file)
|
||||
@@ -8019,9 +7850,10 @@ JSValue js_imgui_use(JSContext *js);
|
||||
|
||||
#define MISTLINE(NAME) (ModuleEntry){#NAME, js_##NAME##_use}
|
||||
|
||||
void ffi_load(JSContext *js, int argc, char **argv) {
|
||||
prosperon_rt *rt = calloc(1,sizeof(*rt));
|
||||
JS_SetContextOpaque(js, rt);
|
||||
void ffi_load(JSContext *js)
|
||||
{
|
||||
prosperon_rt *rt = JS_GetContextOpaque(js);
|
||||
|
||||
m_seedRand(&rt->mrand, time(NULL));
|
||||
|
||||
arrput(rt->module_registry, MISTLINE(io));
|
||||
@@ -8114,15 +7946,9 @@ void ffi_load(JSContext *js, int argc, char **argv) {
|
||||
JS_FreeValue(js,jsnumber);
|
||||
JS_FreeValue(js,number_proto);
|
||||
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGSEGV, signal_handler);
|
||||
signal(SIGABRT, signal_handler);
|
||||
atexit(exit_handler);
|
||||
|
||||
JSValue args = JS_NewArray(js);
|
||||
for (int i = 0; i < argc; i++)
|
||||
JS_SetPropertyUint32(js,args, i, JS_NewString(js,argv[i]));
|
||||
for (int i = 0; i < rt->cmd.argc; i++)
|
||||
JS_SetPropertyUint32(js,args, i, JS_NewString(js,rt->cmd.argv[i]));
|
||||
|
||||
JS_SetPropertyStr(js,prosp,"argv", args);
|
||||
JS_SetPropertyStr(js,prosp, "version", JS_NewString(js,PROSPERON_VERSION));
|
||||
@@ -8130,6 +7956,4 @@ void ffi_load(JSContext *js, int argc, char **argv) {
|
||||
JS_SetPropertyStr(js,prosp,"engine_start", JS_NewCFunction(js,js_os_engine_start, "engine_start", 1));
|
||||
|
||||
JS_FreeValue(js,globalThis);
|
||||
|
||||
SDL_Init(SDL_INIT_EVENTS);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#ifndef FFI_H
|
||||
#define FFI_H
|
||||
|
||||
#include <quickjs.h>
|
||||
void ffi_load(JSContext *js, int argc, char **argv);
|
||||
void ffi_load(JSContext *js);
|
||||
int js_print_exception(JSContext *js, JSValue v);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,10 +4,26 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "stb_ds.h"
|
||||
|
||||
#include "prosperon.h"
|
||||
#include "jsffi.h"
|
||||
|
||||
static prosperon_rt **ready_queue = NULL;
|
||||
static prosperon_rt **slow_queue = NULL; // Slow actors
|
||||
static prosperon_rt **reclaim_queue = NULL; // Actors needing reclamation
|
||||
static SDL_Mutex *queue_mutex = NULL; // Protects queue access
|
||||
static SDL_Condition *queue_cond = NULL; // Signals when work is available
|
||||
|
||||
static struct { char *key; prosperon_rt *value } *actors;
|
||||
|
||||
static unsigned char *zip_buffer_global;
|
||||
static char *prosperon;
|
||||
|
||||
SDL_ThreadID main_thread = 0;
|
||||
|
||||
void free_zip(void)
|
||||
{
|
||||
free(zip_buffer_global);
|
||||
@@ -92,7 +108,179 @@ if (!ret) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void free_actor(prosperon_rt *actor)
|
||||
{
|
||||
for (int i = 0; i < actor->cmd.argc; i++) free(actor->cmd.argv[i]);
|
||||
script_stop(actor->context);
|
||||
JSRuntime *rt = JS_GetRuntime(actor->context);
|
||||
arrfree(actor->messages);
|
||||
SDL_DestroyMutex(actor->mutex);
|
||||
arrfree(actor->js_swapchains);
|
||||
arrfree(actor->module_registry);
|
||||
free(actor);
|
||||
}
|
||||
|
||||
// this function should be called to spin off a new thread with actor
|
||||
prosperon_rt *create_actor(int argc, char **argv)
|
||||
{
|
||||
prosperon_rt *rt = calloc(sizeof(*rt),1);
|
||||
rt->cmd.argc = argc;
|
||||
rt->cmd.argv = argv;
|
||||
rt->cycle_fn = JS_UNDEFINED;
|
||||
rt->idx_buffer = JS_UNDEFINED;
|
||||
|
||||
script_startup(rt);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
void js_dofree(JSRuntime *rt, void *opaque, void *ptr)
|
||||
{
|
||||
js_free_rt(rt, ptr);
|
||||
}
|
||||
|
||||
void run_actor_turn(prosperon_rt *actor)
|
||||
{
|
||||
SDL_LockMutex(actor->mutex);
|
||||
if (actor->state != ACTOR_READY) goto END;
|
||||
if (arrlen(actor->messages) == 0) {
|
||||
actor->state = ACTOR_IDLE;
|
||||
goto END;
|
||||
}
|
||||
struct message msg = actor->messages[0];
|
||||
arrdel(actor->messages, 0);
|
||||
JSValue arg = JS_NewArrayBuffer(actor->context, msg.data, msg.size, js_dofree, NULL, 0);
|
||||
printf("running actor %p, fn? %d. context %p\n", actor, JS_IsFunction(actor->context, actor->message_handle), actor->context);
|
||||
int tag = JS_VALUE_GET_TAG(actor->message_handle);
|
||||
printf("message_handle tag: %d, value: %llu\n", tag, actor->message_handle);
|
||||
if (tag >= 0) printf(" as ptr: %p\n", JS_VALUE_GET_PTR(actor->message_handle));
|
||||
JSValue fstr = JS_ToString(actor->context, actor->message_handle);
|
||||
const char *fnstr = JS_ToCString(actor->context, fstr);
|
||||
printf("function is %s\n", fnstr ? fnstr : "(null)");
|
||||
JS_FreeCString(actor->context, fnstr);
|
||||
JSValue result = JS_Call(actor->context, actor->message_handle, JS_UNDEFINED, 1, &arg);
|
||||
printf("exception? %d\n", JS_IsException(result));
|
||||
if (JS_IsException(result)) {
|
||||
JSValue exception = JS_GetException(actor->context);
|
||||
const char *err_str = JS_ToCString(actor->context, exception);
|
||||
printf("exception details: %s\n", err_str ? err_str : "(null)");
|
||||
JS_FreeCString(actor->context, err_str);
|
||||
JS_FreeValue(actor->context, exception);
|
||||
}
|
||||
uncaught_exception(actor->context, result);
|
||||
printf("ran actor %p\n", actor);
|
||||
END:
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
}
|
||||
|
||||
int reclaimer_thread(void *data)
|
||||
{
|
||||
while (true) {
|
||||
SDL_LockMutex(queue_mutex);
|
||||
while (arrlen(reclaim_queue) == 0)
|
||||
SDL_WaitCondition(queue_cond, queue_mutex);
|
||||
|
||||
prosperon_rt *actor = reclaim_queue[0];
|
||||
arrdel(reclaim_queue, 0);
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
|
||||
SDL_LockMutex(actor->mutex);
|
||||
if (actor->state == ACTOR_EXHAUSTED) {
|
||||
actor->state = ACTOR_RECLAIMING;
|
||||
JS_RunGC(JS_GetRuntime(actor->context));
|
||||
}
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
|
||||
actor_signal(actor);
|
||||
}
|
||||
}
|
||||
|
||||
int crank_actor()
|
||||
{
|
||||
while (true) {
|
||||
prosperon_rt *actor = NULL;
|
||||
SDL_LockMutex(queue_mutex);
|
||||
if (arrlen(ready_queue) > 0) {
|
||||
actor = ready_queue[0];
|
||||
arrdel(ready_queue, 0);
|
||||
} else if (arrlen(slow_queue) > 0) {
|
||||
actor = slow_queue[0];
|
||||
arrdel(slow_queue, 0);
|
||||
} else {
|
||||
SDL_WaitCondition(queue_cond, queue_mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
if (actor)
|
||||
run_actor_turn(actor);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void signal_handler(int sig) {
|
||||
const char *str = NULL;
|
||||
switch(sig) {
|
||||
case SIGABRT:
|
||||
str = "SIGABRT";
|
||||
break;
|
||||
case SIGFPE:
|
||||
str = "SIGFPE";
|
||||
break;
|
||||
case SIGILL:
|
||||
str = "SIGILL";
|
||||
break;
|
||||
case SIGINT:
|
||||
str = "SIGINT";
|
||||
break;
|
||||
case SIGSEGV:
|
||||
str = "SIGSEGV";
|
||||
break;
|
||||
case SIGTERM:
|
||||
str = "SIGTERM";
|
||||
break;
|
||||
}
|
||||
if (!str) return;
|
||||
|
||||
for (int i = 0; i < shlen(actors); i++) {
|
||||
prosperon_rt *main = actors[i].value;
|
||||
JSContext *js = main->context;
|
||||
script_evalf(js, "prosperon.dispatch('%s')", str);
|
||||
}
|
||||
|
||||
switch(sig) {
|
||||
case SIGTERM:
|
||||
exit(1);
|
||||
case SIGINT:
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void exit_handler()
|
||||
{
|
||||
for (int i = 0; i < shlen(actors); i++) {
|
||||
prosperon_rt *main = actors[i].value;
|
||||
JSContext *js = main->context;
|
||||
script_evalf(js, "prosperon.dispatch('exit')", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO);
|
||||
int cores = SDL_GetNumLogicalCPUCores();
|
||||
if (cores == 1) {
|
||||
printf("Platform has only one core!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
main_thread = SDL_GetCurrentThreadID();
|
||||
|
||||
if (!main_thread) {
|
||||
printf("Platform does not support threads!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
prosperon = argv[0];
|
||||
|
||||
PHYSFS_init(argv[0]);
|
||||
@@ -107,7 +295,74 @@ int main(int argc, char **argv) {
|
||||
printf("Could not mount core. Reason: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
char **margv = malloc(sizeof(char*));
|
||||
for (int i = 0; i < argc; i++)
|
||||
margv[i] = strdup(argv[i]);
|
||||
|
||||
create_actor(argc, margv);
|
||||
|
||||
queue_mutex = SDL_CreateMutex();
|
||||
queue_cond = SDL_CreateCondition();
|
||||
|
||||
for (int i = 0; i < 1; i++)
|
||||
SDL_CreateThread(crank_actor, "actor_runner", NULL);
|
||||
|
||||
SDL_CreateThread(reclaimer_thread, "reclaimer", NULL);
|
||||
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGSEGV, signal_handler);
|
||||
signal(SIGABRT, signal_handler);
|
||||
atexit(exit_handler);
|
||||
|
||||
SDL_Event *event;
|
||||
while (SDL_WaitEvent(event)) {
|
||||
printf("Got event!\n");
|
||||
if (event->type == SDL_EVENT_QUIT)
|
||||
return 0;
|
||||
}
|
||||
|
||||
script_startup(argc, argv); // runs engine.js
|
||||
return 0;
|
||||
}
|
||||
|
||||
prosperon_rt *get_actor(char *id)
|
||||
{
|
||||
int idx = shgeti(actors, id);
|
||||
if (idx == -1) return NULL;
|
||||
|
||||
return actors[idx].value;
|
||||
}
|
||||
|
||||
char *register_actor(char *id, prosperon_rt *actor)
|
||||
{
|
||||
if (shgeti(actors, id) != -1) return "Actor with given ID already exists.";
|
||||
shput(actors, id, actor);
|
||||
printf("registerd actor %s as %p\n", id, actor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void send_message(prosperon_rt *target, struct message msg)
|
||||
{
|
||||
printf("sending message to actor %p\n", target);
|
||||
SDL_LockMutex(target->mutex);
|
||||
arrput(target->messages, msg);
|
||||
SDL_UnlockMutex(target->mutex);
|
||||
|
||||
actor_signal(target);
|
||||
}
|
||||
|
||||
void actor_signal(prosperon_rt *actor)
|
||||
{
|
||||
printf("waking actor %p\n", actor);
|
||||
SDL_LockMutex(actor->mutex);
|
||||
if (actor->state != ACTOR_READY) {
|
||||
actor->state = ACTOR_READY;
|
||||
SDL_LockMutex(queue_mutex);
|
||||
arrput(ready_queue, actor);
|
||||
SDL_SignalCondition(queue_cond);
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
}
|
||||
|
||||
67
source/prosperon.h
Normal file
67
source/prosperon.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef PROSPERON_H
|
||||
#define PROSPERON_H
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include "quickjs.h"
|
||||
|
||||
typedef JSValue (*MODULEFN)(JSContext *js);
|
||||
|
||||
#define STATE_VECTOR_LENGTH 624
|
||||
#define STATE_VECTOR_M 397 /* changes to STATE_VECTOR_LENGTH also require changes to this */
|
||||
|
||||
typedef struct tagMTRand {
|
||||
uint32_t mt[STATE_VECTOR_LENGTH];
|
||||
int32_t index;
|
||||
} MTRand;
|
||||
|
||||
extern SDL_ThreadID main_thread;
|
||||
|
||||
extern SDL_TLSID prosperon_id;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
MODULEFN fn;
|
||||
} ModuleEntry;
|
||||
|
||||
typedef struct {
|
||||
int argc;
|
||||
char **argv;
|
||||
} cmdargs;
|
||||
|
||||
struct message {
|
||||
void *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#define ACTOR_IDLE 0
|
||||
#define ACTOR_READY 1
|
||||
#define ACTOR_RUNNING 2
|
||||
#define ACTOR_EXHAUSTED 3 // flagged when the actor is running GC
|
||||
#define ACTOR_RECLAIMING 4
|
||||
#define ACTOR_SLOW 5
|
||||
|
||||
typedef struct prosperon_rt {
|
||||
cmdargs cmd; // args this actor was started with
|
||||
JSContext *context; // The context this actor uses
|
||||
MTRand mrand;
|
||||
JSValue cycle_fn;
|
||||
JSValue idx_buffer;
|
||||
JSValue on_exception;
|
||||
JSValue message_handle;
|
||||
int idx_count;
|
||||
ModuleEntry *module_registry;
|
||||
JSValue *js_swapchains;
|
||||
struct { Uint32 key; JSValue value; } *timers;
|
||||
JSValue *events; // stack of events that need triggered on this actor
|
||||
SDL_Mutex *mutex; // blocks access to modifying this actor
|
||||
struct message *messages;
|
||||
int state; //
|
||||
} prosperon_rt;
|
||||
|
||||
prosperon_rt *get_actor(char *id);
|
||||
char *register_actor(char *id, prosperon_rt *actor);
|
||||
prosperon_rt *create_actor();
|
||||
void actor_signal(prosperon_rt *actor);
|
||||
void actor_turn(prosperon_rt *actor);
|
||||
void send_message(prosperon_rt *actor, struct message msg);
|
||||
#endif
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <assert.h>
|
||||
#include "quickjs.h"
|
||||
|
||||
#include "prosperon.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <malloc/malloc.h>
|
||||
#elif defined(_WIN32)
|
||||
@@ -22,13 +24,8 @@
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
SDL_TLSID on_exception = {0};
|
||||
SDL_TLSID js_id = {0};
|
||||
|
||||
#define ENGINE "scripts/core/engine.js"
|
||||
|
||||
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT
|
||||
|
||||
#ifdef TRACY_ENABLE
|
||||
#include <tracy/TracyC.h>
|
||||
|
||||
@@ -135,7 +132,8 @@ static const JSMallocFunctions tracy_malloc_funcs = {
|
||||
|
||||
#endif
|
||||
|
||||
void script_startup(int argc, char **argv) {
|
||||
// this function takes control of the program.
|
||||
void script_startup(prosperon_rt *prt) {
|
||||
JSRuntime *rt;
|
||||
#ifdef TRACY_ENABLE
|
||||
rt = JS_NewRuntime2(&tracy_malloc_funcs, NULL);
|
||||
@@ -143,7 +141,6 @@ void script_startup(int argc, char **argv) {
|
||||
rt = JS_NewRuntime();
|
||||
#endif
|
||||
JSContext *js = JS_NewContextRaw(rt);
|
||||
SDL_SetTLS(&js_id, js, NULL);
|
||||
JS_AddIntrinsicBaseObjects(js);
|
||||
JS_AddIntrinsicEval(js);
|
||||
JS_AddIntrinsicRegExp(js);
|
||||
@@ -156,11 +153,11 @@ void script_startup(int argc, char **argv) {
|
||||
JS_AddIntrinsicOperators(js);
|
||||
JS_EnableBignumExt(js, 1);
|
||||
|
||||
JSValue *onexp = malloc(sizeof(JSValue));
|
||||
*onexp = JS_UNDEFINED;
|
||||
SDL_SetTLS(&on_exception, onexp, NULL);
|
||||
JS_SetContextOpaque(js, prt);
|
||||
prt->context = js;
|
||||
printf("started actor %p with context %p\n", prt, prt->context);
|
||||
|
||||
ffi_load(js, argc, argv);
|
||||
ffi_load(js);
|
||||
|
||||
PHYSFS_File *eng = PHYSFS_openRead(ENGINE);
|
||||
if (!eng) {
|
||||
@@ -173,9 +170,10 @@ void script_startup(int argc, char **argv) {
|
||||
void *data = malloc(stat.filesize);
|
||||
PHYSFS_readBytes(eng,data,stat.filesize);
|
||||
PHYSFS_close(eng);
|
||||
JSValue v = script_eval(js, ENGINE, data);
|
||||
SDL_LockMutex(prt->mutex);
|
||||
JSValue v = JS_Eval(js, data, strlen(data), ENGINE, JS_EVAL_FLAG_STRICT);
|
||||
uncaught_exception(js,v);
|
||||
script_stop(js);
|
||||
SDL_UnlockMutex(prt->mutex);
|
||||
}
|
||||
|
||||
void script_stop(JSContext *js)
|
||||
@@ -188,13 +186,9 @@ void script_stop(JSContext *js)
|
||||
|
||||
free(prt);
|
||||
|
||||
JSValue *onexp = SDL_GetTLS(&on_exception);
|
||||
JS_FreeValue(js,*onexp);
|
||||
JSRuntime *rt = JS_GetRuntime(js);
|
||||
JS_FreeContext(js);
|
||||
JS_FreeRuntime(rt);
|
||||
|
||||
free(onexp);
|
||||
}
|
||||
|
||||
void uncaught_exception(JSContext *js, JSValue v)
|
||||
@@ -204,11 +198,13 @@ void uncaught_exception(JSContext *js, JSValue v)
|
||||
return;
|
||||
}
|
||||
|
||||
JSValue *onexp = SDL_GetTLS(&on_exception);
|
||||
prosperon_rt *rt = JS_GetContextOpaque(js);
|
||||
|
||||
JSValue onexp = rt->on_exception;
|
||||
|
||||
if (!JS_IsUndefined(*onexp)) {
|
||||
if (!JS_IsUndefined(onexp)) {
|
||||
JSValue ex = JS_GetException(js);
|
||||
JSValue ret = JS_Call(js, *onexp, JS_UNDEFINED, 1, &ex);
|
||||
JSValue ret = JS_Call(js, onexp, JS_UNDEFINED, 1, &ex);
|
||||
JS_FreeValue(js,ret);
|
||||
JS_FreeValue(js,ex);
|
||||
} else {
|
||||
@@ -239,13 +235,8 @@ void script_evalf(JSContext *js, const char *format, ...)
|
||||
vsnprintf(eval, len+1, format, args);
|
||||
va_end(args);
|
||||
|
||||
obj = JS_Eval(js, eval, len, "C eval", JS_EVAL_FLAGS);
|
||||
obj = JS_Eval(js, eval, len, "C eval", JS_EVAL_FLAG_STRICT);
|
||||
free(eval);
|
||||
|
||||
uncaught_exception(js,obj);
|
||||
}
|
||||
|
||||
JSValue script_eval(JSContext *js, const char *file, const char *script)
|
||||
{
|
||||
return JS_Eval(js, script, strlen(script), file, JS_EVAL_FLAGS);
|
||||
}
|
||||
|
||||
@@ -3,35 +3,9 @@
|
||||
|
||||
#include "quickjs.h"
|
||||
#include <SDL3/SDL.h>
|
||||
#include "prosperon.h"
|
||||
|
||||
typedef JSValue (*MODULEFN)(JSContext *js);
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
MODULEFN fn;
|
||||
} ModuleEntry;
|
||||
|
||||
#define STATE_VECTOR_LENGTH 624
|
||||
#define STATE_VECTOR_M 397 /* changes to STATE_VECTOR_LENGTH also require changes to this */
|
||||
|
||||
typedef struct tagMTRand {
|
||||
uint32_t mt[STATE_VECTOR_LENGTH];
|
||||
int32_t index;
|
||||
} MTRand;
|
||||
|
||||
typedef struct prosperon_rt {
|
||||
MTRand mrand;
|
||||
JSValue cycle_fn;
|
||||
JSValue idx_buffer;
|
||||
int idx_count;
|
||||
ModuleEntry *module_registry;
|
||||
JSValue *js_swapchains;
|
||||
} prosperon_rt;
|
||||
|
||||
extern SDL_TLSID on_exception;
|
||||
extern SDL_TLSID js_id;
|
||||
|
||||
void script_startup(int argc, char **argv);
|
||||
void script_startup(prosperon_rt *rt);
|
||||
void script_stop(JSContext*);
|
||||
|
||||
void script_evalf(JSContext *js, const char *format, ...);
|
||||
|
||||
Reference in New Issue
Block a user