[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;
|
struct ax_theme;
|
||||||
|
|
||||||
extern const char* ax__backend_impl_name;
|
extern const char* ax__backend_impl_name;
|
||||||
|
extern size_t ax__backend_desired_region_size;
|
||||||
|
|
||||||
int ax__backend_new(
|
int ax__backend_new(
|
||||||
struct rgn* init_rgn,
|
struct rgn* init_rgn,
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
const char* ax__backend_impl_name = "SDL";
|
const char* ax__backend_impl_name = "SDL";
|
||||||
|
size_t ax__backend_desired_region_size = SMALL;
|
||||||
|
|
||||||
struct ax_backend {
|
struct ax_backend {
|
||||||
struct msgq* mq;
|
struct msgq* mq;
|
||||||
|
@ -48,6 +49,7 @@ int ax__backend_new(
|
||||||
if (out_bac != NULL) {
|
if (out_bac != NULL) {
|
||||||
*out_bac = bac;
|
*out_bac = bac;
|
||||||
}
|
}
|
||||||
|
printf("hello from SDL\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -61,6 +63,7 @@ static void backend_cleanup(struct ax_backend* bac)
|
||||||
{
|
{
|
||||||
TTF_Quit();
|
TTF_Quit();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
printf("bye from SDL\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct msgq* ax__backend_msgq(struct ax_backend* bac)
|
struct msgq* ax__backend_msgq(struct ax_backend* bac)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "util/region.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "util/region.h"
|
#include <pthread.h>
|
||||||
|
|
||||||
struct ax_theme;
|
struct ax_theme;
|
||||||
struct ax_theme_builder;
|
struct ax_theme_builder;
|
||||||
|
@ -20,6 +21,7 @@ struct ax_ctxt {
|
||||||
const char* err;
|
const char* err;
|
||||||
|
|
||||||
// backend
|
// backend
|
||||||
|
pthread_t bac_thid;
|
||||||
struct ax_backend* bac;
|
struct ax_backend* bac;
|
||||||
|
|
||||||
// theme
|
// theme
|
||||||
|
|
108
src/ctxt/ctxt.c
108
src/ctxt/ctxt.c
|
@ -1,5 +1,7 @@
|
||||||
#include "../ax.h"
|
#include "../ax.h"
|
||||||
#include "../backend.h"
|
#include "../backend.h"
|
||||||
|
#include "../concurrent/msg.h"
|
||||||
|
#include "../concurrent/msgq.h"
|
||||||
#include "../ctxt.h"
|
#include "../ctxt.h"
|
||||||
#include "../util.h"
|
#include "../util.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
|
@ -37,8 +39,15 @@ const char* ax_get_error(struct ax_ctxt* ax)
|
||||||
* Internal 'ax_ctxt' operations
|
* 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)
|
void ax__ctxt_init(struct ax_ctxt* ax, struct rgn* init_rgn)
|
||||||
{
|
{
|
||||||
|
/* init simple stuff */
|
||||||
|
|
||||||
ax->init_rgn = init_rgn;
|
ax->init_rgn = init_rgn;
|
||||||
|
|
||||||
ax->log_out = NULL;
|
ax->log_out = NULL;
|
||||||
|
@ -51,16 +60,20 @@ void ax__ctxt_init(struct ax_ctxt* ax, struct rgn* init_rgn)
|
||||||
ax->thmb = NULL;
|
ax->thmb = NULL;
|
||||||
ax->sel_theme = NULL;
|
ax->sel_theme = NULL;
|
||||||
|
|
||||||
const char* err;
|
ax->bac = NULL;
|
||||||
if (ax__backend_new(init_rgn, &ax->bac, &err) != 0) {
|
spawn_backend(init_rgn, &ax->bac_thid, &ax->bac);
|
||||||
ASSERT(0, "initializing %s backend failed: %s",
|
ASSERT(ax->bac != NULL, "backend wasn't initialized");
|
||||||
ax__backend_impl_name,
|
|
||||||
err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ax__ctxt_cleanup(struct ax_ctxt* ax)
|
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->thmb_rgn);
|
||||||
rgn_cleanup(&ax->err_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");
|
ax_log(ax, "theme selected");
|
||||||
return 0;
|
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 <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include "../src/ax.h"
|
#include "../src/ax.h"
|
||||||
#include "../src/ctxt.h"
|
#include "../src/ctxt.h"
|
||||||
#include "../src/backend.h"
|
#include "../src/backend.h"
|
||||||
|
@ -20,6 +21,17 @@ static void sigint_handler(int signum)
|
||||||
exit(0);
|
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)
|
int main(void)
|
||||||
{
|
{
|
||||||
signal(SIGINT, sigint_handler);
|
signal(SIGINT, sigint_handler);
|
||||||
|
@ -27,28 +39,10 @@ int main(void)
|
||||||
ax = ax_new();
|
ax = ax_new();
|
||||||
ax_set_logger(ax, 0, false);
|
ax_set_logger(ax, 0, false);
|
||||||
|
|
||||||
int rv = 0;
|
(void) make_example_theme();
|
||||||
#define GUARD(f, ...) if ((rv = f(__VA_ARGS__)) != 0) goto cleanup
|
|
||||||
|
|
||||||
ax_begin_theme(ax);
|
usleep(5 * 1000 * 1000);
|
||||||
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);
|
|
||||||
|
|
||||||
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();
|
cleanup();
|
||||||
return rv;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue