diff --git a/src/ax.h b/src/ax.h index 78223b7..9c3667c 100644 --- a/src/ax.h +++ b/src/ax.h @@ -35,6 +35,7 @@ void ax_set_theme_font( void ax_set_theme_iconset( 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); #define AX_ERR_THEME_LOADING 1 diff --git a/src/backend/sdl.c b/src/backend/sdl.c index db28601..8e5112a 100644 --- a/src/backend/sdl.c +++ b/src/backend/sdl.c @@ -93,7 +93,6 @@ struct font_list { struct font_list* next; struct ax_theme* thm; size_t cat; - struct msgq* cb_mq; }; static void load_fonts( @@ -123,7 +122,6 @@ void ax__backend_step(struct ax_backend* bac) l->next = fonts; l->thm = m.theme; l->cat = m.category; - l->cb_mq = m.callback_mq; fonts = l; break; }); @@ -150,6 +148,7 @@ static int load_font( struct rgn* rgn, const char* path, size_t size, 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); if ((fh->font = TTF_OpenFont(path, size)) == NULL) { *out_err = TTF_GetError(); @@ -173,13 +172,7 @@ static void load_fonts(struct ax_backend* bac, struct font_list* fl) &fh, &err)) != 0) { goto fail; } - bool is_loaded = 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); - } + ax__theme_set_font_handle(thm, fl->cat, fh); } fail: diff --git a/src/concurrent/msg.h b/src/concurrent/msg.h index 94c2805..ca5ff7d 100644 --- a/src/concurrent/msg.h +++ b/src/concurrent/msg.h @@ -12,7 +12,6 @@ struct ax_msg_shutdown { }; struct ax_msg_load_font { - struct msgq* callback_mq; struct ax_theme* theme; int category; }; diff --git a/src/concurrent/msgq.h b/src/concurrent/msgq.h index 907acae..894c2d0 100644 --- a/src/concurrent/msgq.h +++ b/src/concurrent/msgq.h @@ -13,6 +13,11 @@ struct msgq { pthread_cond_t cv; }; +struct msgq_list { + struct msgq* mq; + struct msgq_list* next; +}; + struct msgq_msg_list { struct msgq_msg_list* next; int type; diff --git a/src/ctxt/ctxt.c b/src/ctxt/ctxt.c index 4a697dc..365dcc4 100644 --- a/src/ctxt/ctxt.c +++ b/src/ctxt/ctxt.c @@ -115,16 +115,11 @@ void ax_end_theme(struct ax_ctxt* ax, struct ax_theme** out_thm) ax->thmb = NULL; rgn_clear(ax->thmb_rgn); + ax__theme_load(thm, ax__backend_msgq(ax->bac)); + if (out_thm != NULL) { *out_thm = thm; } - - struct msgq* callback; - UNIMPLEMENTED(); - - ax__theme_request_load(thm, - ax__backend_msgq(ax->bac), - callback); } void ax_set_theme_color( @@ -160,6 +155,18 @@ void ax_set_theme_iconset( 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) { ASSERT_NON_NULL(thm, "theme"); diff --git a/src/ctxt/theme.c b/src/ctxt/theme.c index d631f68..8c119ec 100644 --- a/src/ctxt/theme.c +++ b/src/ctxt/theme.c @@ -95,7 +95,9 @@ struct ax_theme* ax__theme_builder_finish( dflt_font_path : 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); return thm; } @@ -114,50 +116,72 @@ static inline bool is_loaded(struct ax_theme* thm) 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_theme* thm, 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]; - pthread_mutex_unlock(&thm->handles_mx); + pthread_mutex_unlock(&thm->mx); return h; } 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); - pthread_mutex_unlock(&thm->handles_mx); + pthread_mutex_unlock(&thm->mx); return l; } -bool ax__theme_set_font_handle( +void ax__theme_set_font_handle( struct ax_theme* thm, enum ax_font_cat i, struct ax_font_h* h) { - pthread_mutex_lock(&thm->handles_mx); + pthread_mutex_lock(&thm->mx); thm->font_handle[i] = h; - bool l = is_loaded(thm); - pthread_mutex_unlock(&thm->handles_mx); - return l; + if (is_loaded(thm)) { + while (thm->on_load != NULL) { + 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( - struct ax_theme* thm, - struct msgq* req_mq, - struct msgq* res_mq) +void ax__theme_load(struct ax_theme* thm, struct msgq* req_mq) { 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); - m->callback_mq = res_mq; m->theme = thm; m->category = i; 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) { enum ax_color_cat val; diff --git a/src/ctxt/theme.h b/src/ctxt/theme.h index b69348d..f4ad927 100644 --- a/src/ctxt/theme.h +++ b/src/ctxt/theme.h @@ -7,6 +7,7 @@ struct rgn; struct msgq; +struct msgq_list; #define THEME_BUILDER_DESIRED_REGION_SIZE (16*1024) @@ -43,7 +44,9 @@ struct ax_theme { size_t font_size[AX_FONT__COUNT]; const char* font_path[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 { @@ -99,14 +102,17 @@ struct ax_font_h* ax__theme_font_handle( bool ax__theme_is_loaded( 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, enum ax_font_cat i, 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 msgq* req_mq, struct msgq* res_mq); /* diff --git a/test/main.c b/test/main.c index 90519f9..714c353 100644 --- a/test/main.c +++ b/test/main.c @@ -40,7 +40,9 @@ int main(void) ax_set_logger(ax, 0, false); 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;