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 <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2013-01-13 11:54:29 +01:00
parent 5ee2338b60
commit 1ef166c12c
6 changed files with 51 additions and 22 deletions

View File

@ -2297,6 +2297,7 @@ void ev_eloop_unregister_child_cb(struct ev_eloop *loop, ev_child_cb cb,
* @eloop: event loop * @eloop: event loop
* @cb: user-supplied callback * @cb: user-supplied callback
* @data: user-supplied data * @data: user-supplied data
* @flags: flags
* *
* This register a new idle-source with the given callback and data. @cb must * This register a new idle-source with the given callback and data. @cb must
* not be NULL!. * 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. * Returns: 0 on success, negative error code on failure.
*/ */
int ev_eloop_register_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb, int ev_eloop_register_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb,
void *data) void *data, unsigned int flags)
{ {
int ret; int ret;
bool os = flags & EV_ONESHOT;
if (!eloop) if (!eloop || (flags & ~EV_IDLE_ALL))
return -EINVAL; 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) if (ret)
return ret; return ret;
@ -2330,6 +2336,7 @@ int ev_eloop_register_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb,
* @eloop: event loop * @eloop: event loop
* @cb: user-supplied callback * @cb: user-supplied callback
* @data: user-supplied data * @data: user-supplied data
* @flags: flags
* *
* This removes an idle-source. The arguments must be the same as for the * 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, * 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. * they are identical.
*/ */
void ev_eloop_unregister_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb, 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; 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);
} }
/* /*

View File

@ -262,10 +262,17 @@ void ev_eloop_unregister_child_cb(struct ev_eloop *loop, ev_child_cb cb,
/* idle sources */ /* 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, 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 ev_eloop_unregister_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb,
void *data); void *data, unsigned int flags);
/* pre dispatch callbacks */ /* pre dispatch callbacks */

View 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) \ #define shl_hook_add_cast(hook, cb, data, oneshot) \
shl_hook_add((hook), (shl_hook_cb)(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) \ #define shl_hook_rm_cast(hook, cb, data) \
shl_hook_rm((hook), (shl_hook_cb)(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_hook_entry {
struct shl_dlist list; struct shl_dlist list;

View File

@ -475,7 +475,7 @@ static void intro_idle_event(struct ev_eloop *eloop, void *unused, void *data)
int ret; int ret;
vfb->pending_intro = false; 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); ret = display_new(&disp, &fbdev_display_ops);
if (ret) { if (ret) {
@ -514,7 +514,8 @@ static int video_init(struct uterm_video *video, const char *node)
goto err_free; 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) { if (ret) {
log_error("cannot register idle event: %d", ret); log_error("cannot register idle event: %d", ret);
goto err_node; goto err_node;
@ -538,7 +539,7 @@ static void video_destroy(struct uterm_video *video)
if (vfb->pending_intro) if (vfb->pending_intro)
ev_eloop_unregister_idle_cb(video->eloop, intro_idle_event, ev_eloop_unregister_idle_cb(video->eloop, intro_idle_event,
video); video, EV_NORMAL);
free(vfb->node); free(vfb->node);
free(vfb); free(vfb);

View 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); log_debug("enter VT %d %p during startup", vt->real_num, vt);
vt->real_delayed = false; 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); 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) { if (vt->real_delayed) {
vt->real_delayed = false; 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) { } else if (vt->active) {
log_warning("activating VT %d even though it's already active", log_warning("activating VT %d even though it's already active",
vt->real_num); vt->real_num);
@ -237,7 +238,8 @@ static void real_sig_leave(struct uterm_vt *vt, struct signalfd_siginfo *info)
if (vt->real_delayed) { if (vt->real_delayed) {
vt->real_delayed = false; 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); uterm_input_sleep(vt->input);
} else if (!active) { } else if (!active) {
log_warning("deactivating VT %d even though it's not 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) { if (vts.v_active == vt->real_num) {
ret = ev_eloop_register_idle_cb(vt->vtm->eloop, real_delayed, ret = ev_eloop_register_idle_cb(vt->vtm->eloop, real_delayed,
vt); vt, EV_NORMAL);
if (ret) { if (ret) {
log_error("cannot register idle cb for VT switch"); log_error("cannot register idle cb for VT switch");
goto err_kbdmode; goto err_kbdmode;
@ -417,7 +419,8 @@ static void real_close(struct uterm_vt *vt)
if (vt->real_delayed) { if (vt->real_delayed) {
vt->real_delayed = false; 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); uterm_input_sleep(vt->input);
} else if (vt->active) { } else if (vt->active) {
uterm_input_sleep(vt->input); uterm_input_sleep(vt->input);

View File

@ -1423,7 +1423,8 @@ static void do_frame(struct wlt_window *wnd)
bool force; bool force;
wnd->idle_pending = false; 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) { if (wnd->need_resize) {
force = wnd->need_redraw; force = wnd->need_redraw;
@ -1501,7 +1502,8 @@ static void schedule_frame(struct wlt_window *wnd)
if (wnd->need_frame || wnd->idle_pending) if (wnd->need_frame || wnd->idle_pending)
return; 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) if (ret)
log_error("cannot schedule idle callback: %d", ret); log_error("cannot schedule idle callback: %d", ret);
else else
@ -1537,7 +1539,7 @@ static void close_window(struct ev_eloop *eloop, void *unused, void *data)
{ {
struct wlt_window *wnd = 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; wnd->close_pending = false;
if (wnd->close_cb) if (wnd->close_cb)
@ -1631,9 +1633,10 @@ void wlt_window_unref(struct wlt_window *wnd)
if (wnd->close_pending) if (wnd->close_pending)
ev_eloop_unregister_idle_cb(wnd->disp->eloop, close_window, ev_eloop_unregister_idle_cb(wnd->disp->eloop, close_window,
wnd); wnd, EV_NORMAL);
if (wnd->idle_pending) 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); shl_dlist_unlink(&wnd->list);
if (wnd->w_frame) if (wnd->w_frame)
wl_callback_destroy(wnd->w_frame); wl_callback_destroy(wnd->w_frame);
@ -1790,7 +1793,8 @@ void wlt_window_close(struct wlt_window *wnd)
return; return;
wnd->close_pending = true; 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) void wlt_window_toggle_maximize(struct wlt_window *wnd)