From fbe01e351bbaed1380126322b63d1ec376303545 Mon Sep 17 00:00:00 2001 From: Milo Turner Date: Wed, 19 Feb 2020 20:55:14 -0500 Subject: [PATCH] [async] shenanigans to run the backend in another thread --- src/backend.h | 1 + src/backend/sdl.c | 3 ++ src/ctxt.h | 4 +- src/ctxt/ctxt.c | 108 +++++++++++++++++++++++++++++++++++++++++++--- test/main.c | 36 +++++++--------- 5 files changed, 124 insertions(+), 28 deletions(-) diff --git a/src/backend.h b/src/backend.h index fe16a89..1937141 100644 --- a/src/backend.h +++ b/src/backend.h @@ -10,6 +10,7 @@ struct ax_backend; struct ax_theme; extern const char* ax__backend_impl_name; +extern size_t ax__backend_desired_region_size; int ax__backend_new( struct rgn* init_rgn, diff --git a/src/backend/sdl.c b/src/backend/sdl.c index 6611055..1a0b8a1 100644 --- a/src/backend/sdl.c +++ b/src/backend/sdl.c @@ -12,6 +12,7 @@ * -------------------------------------------------------------------------- */ const char* ax__backend_impl_name = "SDL"; +size_t ax__backend_desired_region_size = SMALL; struct ax_backend { struct msgq* mq; @@ -48,6 +49,7 @@ int ax__backend_new( if (out_bac != NULL) { *out_bac = bac; } + printf("hello from SDL\n"); return 0; fail: @@ -61,6 +63,7 @@ static void backend_cleanup(struct ax_backend* bac) { TTF_Quit(); SDL_Quit(); + printf("bye from SDL\n"); } struct msgq* ax__backend_msgq(struct ax_backend* bac) diff --git a/src/ctxt.h b/src/ctxt.h index 657d39b..f10beb8 100644 --- a/src/ctxt.h +++ b/src/ctxt.h @@ -1,8 +1,9 @@ #pragma once +#include "util/region.h" #include #include -#include "util/region.h" +#include struct ax_theme; struct ax_theme_builder; @@ -20,6 +21,7 @@ struct ax_ctxt { const char* err; // backend + pthread_t bac_thid; struct ax_backend* bac; // theme diff --git a/src/ctxt/ctxt.c b/src/ctxt/ctxt.c index a951b57..65f71b6 100644 --- a/src/ctxt/ctxt.c +++ b/src/ctxt/ctxt.c @@ -1,5 +1,7 @@ #include "../ax.h" #include "../backend.h" +#include "../concurrent/msg.h" +#include "../concurrent/msgq.h" #include "../ctxt.h" #include "../util.h" #include "theme.h" @@ -37,8 +39,15 @@ const char* ax_get_error(struct ax_ctxt* ax) * Internal 'ax_ctxt' operations * -------------------------------------------------------------------------- */ +static void spawn_backend( + struct rgn* init_rgn, + pthread_t* out_thid, + struct ax_backend** out_backend); + void ax__ctxt_init(struct ax_ctxt* ax, struct rgn* init_rgn) { + /* init simple stuff */ + ax->init_rgn = init_rgn; ax->log_out = NULL; @@ -51,16 +60,20 @@ void ax__ctxt_init(struct ax_ctxt* ax, struct rgn* init_rgn) ax->thmb = NULL; ax->sel_theme = NULL; - const char* err; - if (ax__backend_new(init_rgn, &ax->bac, &err) != 0) { - ASSERT(0, "initializing %s backend failed: %s", - ax__backend_impl_name, - err); - } + ax->bac = NULL; + spawn_backend(init_rgn, &ax->bac_thid, &ax->bac); + ASSERT(ax->bac != NULL, "backend wasn't initialized"); } void ax__ctxt_cleanup(struct ax_ctxt* ax) { + struct msgq* bac_mq = ax__backend_msgq(ax->bac); + msgq_begin_send_typed(bac_mq, ax_msg_shutdown); + msgq_end_send(bac_mq); + ax_log(ax, "waiting for backend shutdown."); + pthread_join(ax->bac_thid, NULL); + ax_log(ax, "backend shutdown"); + rgn_cleanup(&ax->thmb_rgn); rgn_cleanup(&ax->err_rgn); } @@ -153,3 +166,86 @@ int ax_select_theme(struct ax_ctxt* ax, struct ax_theme* thm) ax_log(ax, "theme selected"); return 0; } + +/* ----------------------------------------------------------------------------- + * Backend worker thread + * -------------------------------------------------------------------------- */ + +struct backend_init_ctxt { + // "input" + struct rgn* rgn; + pthread_mutex_t mx; + pthread_cond_t cv; + + // "output" + struct ax_backend* backend; + const char* err; +}; + +static void* backend_worker(void* arg); + +static void spawn_backend( + struct rgn* init_rgn, + pthread_t* out_thid, + struct ax_backend** out_backend) +{ + pthread_t thid; + struct backend_init_ctxt init = { + .rgn = init_rgn, + .err = NULL, + }; + pthread_mutex_init(&init.mx, NULL); + pthread_cond_init(&init.cv, NULL); + pthread_mutex_lock(&init.mx); + pthread_create(&thid, NULL, backend_worker, &init); + pthread_cond_wait(&init.cv, &init.mx); + pthread_mutex_unlock(&init.mx); + pthread_cond_destroy(&init.cv); + pthread_mutex_destroy(&init.mx); + + if (init.err != NULL) { + ASSERT(0, "failed to initialize `%s' backend: %s", + ax__backend_impl_name, init.err); + } + if (out_thid != NULL) { + *out_thid = thid; + } + if (out_backend != NULL) { + *out_backend = init.backend; + } +} + +static void* backend_worker(void* arg) +{ + struct backend_init_ctxt* init = arg; + + struct rgn* bac_rgn = ralloc_typed(init->rgn, struct rgn, 1); + rgn_init(bac_rgn, ax__backend_desired_region_size); + + struct ax_backend* bac; + const char* err = NULL; + int rv = ax__backend_new(bac_rgn, &bac, &err); + + pthread_mutex_lock(&init->mx); + init->backend = bac; + if (rv != 0) { + init->err = rstrdup(init->rgn, err); + } + pthread_cond_signal(&init->cv); + pthread_mutex_unlock(&init->mx); + + if (rv != 0) { + goto cleanup; + } + + // `bac` is succesfully initialized here! + + while (!ax__backend_is_shutdown(bac)) { + ax__backend_wait_for_event(bac); + ax__backend_step(bac); + } + +cleanup: + rgn_cleanup(bac_rgn); + return NULL; +} diff --git a/test/main.c b/test/main.c index 6afb806..e8abce9 100644 --- a/test/main.c +++ b/test/main.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../src/ax.h" #include "../src/ctxt.h" #include "../src/backend.h" @@ -20,6 +21,17 @@ static void sigint_handler(int signum) exit(0); } +static struct ax_theme* make_example_theme() +{ + ax_begin_theme(ax); + ax_set_theme_color(ax, "primary", 0x00ff00); + ax_set_theme_font(ax, "default", "/usr/share/fonts/TTF/DejaVuSans.ttf", 0); + ax_set_theme_font(ax, "h1", NULL, 95); + struct ax_theme* thm; + ax_end_theme(ax, &thm); + return thm; +} + int main(void) { signal(SIGINT, sigint_handler); @@ -27,28 +39,10 @@ int main(void) ax = ax_new(); ax_set_logger(ax, 0, false); - int rv = 0; -#define GUARD(f, ...) if ((rv = f(__VA_ARGS__)) != 0) goto cleanup + (void) make_example_theme(); - ax_begin_theme(ax); - ax_set_theme_color(ax, "primary", 0x00ff00); - ax_set_theme_font(ax, "default", "/usr/share/fonts/TTF/DejaVuSans.ttf", 0); - ax_set_theme_font(ax, "h1", NULL, 95); + usleep(5 * 1000 * 1000); - struct ax_theme* thm; - ax_end_theme(ax, &thm); - - ax_log(ax, "Got here\n"); - - while (!ax__backend_is_shutdown(ax->bac)) { - ax__backend_wait_for_event(ax->bac); - ax__backend_step(ax->bac); - } - -//cleanup: - if (rv != 0) { - printf("error: %s\n", ax_get_error(ax)); - } cleanup(); - return rv; + return 0; }