eloop: convert idle sources to hooks

Instead if implementing complex idle sources we now provide a hook so
other subsystems can register callbacks.

This simplifies the code a lot and doesn't drop any major functionality.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-05-17 18:35:00 +02:00
parent 83ed40f089
commit 3219b9ccfd
3 changed files with 49 additions and 152 deletions

View File

@ -56,10 +56,8 @@ struct ev_eloop {
unsigned long ref;
struct ev_fd *fd;
struct ev_idle *idle_list;
struct ev_idle *cur_idle;
struct kmscon_dlist sig_list;
struct kmscon_hook *idlers;
struct epoll_event *cur_fds;
size_t cur_fds_cnt;
@ -102,16 +100,6 @@ struct ev_signal_shared {
struct kmscon_hook *hook;
};
struct ev_idle {
unsigned long ref;
struct ev_eloop *loop;
struct ev_idle *next;
struct ev_idle *prev;
ev_idle_cb cb;
void *data;
};
/*
* Shared signals
*/
@ -260,10 +248,14 @@ int ev_eloop_new(struct ev_eloop **out)
loop->ref = 1;
kmscon_dlist_init(&loop->sig_list);
ret = kmscon_hook_new(&loop->idlers);
if (ret)
goto err_free;
loop->efd = epoll_create1(EPOLL_CLOEXEC);
if (loop->efd < 0) {
ret = -errno;
goto err_free;
goto err_idlers;
}
ret = ev_fd_new(&loop->fd, loop->efd, EV_READABLE, eloop_event, loop);
@ -276,6 +268,8 @@ int ev_eloop_new(struct ev_eloop **out)
err_close:
close(loop->efd);
err_idlers:
kmscon_hook_free(loop->idlers);
err_free:
free(loop);
return ret;
@ -307,6 +301,7 @@ void ev_eloop_unref(struct ev_eloop *loop)
ev_fd_unref(loop->fd);
close(loop->efd);
kmscon_hook_free(loop->idlers);
free(loop);
}
@ -333,12 +328,7 @@ int ev_eloop_dispatch(struct ev_eloop *loop, int timeout)
return -EINVAL;
/* dispatch idle events */
loop->cur_idle = loop->idle_list;
while (loop->cur_idle) {
loop->cur_idle->cb(loop->cur_idle, loop->cur_idle->data);
if (loop->cur_idle)
loop->cur_idle = loop->cur_idle->next;
}
kmscon_hook_call(loop->idlers, loop, NULL);
/* dispatch fd events */
count = epoll_wait(loop->efd, ep, 32, timeout);
@ -1018,124 +1008,9 @@ void ev_eloop_rm_counter(struct ev_counter *cnt)
}
/*
* Idle sources
* Shared signals
*/
int ev_idle_new(struct ev_idle **out)
{
struct ev_idle *idle;
if (!out)
return -EINVAL;
idle = malloc(sizeof(*idle));
if (!idle)
return -ENOMEM;
memset(idle, 0, sizeof(*idle));
idle->ref = 1;
*out = idle;
return 0;
}
void ev_idle_ref(struct ev_idle *idle)
{
if (!idle)
return;
++idle->ref;
}
void ev_idle_unref(struct ev_idle *idle)
{
if (!idle || !idle->ref || --idle->ref)
return;
free(idle);
}
int ev_eloop_new_idle(struct ev_eloop *loop, struct ev_idle **out,
ev_idle_cb cb, void *data)
{
struct ev_idle *idle;
int ret;
if (!out || !loop || !cb)
return -EINVAL;
ret = ev_idle_new(&idle);
if (ret)
return ret;
ret = ev_eloop_add_idle(loop, idle, cb, data);
if (ret) {
ev_idle_unref(idle);
return ret;
}
ev_idle_unref(idle);
*out = idle;
return 0;
}
int ev_eloop_add_idle(struct ev_eloop *loop, struct ev_idle *idle,
ev_idle_cb cb, void *data)
{
if (!loop || !idle || !cb)
return -EINVAL;
if (idle->next || idle->prev || idle->loop)
return -EALREADY;
idle->next = loop->idle_list;
if (idle->next)
idle->next->prev = idle;
loop->idle_list = idle;
idle->loop = loop;
idle->cb = cb;
idle->data = data;
ev_idle_ref(idle);
ev_eloop_ref(loop);
return 0;
}
void ev_eloop_rm_idle(struct ev_idle *idle)
{
struct ev_eloop *loop;
if (!idle || !idle->loop)
return;
loop = idle->loop;
/*
* If the loop is currently dispatching, we need to check whether we are
* the current element and correctly set it to the next element.
*/
if (loop->cur_idle == idle)
loop->cur_idle = idle->next;
if (idle->prev)
idle->prev->next = idle->next;
if (idle->next)
idle->next->prev = idle->prev;
if (loop->idle_list == idle)
loop->idle_list = idle->next;
idle->next = NULL;
idle->prev = NULL;
idle->loop = NULL;
idle->cb = NULL;
idle->data = NULL;
ev_idle_unref(idle);
ev_eloop_unref(loop);
}
int ev_eloop_register_signal_cb(struct ev_eloop *loop, int signum,
ev_signal_shared_cb cb, void *data)
{
@ -1180,3 +1055,25 @@ void ev_eloop_unregister_signal_cb(struct ev_eloop *loop, int signum,
}
}
}
/*
* Idle sources
*/
int ev_eloop_register_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb,
void *data)
{
if (!eloop)
return -EINVAL;
return kmscon_hook_add_cast(eloop->idlers, cb, data);
}
void ev_eloop_unregister_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb,
void *data)
{
if (!eloop)
return;
kmscon_hook_rm_cast(eloop->idlers, cb, data);
}

View File

@ -46,7 +46,7 @@ struct ev_fd;
struct ev_timer;
struct ev_counter;
typedef void (*ev_idle_cb) (struct ev_idle *idle, void *data);
typedef void (*ev_idle_cb) (struct ev_eloop *eloop, void *unused, void *data);
typedef void (*ev_fd_cb) (struct ev_fd *fd, int mask, void *data);
typedef void (*ev_signal_shared_cb)
(struct ev_eloop *eloop, struct signalfd_siginfo *info, void *data);

View File

@ -72,8 +72,8 @@ struct kmscon_terminal {
unsigned int max_width;
unsigned int max_height;
bool redraw;
struct kmscon_console *console;
struct ev_idle *redraw;
struct kmscon_vte *vte;
struct kmscon_pty *pty;
@ -81,14 +81,15 @@ struct kmscon_terminal {
void *data;
};
static void draw_all(struct ev_idle *idle, void *data)
static void draw_all(struct ev_eloop *eloop, void *unused, void *data)
{
struct kmscon_terminal *term = data;
struct screen *iter;
struct uterm_screen *screen;
int ret;
ev_eloop_rm_idle(idle);
ev_eloop_unregister_idle_cb(term->eloop, draw_all, term);
term->redraw = false;
iter = term->screens;
for (; iter; iter = iter->next) {
@ -110,9 +111,14 @@ static void schedule_redraw(struct kmscon_terminal *term)
{
int ret;
ret = ev_eloop_add_idle(term->eloop, term->redraw, draw_all, term);
if (ret && ret != -EALREADY)
log_warn("terminal: cannot schedule redraw");
if (term->redraw)
return;
ret = ev_eloop_register_idle_cb(term->eloop, draw_all, term);
if (ret)
log_warn("cannot schedule redraw");
else
term->redraw = true;
}
static int add_display(struct kmscon_terminal *term, struct uterm_display *disp)
@ -275,13 +281,9 @@ int kmscon_terminal_new(struct kmscon_terminal **out,
term->video = video;
term->input = input;
ret = ev_idle_new(&term->redraw);
if (ret)
goto err_free;
ret = kmscon_console_new(&term->console);
if (ret)
goto err_idle;
goto err_free;
ret = kmscon_vte_new(&term->vte);
if (ret)
@ -322,8 +324,6 @@ err_vte:
kmscon_vte_unref(term->vte);
err_con:
kmscon_console_unref(term->console);
err_idle:
ev_idle_unref(term->redraw);
err_free:
free(term);
return ret;
@ -354,8 +354,8 @@ void kmscon_terminal_unref(struct kmscon_terminal *term)
kmscon_pty_unref(term->pty);
kmscon_vte_unref(term->vte);
kmscon_console_unref(term->console);
ev_eloop_rm_idle(term->redraw);
ev_idle_unref(term->redraw);
if (term->redraw)
ev_eloop_unregister_idle_cb(term->eloop, draw_all, term);
kmscon_input_unref(term->input);
uterm_video_unref(term->video);
ev_eloop_unref(term->eloop);