From 1ef166c12cc259cd72250c0f28da4ab4529d90bf Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 13 Jan 2013 11:54:29 +0100 Subject: [PATCH] eloop: add EV_ONESHOT and EV_SINGLE flags for idle sources EV_ONESHOT will remove idle sources once they have been processed and EV_SINGLE will only register the source if it hasn't been registered, yet. For source removal EV_ONESHOT has no effect but EV_SINGLE causes all events with this cb+data combination to be removed. Signed-off-by: David Herrmann --- src/eloop.c | 22 ++++++++++++++++------ src/eloop.h | 11 +++++++++-- src/shl_hook.h | 4 ++++ src/uterm_fbdev_video.c | 7 ++++--- src/uterm_vt.c | 13 ++++++++----- src/wlt_toolkit.c | 16 ++++++++++------ 6 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/eloop.c b/src/eloop.c index c9a7c05..d3e09c4 100644 --- a/src/eloop.c +++ b/src/eloop.c @@ -2297,6 +2297,7 @@ void ev_eloop_unregister_child_cb(struct ev_eloop *loop, ev_child_cb cb, * @eloop: event loop * @cb: user-supplied callback * @data: user-supplied data + * @flags: flags * * This register a new idle-source with the given callback and data. @cb must * not be NULL!. @@ -2304,14 +2305,19 @@ void ev_eloop_unregister_child_cb(struct ev_eloop *loop, ev_child_cb cb, * Returns: 0 on success, negative error code on failure. */ int ev_eloop_register_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb, - void *data) + void *data, unsigned int flags) { int ret; + bool os = flags & EV_ONESHOT; - if (!eloop) + if (!eloop || (flags & ~EV_IDLE_ALL)) return -EINVAL; - ret = shl_hook_add_cast(eloop->idlers, cb, data, false); + if ((flags & EV_SINGLE)) + ret = shl_hook_add_single_cast(eloop->idlers, cb, data, os); + else + ret = shl_hook_add_cast(eloop->idlers, cb, data, os); + if (ret) return ret; @@ -2330,6 +2336,7 @@ int ev_eloop_register_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb, * @eloop: event loop * @cb: user-supplied callback * @data: user-supplied data + * @flags: flags * * This removes an idle-source. The arguments must be the same as for the * ev_eloop_register_idle_cb() call. If two identical callbacks are registered, @@ -2337,12 +2344,15 @@ int ev_eloop_register_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb, * they are identical. */ void ev_eloop_unregister_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb, - void *data) + void *data, unsigned int flags) { - if (!eloop) + if (!eloop || (flags & ~EV_IDLE_ALL)) return; - shl_hook_rm_cast(eloop->idlers, cb, data); + if (flags & EV_SINGLE) + shl_hook_rm_all_cast(eloop->idlers, cb, data); + else + shl_hook_rm_cast(eloop->idlers, cb, data); } /* diff --git a/src/eloop.h b/src/eloop.h index c984dc9..eee7f08 100644 --- a/src/eloop.h +++ b/src/eloop.h @@ -262,10 +262,17 @@ void ev_eloop_unregister_child_cb(struct ev_eloop *loop, ev_child_cb cb, /* idle sources */ +enum ev_idle_flags { + EV_NORMAL = 0x00, + EV_ONESHOT = 0x01, + EV_SINGLE = 0x02, + EV_IDLE_ALL = EV_ONESHOT | EV_SINGLE, +}; + int ev_eloop_register_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb, - void *data); + void *data, unsigned int flags); void ev_eloop_unregister_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb, - void *data); + void *data, unsigned int flags); /* pre dispatch callbacks */ diff --git a/src/shl_hook.h b/src/shl_hook.h index f1a4454..be64b74 100644 --- a/src/shl_hook.h +++ b/src/shl_hook.h @@ -45,8 +45,12 @@ typedef void (*shl_hook_cb) (void *parent, void *arg, void *data); #define shl_hook_add_cast(hook, cb, data, oneshot) \ shl_hook_add((hook), (shl_hook_cb)(cb), (data), (oneshot)) +#define shl_hook_add_single_cast(hook, cb, data, oneshot) \ + shl_hook_add_single((hook), (shl_hook_cb)(cb), (data), (oneshot)) #define shl_hook_rm_cast(hook, cb, data) \ shl_hook_rm((hook), (shl_hook_cb)(cb), (data)) +#define shl_hook_rm_all_cast(hook, cb, data) \ + shl_hook_rm_all((hook), (shl_hook_cb)(cb), (data)) struct shl_hook_entry { struct shl_dlist list; diff --git a/src/uterm_fbdev_video.c b/src/uterm_fbdev_video.c index bc799f6..f1b1c06 100644 --- a/src/uterm_fbdev_video.c +++ b/src/uterm_fbdev_video.c @@ -475,7 +475,7 @@ static void intro_idle_event(struct ev_eloop *eloop, void *unused, void *data) int ret; vfb->pending_intro = false; - ev_eloop_unregister_idle_cb(eloop, intro_idle_event, data); + ev_eloop_unregister_idle_cb(eloop, intro_idle_event, data, EV_NORMAL); ret = display_new(&disp, &fbdev_display_ops); if (ret) { @@ -514,7 +514,8 @@ static int video_init(struct uterm_video *video, const char *node) goto err_free; } - ret = ev_eloop_register_idle_cb(video->eloop, intro_idle_event, video); + ret = ev_eloop_register_idle_cb(video->eloop, intro_idle_event, video, + EV_NORMAL); if (ret) { log_error("cannot register idle event: %d", ret); goto err_node; @@ -538,7 +539,7 @@ static void video_destroy(struct uterm_video *video) if (vfb->pending_intro) ev_eloop_unregister_idle_cb(video->eloop, intro_idle_event, - video); + video, EV_NORMAL); free(vfb->node); free(vfb); diff --git a/src/uterm_vt.c b/src/uterm_vt.c index 92a9b36..4b6fdd1 100644 --- a/src/uterm_vt.c +++ b/src/uterm_vt.c @@ -177,7 +177,7 @@ static void real_delayed(struct ev_eloop *eloop, void *unused, void *data) log_debug("enter VT %d %p during startup", vt->real_num, vt); vt->real_delayed = false; - ev_eloop_unregister_idle_cb(eloop, real_delayed, vt); + ev_eloop_unregister_idle_cb(eloop, real_delayed, vt, EV_NORMAL); vt_call_activate(vt); } @@ -197,7 +197,8 @@ static void real_sig_enter(struct uterm_vt *vt, struct signalfd_siginfo *info) if (vt->real_delayed) { vt->real_delayed = false; - ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt); + ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt, + EV_NORMAL); } else if (vt->active) { log_warning("activating VT %d even though it's already active", vt->real_num); @@ -237,7 +238,8 @@ static void real_sig_leave(struct uterm_vt *vt, struct signalfd_siginfo *info) if (vt->real_delayed) { vt->real_delayed = false; - ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt); + ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt, + EV_NORMAL); uterm_input_sleep(vt->input); } else if (!active) { log_warning("deactivating VT %d even though it's not active", @@ -372,7 +374,7 @@ static int real_open(struct uterm_vt *vt, const char *vt_name) if (vts.v_active == vt->real_num) { ret = ev_eloop_register_idle_cb(vt->vtm->eloop, real_delayed, - vt); + vt, EV_NORMAL); if (ret) { log_error("cannot register idle cb for VT switch"); goto err_kbdmode; @@ -417,7 +419,8 @@ static void real_close(struct uterm_vt *vt) if (vt->real_delayed) { vt->real_delayed = false; - ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt); + ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt, + EV_NORMAL); uterm_input_sleep(vt->input); } else if (vt->active) { uterm_input_sleep(vt->input); diff --git a/src/wlt_toolkit.c b/src/wlt_toolkit.c index 7ae6fdc..41f6d0c 100644 --- a/src/wlt_toolkit.c +++ b/src/wlt_toolkit.c @@ -1423,7 +1423,8 @@ static void do_frame(struct wlt_window *wnd) bool force; wnd->idle_pending = false; - ev_eloop_unregister_idle_cb(wnd->disp->eloop, idle_frame, wnd); + ev_eloop_unregister_idle_cb(wnd->disp->eloop, idle_frame, wnd, + EV_NORMAL); if (wnd->need_resize) { force = wnd->need_redraw; @@ -1501,7 +1502,8 @@ static void schedule_frame(struct wlt_window *wnd) if (wnd->need_frame || wnd->idle_pending) return; - ret = ev_eloop_register_idle_cb(wnd->disp->eloop, idle_frame, wnd); + ret = ev_eloop_register_idle_cb(wnd->disp->eloop, idle_frame, wnd, + EV_NORMAL); if (ret) log_error("cannot schedule idle callback: %d", ret); else @@ -1537,7 +1539,7 @@ static void close_window(struct ev_eloop *eloop, void *unused, void *data) { struct wlt_window *wnd = data; - ev_eloop_unregister_idle_cb(eloop, close_window, wnd); + ev_eloop_unregister_idle_cb(eloop, close_window, wnd, EV_NORMAL); wnd->close_pending = false; if (wnd->close_cb) @@ -1631,9 +1633,10 @@ void wlt_window_unref(struct wlt_window *wnd) if (wnd->close_pending) ev_eloop_unregister_idle_cb(wnd->disp->eloop, close_window, - wnd); + wnd, EV_NORMAL); if (wnd->idle_pending) - ev_eloop_unregister_idle_cb(wnd->disp->eloop, idle_frame, wnd); + ev_eloop_unregister_idle_cb(wnd->disp->eloop, idle_frame, wnd, + EV_NORMAL); shl_dlist_unlink(&wnd->list); if (wnd->w_frame) wl_callback_destroy(wnd->w_frame); @@ -1790,7 +1793,8 @@ void wlt_window_close(struct wlt_window *wnd) return; wnd->close_pending = true; - ev_eloop_register_idle_cb(wnd->disp->eloop, close_window, wnd); + ev_eloop_register_idle_cb(wnd->disp->eloop, close_window, wnd, + EV_NORMAL); } void wlt_window_toggle_maximize(struct wlt_window *wnd)