From a3c18e72f5804051c5111fea5f4fca488fa088ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 4 Jan 2020 19:48:15 +0100 Subject: [PATCH] fdm: add support for hooks Hooks are functions executed just before going into a poll(). Or just after executing all FD handlers, if you like. --- fdm.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ fdm.h | 4 ++++ 2 files changed, 53 insertions(+) diff --git a/fdm.c b/fdm.c index 4592a9e8..9d14dca8 100644 --- a/fdm.c +++ b/fdm.c @@ -21,11 +21,17 @@ struct handler { bool deleted; }; +struct hook { + fdm_hook_t callback; + void *callback_data; +}; + struct fdm { int epoll_fd; bool is_polling; tll(struct handler *) fds; tll(struct handler *) deferred_delete; + tll(struct hook) hooks; }; struct fdm * @@ -43,6 +49,7 @@ fdm_init(void) .is_polling = false, .fds = tll_init(), .deferred_delete = tll_init(), + .hooks = tll_init(), }; return fdm; } @@ -56,11 +63,16 @@ fdm_destroy(struct fdm *fdm) if (tll_length(fdm->fds) > 0) LOG_WARN("FD list not empty"); + if (tll_length(fdm->hooks) > 0) + LOG_WARN("hook list not empty"); + assert(tll_length(fdm->fds) == 0); assert(tll_length(fdm->deferred_delete) == 0); + assert(tll_length(fdm->hooks) == 0); tll_free(fdm->fds); tll_free(fdm->deferred_delete); + tll_free(fdm->hooks); close(fdm->epoll_fd); free(fdm); } @@ -195,6 +207,37 @@ fdm_event_del(struct fdm *fdm, int fd, int events) return false; } +bool +fdm_hook_add(struct fdm *fdm, fdm_hook_t hook, void *data) +{ +#if defined(_DEBUG) + tll_foreach(fdm->hooks, it) { + if (it->item.callback == hook) { + LOG_ERR("hook=%p already registered", hook); + return false; + } + } +#endif + + tll_push_back(fdm->hooks, ((struct hook){hook, data})); + return true; +} + +bool +fdm_hook_del(struct fdm *fdm, fdm_hook_t hook) +{ + tll_foreach(fdm->hooks, it) { + if (it->item.callback != hook) + continue; + + tll_remove(fdm->hooks, it); + return true; + } + + LOG_WARN("hook=%p not registered, hook", hook); + return false; +} + bool fdm_poll(struct fdm *fdm) { @@ -204,6 +247,12 @@ fdm_poll(struct fdm *fdm) return false; } + tll_foreach(fdm->hooks, it) { + LOG_DBG("executing hook %p(fdm=%p, data=%p)", + it->item.callback, fdm, it->item.callback_data); + it->item.callback(fdm, it->item.callback_data); + } + struct epoll_event events[tll_length(fdm->fds)]; int r = epoll_wait(fdm->epoll_fd, events, tll_length(fdm->fds), -1); diff --git a/fdm.h b/fdm.h index 62d73ded..62f7616f 100644 --- a/fdm.h +++ b/fdm.h @@ -5,6 +5,7 @@ struct fdm; typedef bool (*fdm_handler_t)(struct fdm *fdm, int fd, int events, void *data); +typedef void (*fdm_hook_t)(struct fdm *fdm, void *data); struct fdm *fdm_init(void); void fdm_destroy(struct fdm *fdm); @@ -16,4 +17,7 @@ bool fdm_del_no_close(struct fdm *fdm, int fd); bool fdm_event_add(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_del(struct fdm *fdm, fdm_hook_t hook); + bool fdm_poll(struct fdm *fdm);