Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ extern twin_backend_t g_twin_backend;
*/
twin_context_t *twin_create(int width, int height)
{
/* Runtime check for missing backend */
if (!g_twin_backend.init) {
log_error("Backend not registered - no init function");
return NULL;
}

assert(g_twin_backend.init && "Backend not registered");

twin_context_t *ctx = g_twin_backend.init(width, height);
if (!ctx) {
#ifdef CONFIG_LOGGING
log_error("Failed to initialize Twin context (%dx%d)", width, height);
#endif
log_error("Backend initialization failed (%dx%d)", width, height);
}
return ctx;
}
Expand All @@ -42,10 +46,18 @@ twin_context_t *twin_create(int width, int height)
*/
void twin_destroy(twin_context_t *ctx)
{
if (!ctx)
return;

/* Runtime check for missing backend */
if (!g_twin_backend.exit) {
log_error("Backend not registered - no exit function");
return;
}

assert(g_twin_backend.exit && "Backend not registered");

if (ctx)
g_twin_backend.exit(ctx);
g_twin_backend.exit(ctx);
}

/**
Expand All @@ -57,11 +69,24 @@ void twin_destroy(twin_context_t *ctx)
*
* @ctx : Twin context to run
* @init_callback : Application initialization function (called once before
* event loop)
* event loop)
*/
void twin_run(twin_context_t *ctx, void (*init_callback)(twin_context_t *))
{
/* Validate context parameter */
if (!ctx) {
log_error("NULL context passed to twin_run");
return;
}

assert(ctx && "NULL context passed to twin_run");

/* Runtime check for missing start function */
if (!g_twin_backend.start) {
log_error("Backend has no start function - main loop not running");
return;
}

assert(g_twin_backend.start && "Backend start function not registered");

g_twin_backend.start(ctx, init_callback);
Expand Down
8 changes: 0 additions & 8 deletions src/dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ bool twin_dispatch_once(twin_context_t *ctx)
{
/* Validate context to prevent null pointer dereference in callbacks */
if (!ctx) {
#ifdef CONFIG_LOGGING
log_error("twin_dispatch_once: NULL context");
#endif
return false;
}

Expand All @@ -57,9 +55,7 @@ bool twin_dispatch_once(twin_context_t *ctx)
if (!g_twin_backend.poll(ctx))
return false;
} else {
#ifdef CONFIG_LOGGING
log_warn("twin_dispatch_once: No backend poll function registered");
#endif
/* Yield CPU to avoid busy-waiting when no event source available */
#ifdef __EMSCRIPTEN__
emscripten_sleep(0);
Expand Down Expand Up @@ -94,18 +90,14 @@ void twin_dispatch(twin_context_t *ctx)
* Calling twin_dispatch() directly will not work in WebAssembly.
*/
(void) ctx; /* Unused in Emscripten builds */
#ifdef CONFIG_LOGGING
log_error(
"twin_dispatch() called in Emscripten build - use "
"twin_dispatch_once() with emscripten_set_main_loop_arg()");
#endif
return;
#else
/* Validate context before entering event loop */
if (!ctx) {
#ifdef CONFIG_LOGGING
log_error("twin_dispatch: NULL context");
#endif
return;
}

Expand Down