[async] shenanigans to run the backend in another thread
This commit is contained in:
parent
bb8eda00e4
commit
fbe01e351b
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/region.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "util/region.h"
|
||||
#include <pthread.h>
|
||||
|
||||
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
|
||||
|
|
108
src/ctxt/ctxt.c
108
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;
|
||||
}
|
||||
|
|
36
test/main.c
36
test/main.c
|
@ -1,6 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue