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:
parent
83ed40f089
commit
3219b9ccfd
169
src/eloop.c
169
src/eloop.c
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user