[theme] callback-style waiting for a theme to load

This commit is contained in:
Milo Turner 2020-02-21 15:53:09 -05:00
parent 940d4231d5
commit 153c084419
8 changed files with 74 additions and 37 deletions

View File

@ -35,6 +35,7 @@ void ax_set_theme_font(
void ax_set_theme_iconset( void ax_set_theme_iconset(
struct ax_ctxt* ax, const char* iconset_dir); struct ax_ctxt* ax, const char* iconset_dir);
void ax_theme_wait_until_loaded(struct ax_ctxt* ax, struct ax_theme* thm);
int ax_select_theme(struct ax_ctxt* ax, struct ax_theme* thm); int ax_select_theme(struct ax_ctxt* ax, struct ax_theme* thm);
#define AX_ERR_THEME_LOADING 1 #define AX_ERR_THEME_LOADING 1

View File

@ -93,7 +93,6 @@ struct font_list {
struct font_list* next; struct font_list* next;
struct ax_theme* thm; struct ax_theme* thm;
size_t cat; size_t cat;
struct msgq* cb_mq;
}; };
static void load_fonts( static void load_fonts(
@ -123,7 +122,6 @@ void ax__backend_step(struct ax_backend* bac)
l->next = fonts; l->next = fonts;
l->thm = m.theme; l->thm = m.theme;
l->cat = m.category; l->cat = m.category;
l->cb_mq = m.callback_mq;
fonts = l; fonts = l;
break; break;
}); });
@ -150,6 +148,7 @@ static int load_font(
struct rgn* rgn, const char* path, size_t size, struct rgn* rgn, const char* path, size_t size,
struct ax_font_h** out_fh, const char** out_err) struct ax_font_h** out_fh, const char** out_err)
{ {
printf("loading `%s' (size %zu)\n", path, size);
struct ax_font_h* fh = ralloc_typed(rgn, struct ax_font_h, 1); struct ax_font_h* fh = ralloc_typed(rgn, struct ax_font_h, 1);
if ((fh->font = TTF_OpenFont(path, size)) == NULL) { if ((fh->font = TTF_OpenFont(path, size)) == NULL) {
*out_err = TTF_GetError(); *out_err = TTF_GetError();
@ -173,13 +172,7 @@ static void load_fonts(struct ax_backend* bac, struct font_list* fl)
&fh, &err)) != 0) { &fh, &err)) != 0) {
goto fail; goto fail;
} }
bool is_loaded = ax__theme_set_font_handle(thm, fl->cat, fh); ax__theme_set_font_handle(thm, fl->cat, fh);
if (is_loaded) {
struct ax_msg_theme_loaded* m =
msgq_begin_send_typed(fl->cb_mq, ax_msg_theme_loaded);
m->theme = thm;
msgq_end_send(fl->cb_mq);
}
} }
fail: fail:

View File

@ -12,7 +12,6 @@ struct ax_msg_shutdown {
}; };
struct ax_msg_load_font { struct ax_msg_load_font {
struct msgq* callback_mq;
struct ax_theme* theme; struct ax_theme* theme;
int category; int category;
}; };

View File

