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
* @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);
}
/*

View 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 */

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) \
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;

View 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);

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);
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);

View 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)