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;
|
unsigned long ref;
|
||||||
struct ev_fd *fd;
|
struct ev_fd *fd;
|
||||||
|
|
||||||
struct ev_idle *idle_list;
|
|
||||||
struct ev_idle *cur_idle;
|
|
||||||
|
|
||||||
struct kmscon_dlist sig_list;
|
struct kmscon_dlist sig_list;
|
||||||
|
struct kmscon_hook *idlers;
|
||||||
|
|
||||||
struct epoll_event *cur_fds;
|
struct epoll_event *cur_fds;
|
||||||
size_t cur_fds_cnt;
|
size_t cur_fds_cnt;
|
||||||
@ -102,16 +100,6 @@ struct ev_signal_shared {
|
|||||||
struct kmscon_hook *hook;
|
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
|
* Shared signals
|
||||||
*/
|
*/
|
||||||
@ -260,10 +248,14 @@ int ev_eloop_new(struct ev_eloop **out)
|
|||||||
loop->ref = 1;
|
loop->ref = 1;
|
||||||
kmscon_dlist_init(&loop->sig_list);
|
kmscon_dlist_init(&loop->sig_list);
|
||||||
|
|
||||||
|
ret = kmscon_hook_new(&loop->idlers);
|
||||||
|
if (ret)
|
||||||
|
goto err_free;
|
||||||
|
|
||||||
loop->efd = epoll_create1(EPOLL_CLOEXEC);
|
loop->efd = epoll_create1(EPOLL_CLOEXEC);
|
||||||
if (loop->efd < 0) {
|
if (loop->efd < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
goto err_free;
|
goto err_idlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ev_fd_new(&loop->fd, loop->efd, EV_READABLE, eloop_event, loop);
|
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:
|
err_close:
|
||||||
close(loop->efd);
|
close(loop->efd);
|
||||||
|
err_idlers:
|
||||||
|
kmscon_hook_free(loop->idlers);
|
||||||
err_free:
|
err_free:
|
||||||
free(loop);
|
free(loop);
|
||||||
return ret;
|
return ret;
|
||||||
@ -307,6 +301,7 @@ void ev_eloop_unref(struct ev_eloop *loop)
|
|||||||
|
|
||||||
ev_fd_unref(loop->fd);
|
ev_fd_unref(loop->fd);
|
||||||
close(loop->efd);
|
close(loop->efd);
|
||||||
|
kmscon_hook_free(loop->idlers);
|
||||||
free(loop);
|
free(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,12 +328,7 @@ int ev_eloop_dispatch(struct ev_eloop *loop, int timeout)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* dispatch idle events */
|
/* dispatch idle events */
|
||||||
loop->cur_idle = loop->idle_list;
|
kmscon_hook_call(loop->idlers, loop, NULL);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dispatch fd events */
|
/* dispatch fd events */
|
||||||
count = epoll_wait(loop->efd, ep, 32, timeout);
|
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,
|
int ev_eloop_register_signal_cb(struct ev_eloop *loop, int signum,
|
||||||
ev_signal_shared_cb cb, void *data)
|
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_timer;
|
||||||
struct ev_counter;
|
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_fd_cb) (struct ev_fd *fd, int mask, void *data);
|
||||||
typedef void (*ev_signal_shared_cb)
|
typedef void (*ev_signal_shared_cb)
|
||||||
(struct ev_eloop *eloop, struct signalfd_siginfo *info, void *data);
|
(struct ev_eloop *eloop, struct signalfd_siginfo *info, void *data);
|
||||||
|
@ -72,8 +72,8 @@ struct kmscon_terminal {
|
|||||||
unsigned int max_width;
|
unsigned int max_width;
|
||||||
unsigned int max_height;
|
unsigned int max_height;
|
||||||
|
|
||||||
|
bool redraw;
|
||||||
struct kmscon_console *console;
|
struct kmscon_console *console;
|
||||||
struct ev_idle *redraw;
|
|
||||||
struct kmscon_vte *vte;
|
struct kmscon_vte *vte;
|
||||||
struct kmscon_pty *pty;
|
struct kmscon_pty *pty;
|
||||||
|
|
||||||
@ -81,14 +81,15 @@ struct kmscon_terminal {
|
|||||||
void *data;
|
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 kmscon_terminal *term = data;
|
||||||
struct screen *iter;
|
struct screen *iter;
|
||||||
struct uterm_screen *screen;
|
struct uterm_screen *screen;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ev_eloop_rm_idle(idle);
|
ev_eloop_unregister_idle_cb(term->eloop, draw_all, term);
|
||||||
|
term->redraw = false;
|
||||||
|
|
||||||
iter = term->screens;
|
iter = term->screens;
|
||||||
for (; iter; iter = iter->next) {
|
for (; iter; iter = iter->next) {
|
||||||
@ -110,9 +111,14 @@ static void schedule_redraw(struct kmscon_terminal *term)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ev_eloop_add_idle(term->eloop, term->redraw, draw_all, term);
|
if (term->redraw)
|
||||||
if (ret && ret != -EALREADY)
|
return;
|
||||||
log_warn("terminal: cannot schedule redraw");
|
|
||||||
|
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)
|
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->video = video;
|
||||||
term->input = input;
|
term->input = input;
|
||||||
|
|
||||||
ret = ev_idle_new(&term->redraw);
|
|
||||||
if (ret)
|
|
||||||
goto err_free;
|
|
||||||
|
|
||||||
ret = kmscon_console_new(&term->console);
|
ret = kmscon_console_new(&term->console);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_idle;
|
goto err_free;
|
||||||
|
|
||||||
ret = kmscon_vte_new(&term->vte);
|
ret = kmscon_vte_new(&term->vte);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -322,8 +324,6 @@ err_vte:
|
|||||||
kmscon_vte_unref(term->vte);
|
kmscon_vte_unref(term->vte);
|
||||||
err_con:
|
err_con:
|
||||||
kmscon_console_unref(term->console);
|
kmscon_console_unref(term->console);
|
||||||
err_idle:
|
|
||||||
ev_idle_unref(term->redraw);
|
|
||||||
err_free:
|
err_free:
|
||||||
free(term);
|
free(term);
|
||||||
return ret;
|
return ret;
|
||||||
@ -354,8 +354,8 @@ void kmscon_terminal_unref(struct kmscon_terminal *term)
|
|||||||
kmscon_pty_unref(term->pty);
|
kmscon_pty_unref(term->pty);
|
||||||
kmscon_vte_unref(term->vte);
|
kmscon_vte_unref(term->vte);
|
||||||
kmscon_console_unref(term->console);
|
kmscon_console_unref(term->console);
|
||||||
ev_eloop_rm_idle(term->redraw);
|
if (term->redraw)
|
||||||
ev_idle_unref(term->redraw);
|
ev_eloop_unregister_idle_cb(term->eloop, draw_all, term);
|
||||||
kmscon_input_unref(term->input);
|
kmscon_input_unref(term->input);
|
||||||
uterm_video_unref(term->video);
|
uterm_video_unref(term->video);
|
||||||
ev_eloop_unref(term->eloop);
|
ev_eloop_unref(term->eloop);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user