root actor runs only on main thread; restrict ffi main thread functions to it
This commit is contained in:
@@ -2457,6 +2457,9 @@ JS_FreeValue(js,v); \
|
||||
} \
|
||||
|
||||
JSC_CCALL(os_engine_start,
|
||||
if (SDL_GetCurrentThreadID() != main_thread)
|
||||
return JS_ThrowInternalError(js, "This can only be called from the root actor.");
|
||||
|
||||
if (global_window)
|
||||
return JS_ThrowReferenceError(js, "The engine was already started.");
|
||||
|
||||
@@ -6298,6 +6301,9 @@ JSC_CCALL(os_make_surface,
|
||||
)
|
||||
|
||||
JSC_CCALL(os_make_cursor,
|
||||
if (SDL_GetCurrentThreadID() != main_thread)
|
||||
return JS_ThrowInternalError(js, "This can only be called from the root actor.");
|
||||
|
||||
SDL_Surface *s = js2SDL_Surface(js,argv[0]);
|
||||
HMM_Vec2 hot = js2vec2(js,argv[1]);
|
||||
SDL_Cursor *c = SDL_CreateColorCursor(s, hot.x, hot.y);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#define ENGINE "scripts/core/engine.js"
|
||||
|
||||
static prosperon_rt **ready_queue = NULL;
|
||||
static prosperon_rt **main_ready_queue = NULL;
|
||||
static SDL_Mutex *queue_mutex = NULL;
|
||||
static SDL_Condition *queue_cond = NULL;
|
||||
static SDL_Mutex *actors_mutex = NULL;
|
||||
@@ -48,6 +49,8 @@ static struct { char *key; prosperon_rt *value; } *actors = NULL;
|
||||
static unsigned char *zip_buffer_global = NULL;
|
||||
static char *prosperon = NULL;
|
||||
|
||||
static Uint32 queue_event;
|
||||
|
||||
static SDL_AtomicInt shutdown;
|
||||
static SDL_Thread **runners = NULL;
|
||||
|
||||
@@ -226,6 +229,8 @@ 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.";
|
||||
if (shlen(actors) == 0)
|
||||
actor->main_thread_only = 1;
|
||||
actor->id = strdup(id);
|
||||
SDL_LockMutex(actors_mutex);
|
||||
shput(actors, id, actor);
|
||||
@@ -262,6 +267,7 @@ static void set_actor_state(prosperon_rt *actor)
|
||||
|
||||
int has_messages = arrlen(actor->messages);
|
||||
int has_events = arrlen(actor->events);
|
||||
int has_upcoming = hmlen(actor->timers);
|
||||
|
||||
if (actor->state == ACTOR_RUNNING)
|
||||
actor->state = ACTOR_IDLE;
|
||||
@@ -271,8 +277,15 @@ static void set_actor_state(prosperon_rt *actor)
|
||||
if (has_messages || has_events) {
|
||||
actor->state = ACTOR_READY;
|
||||
SDL_LockMutex(queue_mutex);
|
||||
arrput(ready_queue, actor);
|
||||
SDL_SignalCondition(queue_cond);
|
||||
if (actor->main_thread_only) {
|
||||
arrput(main_ready_queue, actor);
|
||||
SDL_Event event;
|
||||
event.type = queue_event;
|
||||
SDL_PushEvent(&event);
|
||||
} else {
|
||||
SDL_SignalCondition(queue_cond);
|
||||
arrput(ready_queue, actor);
|
||||
}
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
goto END;
|
||||
}
|
||||
@@ -287,12 +300,12 @@ static void set_actor_state(prosperon_rt *actor)
|
||||
}
|
||||
|
||||
END:
|
||||
if (actor->state == ACTOR_IDLE && !actor->ar)
|
||||
if (actor->state == ACTOR_IDLE && !actor->ar && !has_upcoming)
|
||||
actor->ar = SDL_AddTimerNS(SDL_SECONDS_TO_NS(1), actor_remove_cb, actor);
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
}
|
||||
|
||||
void actor_turn(prosperon_rt *actor)
|
||||
void actor_turn(prosperon_rt *actor, int greedy)
|
||||
{
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
actor->state = ACTOR_RUNNING;
|
||||
@@ -326,6 +339,8 @@ void actor_turn(prosperon_rt *actor)
|
||||
uncaught_exception(actor->context, result);
|
||||
JS_FreeValue(actor->context,arg);
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
|
||||
if (!greedy) goto END;
|
||||
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
need_stop = actor->need_stop;
|
||||
@@ -358,6 +373,8 @@ void actor_turn(prosperon_rt *actor)
|
||||
uncaught_exception(actor->context, result);
|
||||
JS_FreeValue(actor->context, event);
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
|
||||
if (!greedy) goto END;
|
||||
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
events = arrlen(actor->events);
|
||||
@@ -486,6 +503,10 @@ JSValue js_actor_delay(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
JSValue cb = JS_DupValue(js, argv[0]);
|
||||
hmput(actor->timers, id, cb);
|
||||
if (actor->ar) {
|
||||
SDL_RemoveTimer(actor->ar);
|
||||
actor->ar = 0;
|
||||
}
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
|
||||
return JS_UNDEFINED;
|
||||
@@ -627,7 +648,7 @@ static int crank_actor(void *data)
|
||||
}
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
|
||||
if (actor) actor_turn(actor);
|
||||
if (actor) actor_turn(actor, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1279,17 +1300,18 @@ static WotaBuffer event2wota(const SDL_Event *event) {
|
||||
return wb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO);
|
||||
queue_event = SDL_RegisterEvents(1);
|
||||
|
||||
int cores = SDL_GetNumLogicalCPUCores();
|
||||
if (cores == 1) {
|
||||
printf("Platform has only one core!\n");
|
||||
return 1;
|
||||
}
|
||||
main_thread = SDL_GetCurrentThreadID();
|
||||
printf("main is %u\n", main_thread);
|
||||
if (!main_thread) {
|
||||
printf("Platform does not support threads!\n");
|
||||
return 1;
|
||||
@@ -1331,6 +1353,9 @@ int main(int argc, char **argv)
|
||||
|
||||
SDL_Event event;
|
||||
while (SDL_WaitEvent(&event)) {
|
||||
if (event.type == queue_event)
|
||||
goto QUEUE;
|
||||
|
||||
WotaBuffer wb = event2wota(&event);
|
||||
|
||||
// Broadcast this event to all actors
|
||||
@@ -1345,6 +1370,20 @@ int main(int argc, char **argv)
|
||||
SDL_UnlockMutex(actors_mutex);
|
||||
|
||||
wota_buffer_free(&wb); // free WotaBuffer
|
||||
|
||||
QUEUE:
|
||||
SDL_LockMutex(queue_mutex);
|
||||
if (arrlen(main_ready_queue) == 0) {
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
continue;
|
||||
}
|
||||
prosperon_rt *actor = main_ready_queue[0];
|
||||
arrdel(main_ready_queue, 0);
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
|
||||
actor_turn(actor, 0);
|
||||
|
||||
END:
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ typedef struct prosperon_rt {
|
||||
int state;
|
||||
Uint32 ar;
|
||||
int need_stop;
|
||||
int main_thread_only;
|
||||
} prosperon_rt;
|
||||
|
||||
extern SDL_ThreadID main_thread;
|
||||
|
||||
27
tests/window.js
Normal file
27
tests/window.js
Normal file
@@ -0,0 +1,27 @@
|
||||
prosperon.win = prosperon.engine_start({
|
||||
title:`Prosperon [${prosperon.version}-${prosperon.revision}]`,
|
||||
width: 1280,
|
||||
height: 720,
|
||||
high_dpi:0,
|
||||
alpha:1,
|
||||
fullscreen:0,
|
||||
sample_count:1,
|
||||
enable_clipboard:true,
|
||||
enable_dragndrop: true,
|
||||
max_dropped_files: 1,
|
||||
swap_interval: 1,
|
||||
name: "Prosperon",
|
||||
version:prosperon.version + "-" + prosperon.revision,
|
||||
identifier: "world.pockle.prosperon",
|
||||
creator: "Pockle World LLC",
|
||||
copyright: "Copyright Pockle World 2025",
|
||||
type: "game",
|
||||
url: "https://prosperon.dev"
|
||||
})
|
||||
|
||||
function loop() {
|
||||
$_.delay(loop, 1/60)
|
||||
}
|
||||
loop()
|
||||
|
||||
$_.delay($_.stop, 3)
|
||||
Reference in New Issue
Block a user