Update main loop to fix reentrancy runtime errors

This commit is contained in:
Alexsander Akers
2022-01-26 20:24:15 -05:00
parent a0f8e9c8bc
commit cb8223217b
7 changed files with 124 additions and 41 deletions

View File

@@ -24,39 +24,83 @@
#include <stdio.h>
#include "watch.h"
#include "watch_main_loop.h"
#include <emscripten.h>
#include <emscripten/html5.h>
#define ANIMATION_FRAME_ID_IS_VALID(id) ((id) >= 0)
#define ANIMATION_FRAME_ID_INVALID (-1)
#define ANIMATION_FRAME_ID_SUSPENDED (-2)
static bool sleeping = true;
static volatile long animation_frame_id = ANIMATION_FRAME_ID_INVALID;
// make compiler happy
static void main_loop_set_sleeping(bool sleeping);
static EM_BOOL main_loop(double time, void *userData);
static inline void request_next_frame(void) {
if (animation_frame_id == ANIMATION_FRAME_ID_INVALID) {
animation_frame_id = emscripten_request_animation_frame(main_loop, NULL);
}
}
static EM_BOOL main_loop(double time, void *userData) {
if (main_loop_is_sleeping()) {
request_next_frame();
return EM_FALSE;
}
if (sleeping) {
sleeping = false;
app_wake_from_standby();
}
animation_frame_id = ANIMATION_FRAME_ID_INVALID;
bool can_sleep = app_loop();
if (can_sleep) {
app_prepare_for_standby();
sleeping = true;
animation_frame_id = ANIMATION_FRAME_ID_INVALID;
return EM_FALSE;
}
return EM_TRUE;
request_next_frame();
return EM_FALSE;
}
// make compiler happy
void resume_main_loop(void);
EMSCRIPTEN_KEEPALIVE
void resume_main_loop(void) {
if (sleeping) {
emscripten_request_animation_frame_loop(main_loop, NULL);
if (!ANIMATION_FRAME_ID_IS_VALID(animation_frame_id)) {
animation_frame_id = emscripten_request_animation_frame(main_loop, NULL);
}
}
void suspend_main_loop(void) {
if (ANIMATION_FRAME_ID_IS_VALID(animation_frame_id)) {
emscripten_cancel_animation_frame(animation_frame_id);
}
animation_frame_id = ANIMATION_FRAME_ID_SUSPENDED;
}
void main_loop_sleep(uint32_t ms) {
main_loop_set_sleeping(true);
emscripten_sleep(ms);
main_loop_set_sleeping(false);
}
bool main_loop_is_sleeping(void) {
return EM_ASM_INT({ return Module['suspended']; }) != 0;
}
static void main_loop_set_sleeping(bool sleeping) {
EM_ASM({
Module['suspended'] = $0;
}, sleeping);
}
int main(void) {
printf("Hello, world!\n");