fdm: add hook priorities

There are now three hook priorities: low, normal, high.

High priority hooks are executed *first*. Normal next, and last the
low priority hooks.

The renderer's terminal refresh hook now runs as a normal priority
hook.
This commit is contained in:
Daniel Eklöf 2020-01-04 23:26:27 +01:00
parent 5ec447697c
commit 6534f64e6a
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 70 additions and 18 deletions

70
fdm.c
View file

@ -26,12 +26,16 @@ struct hook {
void *callback_data; void *callback_data;
}; };
typedef tll(struct hook) hooks_t;
struct fdm { struct fdm {
int epoll_fd; int epoll_fd;
bool is_polling; bool is_polling;
tll(struct handler *) fds; tll(struct handler *) fds;
tll(struct handler *) deferred_delete; tll(struct handler *) deferred_delete;
tll(struct hook) hooks; hooks_t hooks_low;
hooks_t hooks_normal;
hooks_t hooks_high;
}; };
struct fdm * struct fdm *
@ -49,7 +53,9 @@ fdm_init(void)
.is_polling = false, .is_polling = false,
.fds = tll_init(), .fds = tll_init(),
.deferred_delete = tll_init(), .deferred_delete = tll_init(),
.hooks = tll_init(), .hooks_low = tll_init(),
.hooks_normal = tll_init(),
.hooks_high = tll_init(),
}; };
return fdm; return fdm;
} }
@ -63,16 +69,24 @@ fdm_destroy(struct fdm *fdm)
if (tll_length(fdm->fds) > 0) if (tll_length(fdm->fds) > 0)
LOG_WARN("FD list not empty"); LOG_WARN("FD list not empty");
if (tll_length(fdm->hooks) > 0) if (tll_length(fdm->hooks_low) > 0 ||
tll_length(fdm->hooks_normal) > 0 ||
tll_length(fdm->hooks_high) > 0)
{
LOG_WARN("hook list not empty"); LOG_WARN("hook list not empty");
}
assert(tll_length(fdm->fds) == 0); assert(tll_length(fdm->fds) == 0);
assert(tll_length(fdm->deferred_delete) == 0); assert(tll_length(fdm->deferred_delete) == 0);
assert(tll_length(fdm->hooks) == 0); assert(tll_length(fdm->hooks_low) == 0);
assert(tll_length(fdm->hooks_normal) == 0);
assert(tll_length(fdm->hooks_high) == 0);
tll_free(fdm->fds); tll_free(fdm->fds);
tll_free(fdm->deferred_delete); tll_free(fdm->deferred_delete);
tll_free(fdm->hooks); tll_free(fdm->hooks_low);
tll_free(fdm->hooks_normal);
tll_free(fdm->hooks_high);
close(fdm->epoll_fd); close(fdm->epoll_fd);
free(fdm); free(fdm);
} }
@ -207,11 +221,27 @@ fdm_event_del(struct fdm *fdm, int fd, int events)
return false; return false;
} }
bool static hooks_t *
fdm_hook_add(struct fdm *fdm, fdm_hook_t hook, void *data) hook_priority_to_list(struct fdm *fdm, enum fdm_hook_priority priority)
{ {
switch (priority) {
case FDM_HOOK_PRIORITY_LOW: return &fdm->hooks_low;
case FDM_HOOK_PRIORITY_NORMAL: return &fdm->hooks_normal;
case FDM_HOOK_PRIORITY_HIGH: return &fdm->hooks_high;
}
assert(false);
return NULL;
}
bool
fdm_hook_add(struct fdm *fdm, fdm_hook_t hook, void *data,
enum fdm_hook_priority priority)
{
hooks_t *hooks = hook_priority_to_list(fdm, priority);
#if defined(_DEBUG) #if defined(_DEBUG)
tll_foreach(fdm->hooks, it) { tll_foreach(*hooks, it) {
if (it->item.callback == hook) { if (it->item.callback == hook) {
LOG_ERR("hook=%p already registered", hook); LOG_ERR("hook=%p already registered", hook);
return false; return false;
@ -219,18 +249,20 @@ fdm_hook_add(struct fdm *fdm, fdm_hook_t hook, void *data)
} }
#endif #endif
tll_push_back(fdm->hooks, ((struct hook){hook, data})); tll_push_back(*hooks, ((struct hook){hook, data}));
return true; return true;
} }
bool bool
fdm_hook_del(struct fdm *fdm, fdm_hook_t hook) fdm_hook_del(struct fdm *fdm, fdm_hook_t hook, enum fdm_hook_priority priority)
{ {
tll_foreach(fdm->hooks, it) { hooks_t *hooks = hook_priority_to_list(fdm, priority);
tll_foreach(*hooks, it) {
if (it->item.callback != hook) if (it->item.callback != hook)
continue; continue;
tll_remove(fdm->hooks, it); tll_remove(*hooks, it);
return true; return true;
} }
@ -247,8 +279,18 @@ fdm_poll(struct fdm *fdm)
return false; return false;
} }
tll_foreach(fdm->hooks, it) { tll_foreach(fdm->hooks_high, it) {
LOG_DBG("executing hook %p(fdm=%p, data=%p)", LOG_DBG("executing high priority hook %p(fdm=%p, data=%p)",
it->item.callback, fdm, it->item.callback_data);
it->item.callback(fdm, it->item.callback_data);
}
tll_foreach(fdm->hooks_normal, it) {
LOG_DBG("executing normal priority hook %p(fdm=%p, data=%p)",
it->item.callback, fdm, it->item.callback_data);
it->item.callback(fdm, it->item.callback_data);
}
tll_foreach(fdm->hooks_low, it) {
LOG_DBG("executing low priority hook %p(fdm=%p, data=%p)",
it->item.callback, fdm, it->item.callback_data); it->item.callback, fdm, it->item.callback_data);
it->item.callback(fdm, it->item.callback_data); it->item.callback(fdm, it->item.callback_data);
} }

11
fdm.h
View file

@ -7,6 +7,12 @@ struct fdm;
typedef bool (*fdm_handler_t)(struct fdm *fdm, int fd, int events, void *data); typedef bool (*fdm_handler_t)(struct fdm *fdm, int fd, int events, void *data);
typedef void (*fdm_hook_t)(struct fdm *fdm, void *data); typedef void (*fdm_hook_t)(struct fdm *fdm, void *data);
enum fdm_hook_priority {
FDM_HOOK_PRIORITY_LOW,
FDM_HOOK_PRIORITY_NORMAL,
FDM_HOOK_PRIORITY_HIGH
};
struct fdm *fdm_init(void); struct fdm *fdm_init(void);
void fdm_destroy(struct fdm *fdm); void fdm_destroy(struct fdm *fdm);
@ -17,7 +23,8 @@ bool fdm_del_no_close(struct fdm *fdm, int fd);
bool fdm_event_add(struct fdm *fdm, int fd, int events); bool fdm_event_add(struct fdm *fdm, int fd, int events);
bool fdm_event_del(struct fdm *fdm, int fd, int events); bool fdm_event_del(struct fdm *fdm, int fd, int events);
bool fdm_hook_add(struct fdm *fdm, fdm_hook_t hook, void *data); bool fdm_hook_add(struct fdm *fdm, fdm_hook_t hook, void *data,
bool fdm_hook_del(struct fdm *fdm, fdm_hook_t hook); enum fdm_hook_priority priority);
bool fdm_hook_del(struct fdm *fdm, fdm_hook_t hook, enum fdm_hook_priority priority);
bool fdm_poll(struct fdm *fdm); bool fdm_poll(struct fdm *fdm);

View file

@ -45,7 +45,9 @@ render_init(struct fdm *fdm, struct wayland *wayl)
.wayl = wayl, .wayl = wayl,
}; };
if (!fdm_hook_add(fdm, &fdm_hook_refresh_pending_terminals, renderer)) { if (!fdm_hook_add(fdm, &fdm_hook_refresh_pending_terminals, renderer,
FDM_HOOK_PRIORITY_NORMAL))
{
LOG_ERR("failed to register FDM hook"); LOG_ERR("failed to register FDM hook");
free(renderer); free(renderer);
return NULL; return NULL;
@ -60,7 +62,8 @@ render_destroy(struct renderer *renderer)
if (renderer == NULL) if (renderer == NULL)
return; return;
fdm_hook_del(renderer->fdm, &fdm_hook_refresh_pending_terminals); fdm_hook_del(renderer->fdm, &fdm_hook_refresh_pending_terminals,
FDM_HOOK_PRIORITY_NORMAL);
} }
static void __attribute__((destructor)) static void __attribute__((destructor))