messages
Some checks failed
Build and Deploy / build-linux (push) Successful in 1m11s
Build and Deploy / build-windows (CLANG64) (push) Failing after 6m17s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped
Some checks failed
Build and Deploy / build-linux (push) Successful in 1m11s
Build and Deploy / build-windows (CLANG64) (push) Failing after 6m17s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped
This commit is contained in:
@@ -137,7 +137,7 @@ deps += dependency('soloud', static:true)
|
||||
deps += dependency('libqrencode', static: true)
|
||||
|
||||
sources = []
|
||||
src += ['anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'timer.c', 'transform.c','prosperon.c', 'wildmatch.c', 'sprite.c', 'rtree.c', 'qjs_dmon.c', 'qjs_nota.c', 'qjs_enet.c', 'qjs_soloud.c', 'qjs_qr.c', 'qjs_wota.c', 'monocypher.c']
|
||||
src += ['anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'transform.c','prosperon.c', 'wildmatch.c', 'sprite.c', 'rtree.c', 'qjs_dmon.c', 'qjs_nota.c', 'qjs_enet.c', 'qjs_soloud.c', 'qjs_qr.c', 'qjs_wota.c', 'monocypher.c']
|
||||
|
||||
# quirc src
|
||||
src += ['thirdparty/quirc/quirc.c', 'thirdparty/quirc/decode.c','thirdparty/quirc/identify.c', 'thirdparty/quirc/version_db.c']
|
||||
|
||||
@@ -235,27 +235,6 @@ prosperon.c_types.datastream[prosperon.DOC].callback = `A function to call whene
|
||||
`;
|
||||
|
||||
|
||||
//
|
||||
// timer
|
||||
//
|
||||
prosperon.c_types.timer[prosperon.DOC] = {}
|
||||
prosperon.c_types.timer[prosperon.DOC][prosperon.DOC] = `A scheduled callback or countdown. Freed automatically once no longer referenced
|
||||
or once it completes.
|
||||
`;
|
||||
|
||||
prosperon.c_types.timer[prosperon.DOC].remain = `Get or set how many seconds remain before the timer triggers.
|
||||
|
||||
:param value: (when setting) A float specifying new time remaining.
|
||||
:return: The current time left (when getting), or None (when setting).
|
||||
`;
|
||||
|
||||
prosperon.c_types.timer[prosperon.DOC].fn = `Get or set the function called when the timer expires.
|
||||
|
||||
:param value: (when setting) The function.
|
||||
:return: The function or undefined if none is set.
|
||||
`;
|
||||
|
||||
|
||||
//
|
||||
// rtree
|
||||
//
|
||||
@@ -367,22 +346,6 @@ prosperon.c_types.SDL_Cursor[prosperon.DOC] = {}
|
||||
prosperon.c_types.SDL_Cursor[prosperon.DOC][prosperon.DOC] = `An SDL cursor handle. Freed automatically on GC. No direct methods.
|
||||
`;
|
||||
|
||||
|
||||
//
|
||||
// SDL_Thread
|
||||
//
|
||||
prosperon.c_types.SDL_Thread[prosperon.DOC] = {}
|
||||
prosperon.c_types.SDL_Thread[prosperon.DOC][prosperon.DOC] = `A handle to an SDL-created thread. Freed on GC after join.
|
||||
|
||||
Note: The engine generally doesn't expose custom usage for threads.
|
||||
`;
|
||||
|
||||
prosperon.c_types.SDL_Thread[prosperon.DOC].wait = `Block until this thread terminates.
|
||||
|
||||
:return: None
|
||||
`;
|
||||
|
||||
|
||||
//
|
||||
// SDL_Window
|
||||
//
|
||||
|
||||
@@ -62,7 +62,6 @@ Object.defineProperty(Function.prototype, "hashify", {
|
||||
|
||||
var io = use_embed('io')
|
||||
|
||||
|
||||
var RESPATH = 'scripts/modules/resources.js'
|
||||
var canonical = io.realdir(RESPATH) + 'resources.js'
|
||||
var content = io.slurp(RESPATH)
|
||||
@@ -88,6 +87,8 @@ prosperon.PATH = [
|
||||
"scripts/modules/ext/",
|
||||
]
|
||||
|
||||
console.print("HERE")
|
||||
|
||||
// path is the path of a module or script to resolve
|
||||
var script_fn = function script_fn(path) {
|
||||
var parsed = {}
|
||||
@@ -222,6 +223,8 @@ console[prosperon.DOC] = {
|
||||
clear: "Clear console."
|
||||
}
|
||||
|
||||
|
||||
|
||||
var BASEPATH = 'scripts/core/base.js'
|
||||
var script = io.slurp(BASEPATH)
|
||||
var fnname = "base"
|
||||
@@ -245,7 +248,7 @@ function add_timer(obj, fn, seconds) {
|
||||
else stop.seconds = timer.remain
|
||||
}
|
||||
|
||||
var timer = os.make_timer(execute)
|
||||
// var timer = os.make_timer(execute)
|
||||
timer.remain = seconds
|
||||
|
||||
stop.remain = seconds
|
||||
@@ -395,6 +398,8 @@ Register.check_registers = function check_registers(obj) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Register.add_cb("appupdate")
|
||||
Register.add_cb("update").doc = "Called once per frame."
|
||||
Register.add_cb("physupdate")
|
||||
@@ -488,6 +493,8 @@ actor.spawn = function spawn(script, config, callback) {
|
||||
return underling
|
||||
}
|
||||
|
||||
|
||||
|
||||
actor.clear = function actor_clear() {
|
||||
this[UNDERLINGS].forEach(p => {
|
||||
p.kill()
|
||||
@@ -521,16 +528,23 @@ actor.delay = function(fn, seconds) {
|
||||
}
|
||||
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`
|
||||
|
||||
|
||||
|
||||
var act = use('actor')
|
||||
actor[UNDERLINGS] = new Set()
|
||||
|
||||
globalThis.mixin("color")
|
||||
|
||||
|
||||
|
||||
var DOCPATH = 'scripts/core/doc.js'
|
||||
var script = io.slurp(DOCPATH)
|
||||
var fnname = "doc"
|
||||
script = `(function ${fnname}() { ${script}; })`
|
||||
js.eval(DOCPATH, script)()
|
||||
//js.eval(DOCPATH, script)()
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
When handling a message, the message appears like this:
|
||||
@@ -555,6 +569,7 @@ js.eval(DOCPATH, script)()
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
var enet = use('enet')
|
||||
var util = use('util')
|
||||
var math = use('math')
|
||||
@@ -564,8 +579,6 @@ var nota = use('nota')
|
||||
|
||||
var HEADER = Symbol()
|
||||
|
||||
var ar = 60 // seconds before reclamation
|
||||
|
||||
var $actor = {
|
||||
toString: print_actor
|
||||
}
|
||||
@@ -744,13 +757,8 @@ $_.stop = function(actor) {
|
||||
}
|
||||
$_.stop[prosperon.DOC] = "The stop function stops an underling."
|
||||
|
||||
var unneeded_fn = $_.stop
|
||||
var unneeded_time = ar
|
||||
|
||||
$_.unneeded = function(fn, seconds = ar) {
|
||||
if (typeof fn !== 'function') throw new Error('Must supply a function to unneeded.')
|
||||
unneeded_fn = fn
|
||||
unneeded_time = seconds
|
||||
$_.unneeded = function(fn, seconds) {
|
||||
os.unnneeded(fn, seconds);
|
||||
}
|
||||
$_.unneeded[prosperon.DOC] = "registers a function that is called when the actor..."
|
||||
|
||||
@@ -852,7 +860,7 @@ if (prosperon.args.program) actor.spawn(prosperon.args.program)
|
||||
function destroyself() {
|
||||
console.log(`Got the message to destroy self.`)
|
||||
if (overling) actor_send(overling, { type: "stopped", id: prosperon.id })
|
||||
doexit = true
|
||||
os.destroy(prosperon.id);
|
||||
}
|
||||
|
||||
function handle_actor_disconnect(id) {
|
||||
@@ -879,7 +887,6 @@ function handle_message(msg) {
|
||||
return
|
||||
}
|
||||
}
|
||||
unneeded_timer()
|
||||
switch (msg.type) {
|
||||
case "user":
|
||||
var letter = msg.data
|
||||
@@ -922,9 +929,6 @@ function handle_message(msg) {
|
||||
var greeter = greeters[msg.id]
|
||||
if (greeter) greeter({type: "actor_started", actor: create_actor(msg)})
|
||||
}
|
||||
unneeded_timer = $_.delay(unneeded_fn, unneeded_time)
|
||||
}
|
||||
|
||||
var unneeded_timer = $_.delay($_.stop, ar)
|
||||
|
||||
})()
|
||||
|
||||
@@ -4,7 +4,6 @@ var layout = use('clay')
|
||||
var input = use('input')
|
||||
var emitter = use('emitter')
|
||||
var os = use('os')
|
||||
var event = use('event')
|
||||
var imgui = use('imgui')
|
||||
var tracy = use('tracy')
|
||||
|
||||
@@ -30,7 +29,7 @@ function step() {
|
||||
dt = last_frame_time - frame_t
|
||||
frame_t = last_frame_time
|
||||
|
||||
event.engine_input(e => prosperon.dispatch(e.type, e))
|
||||
// event.engine_input(e => prosperon.dispatch(e.type, e))
|
||||
layout.newframe()
|
||||
|
||||
prosperon.appupdate(dt)
|
||||
|
||||
117
source/jsffi.c
117
source/jsffi.c
@@ -22,7 +22,6 @@
|
||||
#include "par/par_streamlines.h"
|
||||
#include "par/par_shapes.h"
|
||||
#include <stdint.h>
|
||||
#include "timer.h"
|
||||
#include "cute_aseprite.h"
|
||||
#include "cgltf.h"
|
||||
#include "physfs.h"
|
||||
@@ -69,7 +68,6 @@ typedef struct rtree rtree;
|
||||
|
||||
int randombytes(void *buf, size_t n);
|
||||
|
||||
static Uint32 timer_cb_event;
|
||||
static int trace = 0;
|
||||
|
||||
#ifdef __APPLE__
|
||||
@@ -1086,15 +1084,6 @@ static void js_transform_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark
|
||||
QJSCLASSMARK(transform)
|
||||
QJSCLASS(font)
|
||||
QJSCLASS(datastream)
|
||||
|
||||
static JSClassID js_timer_id;
|
||||
static void js_timer_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) {
|
||||
timer *t = JS_GetOpaque(val,js_timer_id);
|
||||
if (!t) return;
|
||||
JS_MarkValue(rt, t->fn, mark_func);
|
||||
}
|
||||
QJSCLASSMARK(timer)
|
||||
|
||||
QJSCLASS(SDL_Window)
|
||||
QJSCLASS(SDL_Renderer)
|
||||
QJSCLASS(SDL_Camera)
|
||||
@@ -6257,14 +6246,6 @@ static const JSCFunctionListEntry js_datastream_funcs[] = {
|
||||
CGETSET_ADD(datastream, callback),
|
||||
};
|
||||
|
||||
JSC_GETSET_CALLBACK(timer, fn)
|
||||
JSC_GETSET(timer, remain, number)
|
||||
|
||||
static const JSCFunctionListEntry js_timer_funcs[] = {
|
||||
CGETSET_ADD(timer, remain),
|
||||
CGETSET_ADD(timer, fn),
|
||||
};
|
||||
|
||||
JSC_GETSET(font, linegap, number)
|
||||
JSC_GET(font, height, number)
|
||||
JSC_GET(font, ascent, number)
|
||||
@@ -6506,9 +6487,6 @@ JSC_SSCALL(os_eval,
|
||||
ret = JS_Eval(js, str2, strlen(str2), str, JS_EVAL_FLAG_STRICT);
|
||||
)
|
||||
|
||||
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);
|
||||
@@ -7142,6 +7120,7 @@ JSC_CCALL(os_mailbox_push,
|
||||
|
||||
const char *id = JS_ToCString(js, argv[0]);
|
||||
prosperon_rt *target = get_actor(id);
|
||||
JS_FreeCString(js,id);
|
||||
if (!target)
|
||||
return JS_ThrowInternalError(js, "No mailbox found for given ID");
|
||||
|
||||
@@ -7159,57 +7138,27 @@ JSC_CCALL(os_mailbox_push,
|
||||
)
|
||||
|
||||
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));
|
||||
|
||||
JS_FreeCString(js, id);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_mailbox_exist,
|
||||
const char *id = JS_ToCString(js, argv[0]);
|
||||
prosperon_rt *actor = get_actor(id);
|
||||
printf("actor from %s is %p\n", id, actor);
|
||||
JS_FreeCString(js, id);
|
||||
|
||||
return JS_NewBool(js, actor ? 1 : 0);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_waitevent,
|
||||
SDL_Event event;
|
||||
double secs;
|
||||
JS_ToFloat64(js, &secs, argv[1]);
|
||||
while (SDL_WaitEventTimeout(&event, secs*1000.0f)) {
|
||||
if (event.type == timer_cb_event) {
|
||||
JSValue *fn = event.user.data1;
|
||||
JSValue ret = JS_Call(js, *fn, JS_UNDEFINED, 0, NULL);
|
||||
JS_FreeValue(js,*fn);
|
||||
free(fn);
|
||||
uncaught_exception(js,ret);
|
||||
} else {
|
||||
gui_input(&event);
|
||||
JSValue e = event2js(js,event);
|
||||
JSValue ret = JS_Call(js,argv[0], JS_UNDEFINED, 1, &e);
|
||||
uncaught_exception(js,ret);
|
||||
}
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
JSC_CCALL(os_unneeded,
|
||||
prosperon_rt *actor = JS_GetContextOpaque(js);
|
||||
actor->unneeded = JS_DupValue(js, argv[1]);
|
||||
actor->unneeded_secs = js2number(js, argv[2]);
|
||||
)
|
||||
|
||||
JSValue js_os_get_trace(JSContext *js, JSValue self)
|
||||
@@ -7223,6 +7172,11 @@ JSValue js_os_set_trace(JSContext *js, JSValue self, JSValue value)
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
JSC_CCALL(os_destroy,
|
||||
prosperon_rt *rt = JS_GetContextOpaque(js);
|
||||
actor_free(rt);
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, make_transform, 0),
|
||||
MIST_FUNC_DEF(os, clean_transforms, 0),
|
||||
@@ -7242,9 +7196,6 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
|
||||
MIST_FUNC_DEF(os, openurl, 1),
|
||||
|
||||
MIST_FUNC_DEF(os, make_timer, 1),
|
||||
MIST_FUNC_DEF(os, update_timers, 1),
|
||||
|
||||
MIST_FUNC_DEF(os, sleep, 1),
|
||||
MIST_FUNC_DEF(os, battery_pct, 0),
|
||||
MIST_FUNC_DEF(os, battery_voltage, 0),
|
||||
@@ -7261,13 +7212,14 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
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_exist, 1),
|
||||
MIST_FUNC_DEF(os, addtimer, 3),
|
||||
MIST_FUNC_DEF(os, removetimer, 2),
|
||||
MIST_FUNC_DEF(os, register_actor, 2),
|
||||
MIST_FUNC_DEF(os, unneeded, 2),
|
||||
MIST_FUNC_DEF(os, destroy, 0),
|
||||
};
|
||||
|
||||
JSC_CCALL(js_dump_class, return js_get_object_class_distribution(js))
|
||||
@@ -7339,43 +7291,6 @@ static const JSCFunctionListEntry js_video_funcs[] = {
|
||||
MIST_FUNC_DEF(os, make_video, 1),
|
||||
};
|
||||
|
||||
|
||||
// Polls and handles all input events
|
||||
JSValue js_os_engine_input(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == timer_cb_event) {
|
||||
JSValue *fn = event.user.data1;
|
||||
JSValue ret = JS_Call(js, *fn, JS_UNDEFINED, 0, NULL);
|
||||
JS_FreeValue(js,*fn);
|
||||
uncaught_exception(js,ret);
|
||||
continue;
|
||||
}
|
||||
gui_input(&event);
|
||||
JSValue e = event2js(js,event);
|
||||
JSValue ret = JS_Call(js,argv[0], JS_UNDEFINED, 1, &e);
|
||||
uncaught_exception(js,ret);
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
JSC_CCALL(os_push_event,
|
||||
SDL_UserEvent e;
|
||||
SDL_zero(e);
|
||||
e.type = SDL_EVENT_USER;
|
||||
e.timestamp = SDL_GetTicksNS();
|
||||
e.code = 0;
|
||||
JSValue fn = JS_DupValue(js,argv[0]);
|
||||
e.data1 = malloc(sizeof(JSValue));
|
||||
*(JSValue*)e.data1 = fn;
|
||||
SDL_PushEvent(&e);
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_event_funcs[] = {
|
||||
MIST_FUNC_DEF(os, push_event, 1),
|
||||
MIST_FUNC_DEF(os, engine_input, 1),
|
||||
};
|
||||
|
||||
JSC_SCALL(os_use_embed,
|
||||
prosperon_rt *rt = JS_GetContextOpaque(js);
|
||||
ModuleEntry *module_registry = rt->module_registry;
|
||||
@@ -7841,7 +7756,6 @@ MISTUSE(js)
|
||||
MISTUSE(graphics)
|
||||
MISTUSE(util)
|
||||
MISTUSE(video)
|
||||
MISTUSE(event)
|
||||
MISTUSE(camera)
|
||||
MISTUSE(debug)
|
||||
MISTUSE(crypto)
|
||||
@@ -7867,7 +7781,7 @@ void ffi_load(JSContext *js)
|
||||
arrput(rt->module_registry, MISTLINE(js));
|
||||
arrput(rt->module_registry, MISTLINE(util));
|
||||
arrput(rt->module_registry, MISTLINE(video));
|
||||
arrput(rt->module_registry, MISTLINE(event));
|
||||
|
||||
arrput(rt->module_registry, MISTLINE(soloud));
|
||||
arrput(rt->module_registry, MISTLINE(layout));
|
||||
arrput(rt->module_registry, MISTLINE(miniz));
|
||||
@@ -7920,10 +7834,7 @@ void ffi_load(JSContext *js)
|
||||
QJSCLASSPREP_FUNCS(transform);
|
||||
QJSCLASSPREP_FUNCS(font);
|
||||
QJSCLASSPREP_FUNCS(datastream);
|
||||
QJSCLASSPREP_FUNCS(timer);
|
||||
|
||||
timer_cb_event = SDL_RegisterEvents(1);
|
||||
|
||||
JS_SetPropertyStr(js, globalThis, "use_dyn", JS_NewCFunction(js,js_os_use_dyn,"use_dyn", 1));
|
||||
JS_SetPropertyStr(js, globalThis, "use_embed", JS_NewCFunction(js,js_os_use_embed,"use_embed", 1));
|
||||
|
||||
|
||||
@@ -108,16 +108,62 @@ if (!ret) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void free_actor(prosperon_rt *actor)
|
||||
Uint32 actor_remove_cb(prosperon_rt *actor, Uint32 id, Uint32 interval)
|
||||
{
|
||||
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);
|
||||
actor_free(actor);
|
||||
}
|
||||
|
||||
void actor_free(prosperon_rt *actor)
|
||||
{
|
||||
// first, remove it from the queue
|
||||
shdel(actors, actor->id);
|
||||
JSContext *js = actor->context;
|
||||
SDL_LockMutex(actor->mutex);
|
||||
JS_FreeValue(js, actor->cycle_fn);
|
||||
JS_FreeValue(js, actor->idx_buffer);
|
||||
JS_FreeValue(js, actor->message_handle);
|
||||
JS_FreeValue(js, actor->on_exception);
|
||||
|
||||
SDL_RemoveTimer(actor->ar);
|
||||
|
||||
for (int i = 0; i < arrlen(actor->js_swapchains); i++)
|
||||
JS_FreeValue(js, actor->js_swapchains[i]);
|
||||
|
||||
for (int i = 0; i < arrlen(actor->events); i++)
|
||||
JS_FreeValue(js, actor->events[i]);
|
||||
|
||||
for (int i = 0; i < hmlen(actor->timers); i++)
|
||||
JS_FreeValue(js, actor->timers[i].value);
|
||||
|
||||
// free(actor->timers);
|
||||
arrfree(actor->js_swapchains);
|
||||
arrfree(actor->events);
|
||||
arrfree(actor->messages);
|
||||
arrfree(actor->module_registry);
|
||||
free(actor);
|
||||
|
||||
SDL_DestroyMutex(actor->mutex);
|
||||
|
||||
JSRuntime *rt = JS_GetRuntime(js);
|
||||
JS_FreeContext(js);
|
||||
JS_FreeRuntime(rt);
|
||||
free(actor->id);
|
||||
free(actor);
|
||||
}
|
||||
|
||||
void set_actor_state(prosperon_rt *actor)
|
||||
{
|
||||
SDL_LockMutex(actor->mutex);
|
||||
if (arrlen(actor->messages) == 0) {
|
||||
actor->state = ACTOR_IDLE;
|
||||
actor->ar = SDL_AddTimerNS(1e9, actor_remove_cb, actor);
|
||||
} else {
|
||||
actor->state = ACTOR_READY;
|
||||
SDL_LockMutex(queue_mutex);
|
||||
arrput(ready_queue, actor);
|
||||
SDL_SignalCondition(queue_cond);
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
}
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
}
|
||||
|
||||
// this function should be called to spin off a new thread with actor
|
||||
@@ -131,6 +177,8 @@ prosperon_rt *create_actor(int argc, char **argv)
|
||||
|
||||
script_startup(rt);
|
||||
|
||||
set_actor_state(rt);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
@@ -141,36 +189,31 @@ void js_dofree(JSRuntime *rt, void *opaque, void *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);
|
||||
SDL_LockMutex(actor->mutex);
|
||||
actor->state = ACTOR_RUNNING;
|
||||
|
||||
// Process all messages until the message queue is empty
|
||||
while (arrlen(actor->messages) > 0) {
|
||||
struct message msg = actor->messages[0];
|
||||
arrdel(actor->messages, 0);
|
||||
JSValue arg = JS_NewArrayBuffer(actor->context, msg.data, msg.size, js_dofree, NULL, 0);
|
||||
JSValue result = JS_Call(actor->context, actor->message_handle, JS_UNDEFINED, 1, &arg);
|
||||
uncaught_exception(actor->context, result);
|
||||
JS_FreeValue(actor->context, arg); // Free the argument after use
|
||||
}
|
||||
|
||||
// After all messages are processed, process one event if any exist
|
||||
while (arrlen(actor->messages) > 0) {
|
||||
JSValue event = actor->events[0];
|
||||
arrdel(actor->events, 0);
|
||||
JSValue result = JS_Call(actor->context, event, JS_UNDEFINED, 0, NULL);
|
||||
uncaught_exception(actor->context, result);
|
||||
JS_FreeValue(actor->context, event);
|
||||
}
|
||||
|
||||
// Update state and re-queue if necessary
|
||||
set_actor_state(actor);
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
}
|
||||
|
||||
int reclaimer_thread(void *data)
|
||||
@@ -337,16 +380,19 @@ prosperon_rt *get_actor(char *id)
|
||||
char *register_actor(char *id, prosperon_rt *actor)
|
||||
{
|
||||
if (shgeti(actors, id) != -1) return "Actor with given ID already exists.";
|
||||
actor->id = strdup(id);
|
||||
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);
|
||||
if (target->ar) {
|
||||
SDL_RemoveTimer(target->ar);
|
||||
target->ar = 0;
|
||||
}
|
||||
SDL_UnlockMutex(target->mutex);
|
||||
|
||||
actor_signal(target);
|
||||
@@ -354,7 +400,6 @@ void send_message(prosperon_rt *target, struct message msg)
|
||||
|
||||
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;
|
||||
|
||||
@@ -43,11 +43,14 @@ struct message {
|
||||
typedef struct prosperon_rt {
|
||||
cmdargs cmd; // args this actor was started with
|
||||
JSContext *context; // The context this actor uses
|
||||
char *id;
|
||||
MTRand mrand;
|
||||
JSValue cycle_fn;
|
||||
JSValue idx_buffer;
|
||||
JSValue on_exception;
|
||||
JSValue message_handle;
|
||||
JSValue unneeded;
|
||||
double unneeded_secs;
|
||||
int idx_count;
|
||||
ModuleEntry *module_registry;
|
||||
JSValue *js_swapchains;
|
||||
@@ -56,6 +59,7 @@ typedef struct prosperon_rt {
|
||||
SDL_Mutex *mutex; // blocks access to modifying this actor
|
||||
struct message *messages;
|
||||
int state; //
|
||||
Uint32 ar; // "actor removal" timer
|
||||
} prosperon_rt;
|
||||
|
||||
prosperon_rt *get_actor(char *id);
|
||||
@@ -64,4 +68,5 @@ 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);
|
||||
void actor_free(prosperon_rt *actor);
|
||||
#endif
|
||||
|
||||
@@ -155,7 +155,6 @@ void script_startup(prosperon_rt *prt) {
|
||||
|
||||
JS_SetContextOpaque(js, prt);
|
||||
prt->context = js;
|
||||
printf("started actor %p with context %p\n", prt, prt->context);
|
||||
|
||||
ffi_load(js);
|
||||
|
||||
@@ -176,21 +175,6 @@ void script_startup(prosperon_rt *prt) {
|
||||
SDL_UnlockMutex(prt->mutex);
|
||||
}
|
||||
|
||||
void script_stop(JSContext *js)
|
||||
{
|
||||
prosperon_rt *prt = JS_GetContextOpaque(js);
|
||||
JS_FreeValue(js, prt->cycle_fn);
|
||||
JS_FreeValue(js, prt->idx_buffer);
|
||||
for (int i = 0; i < arrlen(prt->js_swapchains); i++)
|
||||
JS_FreeValue(js, prt->js_swapchains[i]);
|
||||
|
||||
free(prt);
|
||||
|
||||
JSRuntime *rt = JS_GetRuntime(js);
|
||||
JS_FreeContext(js);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
void uncaught_exception(JSContext *js, JSValue v)
|
||||
{
|
||||
if (!JS_IsException(v)) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "prosperon.h"
|
||||
|
||||
void script_startup(prosperon_rt *rt);
|
||||
void script_stop(JSContext*);
|
||||
|
||||
void script_evalf(JSContext *js, const char *format, ...);
|
||||
JSValue script_eval(JSContext *js, const char *file, const char *script);
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#include "timer.h"
|
||||
#include <stdio.h>
|
||||
#include "stb_ds.h"
|
||||
|
||||
timer **timers;
|
||||
|
||||
timer *timer_make(JSContext *js, JSValue fn)
|
||||
{
|
||||
timer *t = calloc(sizeof(*t),1);
|
||||
t->fn = JS_DupValue(js,fn);
|
||||
arrput(timers, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
void timer_free(JSRuntime *rt, timer *t)
|
||||
{
|
||||
for (int i = 0; i < arrlen(timers); i++) {
|
||||
if (timers[i] == t) {
|
||||
arrdelswap(timers,i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JS_FreeValueRT(rt, t->fn);
|
||||
|
||||
free(t);
|
||||
}
|
||||
|
||||
void timer_update(JSContext *js, double dt)
|
||||
{
|
||||
for (int i = 0; i < arrlen(timers); i++) {
|
||||
if (timers[i]->remain <= -10000) continue;
|
||||
timers[i]->remain -= dt;
|
||||
if (timers[i]->remain <= 0) {
|
||||
timers[i]->remain = -10000;
|
||||
JSValue fn = JS_DupValue(js, timers[i]->fn);
|
||||
JSValue r = JS_Call(js,fn, JS_UNDEFINED, 0, NULL);
|
||||
uncaught_exception(js,r);
|
||||
JS_FreeValue(js, fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef TIMER_H
|
||||
|
||||
#include "script.h"
|
||||
|
||||
typedef struct timer {
|
||||
double remain;
|
||||
JSValue fn;
|
||||
} timer;
|
||||
|
||||
timer *timer_make(JSContext *js, JSValue fn);
|
||||
void timer_free(JSRuntime *rt, timer *t);
|
||||
void timer_update(JSContext *js, double dt);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user