@ -13,6 +13,11 @@ struct msgq {
pthread_cond_t cv; pthread_cond_t cv;
}; };
struct msgq_list {
struct msgq* mq;
struct msgq_list* next;
};
struct msgq_msg_list { struct msgq_msg_list {
struct msgq_msg_list* next; struct msgq_msg_list* next;
int type; int type;

View File

@ -115,16 +115,11 @@ void ax_end_theme(struct ax_ctxt* ax, struct ax_theme** out_thm)
ax->thmb = NULL; ax->thmb = NULL;
rgn_clear(ax->thmb_rgn); rgn_clear(ax->thmb_rgn);
ax__theme_load(thm, ax__backend_msgq(ax->bac));
if (out_thm != NULL) { if (out_thm != NULL) {
*out_thm = thm; *out_thm = thm;
} }
struct msgq* callback;
UNIMPLEMENTED();
ax__theme_request_load(thm,
ax__backend_msgq(ax->bac),
callback);
} }
void ax_set_theme_color( void ax_set_theme_color(
@ -160,6 +155,18 @@ void ax_set_theme_iconset(
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void ax_theme_wait_until_loaded(struct ax_ctxt* ax, struct ax_theme* thm)
{
struct rgn rgn[1];
rgn_init(rgn, SMALL);
struct msgq* mq = msgq_new(rgn);
ax__theme_on_load(thm, mq);
msgq_begin_recv_and_wait(mq);
MSGQ_RECV_ALL(mq) {}
msgq_end_recv(mq);
rgn_cleanup(rgn);
}
int ax_select_theme(struct ax_ctxt* ax, struct ax_theme* thm) int ax_select_theme(struct ax_ctxt* ax, struct ax_theme* thm)
{ {
ASSERT_NON_NULL(thm, "theme"); ASSERT_NON_NULL(thm, "theme");

View File

@ -95,7 +95,9 @@ struct ax_theme* ax__theme_builder_finish(
dflt_font_path : dflt_font_path :
rstrdup(dst_rgn, thm->font_path[i]); rstrdup(dst_rgn, thm->font_path[i]);
} }
pthread_mutex_init(&thm->handles_mx, NULL); thm->on_load_rgn = rgn_new(dst_rgn, SMALL);
thm->on_load = NULL;
pthread_mutex_init(&thm->mx, NULL);
rgn_pin(dst_rgn, thm, (void*) pthread_mutex_destroy); rgn_pin(dst_rgn, thm, (void*) pthread_mutex_destroy);
return thm; return thm;
} }
@ -114,50 +116,72 @@ static inline bool is_loaded(struct ax_theme* thm)
return true; return true;
} }
static inline void msgq_send_theme_loaded(struct msgq* mq, struct ax_theme* thm)
{
msgq_begin_send_typed(mq, ax_msg_theme_loaded)
->theme = thm;
msgq_end_send(mq);
}
struct ax_font_h* ax__theme_font_handle( struct ax_font_h* ax__theme_font_handle(
struct ax_theme* thm, struct ax_theme* thm,
enum ax_font_cat i) enum ax_font_cat i)
{ {
pthread_mutex_lock(&thm->handles_mx); pthread_mutex_lock(&thm->mx);
struct ax_font_h* h = thm->font_handle[i]; struct ax_font_h* h = thm->font_handle[i];
pthread_mutex_unlock(&thm->handles_mx); pthread_mutex_unlock(&thm->mx);
return h; return h;
} }
bool ax__theme_is_loaded(struct ax_theme* thm) bool ax__theme_is_loaded(struct ax_theme* thm)
{ {
pthread_mutex_lock(&thm->handles_mx); pthread_mutex_lock(&thm->mx);
bool l = is_loaded(thm); bool l = is_loaded(thm);
pthread_mutex_unlock(&thm->handles_mx); pthread_mutex_unlock(&thm->mx);
return l; return l;
} }
bool ax__theme_set_font_handle( void ax__theme_set_font_handle(
struct ax_theme* thm, struct ax_theme* thm,
enum ax_font_cat i, enum ax_font_cat i,
struct ax_font_h* h) struct ax_font_h* h)
{ {
pthread_mutex_lock(&thm->handles_mx); pthread_mutex_lock(&thm->mx);
thm->font_handle[i] = h; thm->font_handle[i] = h;
bool l = is_loaded(thm); if (is_loaded(thm)) {
pthread_mutex_unlock(&thm->handles_mx); while (thm->on_load != NULL) {
return l; msgq_send_theme_loaded(thm->on_load->mq, thm);
thm->on_load = thm->on_load->next;
}
}
pthread_mutex_unlock(&thm->mx);
} }
void ax__theme_request_load( void ax__theme_load(struct ax_theme* thm, struct msgq* req_mq)
struct ax_theme* thm,
struct msgq* req_mq,
struct msgq* res_mq)
{ {
for (size_t i = 0; i < AX_FONT__COUNT; i++) { for (size_t i = 0; i < AX_FONT__COUNT; i++) {
struct ax_msg_load_font* m = msgq_begin_send_typed(req_mq, ax_msg_load_font); struct ax_msg_load_font* m = msgq_begin_send_typed(req_mq, ax_msg_load_font);
m->callback_mq = res_mq;
m->theme = thm; m->theme = thm;
m->category = i; m->category = i;
msgq_end_send(req_mq); msgq_end_send(req_mq);
} }
} }
void ax__theme_on_load(struct ax_theme* thm, struct msgq* res_mq)
{
pthread_mutex_lock(&thm->mx);
if (is_loaded(thm)) {
msgq_send_theme_loaded(res_mq, thm);
} else {
struct msgq_list* l =
ralloc_typed(thm->on_load_rgn, struct msgq_list, 1);
l->mq = res_mq;
l->next = thm->on_load;
thm->on_load = l;
}
pthread_mutex_unlock(&thm->mx);
}
int ax__string_to_color_cat(const char* str, enum ax_color_cat* out_cat) int ax__string_to_color_cat(const char* str, enum ax_color_cat* out_cat)
{ {
enum ax_color_cat val; enum ax_color_cat val;

View File

@ -7,6 +7,7 @@
struct rgn; struct rgn;
struct msgq; struct msgq;
struct msgq_list;
#define THEME_BUILDER_DESIRED_REGION_SIZE (16*1024) #define THEME_BUILDER_DESIRED_REGION_SIZE (16*1024)
@ -43,7 +44,9 @@ struct ax_theme {
size_t font_size[AX_FONT__COUNT]; size_t font_size[AX_FONT__COUNT];
const char* font_path[AX_FONT__COUNT]; const char* font_path[AX_FONT__COUNT];
struct ax_font_h* font_handle[AX_FONT__COUNT]; struct ax_font_h* font_handle[AX_FONT__COUNT];
pthread_mutex_t handles_mx; struct rgn* on_load_rgn;
struct msgq_list* on_load;
pthread_mutex_t mx;
}; };
struct ax_theme_builder { struct ax_theme_builder {
@ -99,14 +102,17 @@ struct ax_font_h* ax__theme_font_handle(
bool ax__theme_is_loaded( bool ax__theme_is_loaded(
struct ax_theme* thm); struct ax_theme* thm);
bool ax__theme_set_font_handle( // returns `true` if the font is now loaded void ax__theme_set_font_handle(
struct ax_theme* thm, struct ax_theme* thm,
enum ax_font_cat i, enum ax_font_cat i,
struct ax_font_h* h); struct ax_font_h* h);
void ax__theme_request_load( void ax__theme_load(
struct ax_theme* thm,
struct msgq* req_mq);
void ax__theme_on_load(
struct ax_theme* thm, struct ax_theme* thm,
struct msgq* req_mq,
struct msgq* res_mq); struct msgq* res_mq);
/* /*

View File

@ -40,7 +40,9 @@ int main(void)
ax_set_logger(ax, 0, false); ax_set_logger(ax, 0, false);
struct ax_theme* thm = make_example_theme(); struct ax_theme* thm = make_example_theme();
(void) thm; ax_theme_wait_until_loaded(ax, thm);
printf("it loaded!\n");
usleep(1000 * 1000 * 2);
/* /*
struct ax_evt evt; struct ax_evt evt;