eloop: add EV_ONESHOT and EV_SINGLE flags for idle sources
authorDavid Herrmann <dh.herrmann@googlemail.com>
Sun, 13 Jan 2013 10:54:29 +0000 (11:54 +0100)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Sun, 13 Jan 2013 10:54:29 +0000 (11:54 +0100)
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 <dh.herrmann@googlemail.com>
src/eloop.c
src/eloop.h
src/shl_hook.h
src/uterm_fbdev_video.c
src/uterm_vt.c
src/wlt_toolkit.c

index c9a7c05..d3e09c4 100644 (file)
@@ -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);
 }
 
 /*
index c984dc9..eee7f08 100644 (file)
@@ -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 */
 
index f1a4454..be64b74 100644 (file)
@@ -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;
index bc799f6..f1b1c06 100644 (file)
@@ -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);
index 92a9b36..4b6fdd1 100644 (file)
@@ -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);
index 7ae6fdc..41f6d0c 100644 (file)
@@ -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)