From f8bb7f435b884eacc2d2468b9defe5f2d5a479eb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 22 Apr 2011 12:06:34 -0400 Subject: [PATCH] event-loop: Dont use a check callback just dispatch again We pass the poll mask so the dispatch callback can know if there is data on the fd or not. The dispatch function must return true if it dispatched something, in which case we need to do another round of post-dispatch callbacks." --- wayland/event-loop.c | 78 +++++++++++++++++++++++------------------------- wayland/wayland-server.c | 10 +++++-- wayland/wayland-server.h | 11 +++---- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/wayland/event-loop.c b/wayland/event-loop.c index 4ca9111..c653380 100644 --- a/wayland/event-loop.c +++ b/wayland/event-loop.c @@ -38,20 +38,18 @@ struct wl_event_loop { int epoll_fd; struct wl_list idle_list; - struct wl_list ready_list; struct wl_list check_list; }; struct wl_event_source_interface { - void (*dispatch)(struct wl_event_source *source, - struct epoll_event *ep); + int (*dispatch)(struct wl_event_source *source, + struct epoll_event *ep); int (*remove)(struct wl_event_source *source); }; struct wl_event_source { struct wl_event_source_interface *interface; struct wl_event_loop *loop; - wl_event_source_check_func_t check; struct wl_list link; void *data; }; @@ -62,7 +60,7 @@ struct wl_event_source_fd { wl_event_loop_fd_func_t func; }; -static void +static int wl_event_source_fd_dispatch(struct wl_event_source *source, struct epoll_event *ep) { @@ -75,7 +73,7 @@ wl_event_source_fd_dispatch(struct wl_event_source *source, if (ep->events & EPOLLOUT) mask |= WL_EVENT_WRITEABLE; - fd_source->func(fd_source->fd, mask, fd_source->base.data); + return fd_source->func(fd_source->fd, mask, fd_source->base.data); } static int @@ -112,6 +110,7 @@ wl_event_loop_add_fd(struct wl_event_loop *loop, source->base.interface = &fd_source_interface; source->base.loop = loop; + wl_list_init(&source->base.link); source->fd = fd; source->func = func; source->base.data = data; @@ -156,7 +155,7 @@ struct wl_event_source_timer { wl_event_loop_timer_func_t func; }; -static void +static int wl_event_source_timer_dispatch(struct wl_event_source *source, struct epoll_event *ep) { @@ -166,7 +165,7 @@ wl_event_source_timer_dispatch(struct wl_event_source *source, read(timer_source->fd, &expires, sizeof expires); - timer_source->func(timer_source->base.data); + return timer_source->func(timer_source->base.data); } static int @@ -199,6 +198,7 @@ wl_event_loop_add_timer(struct wl_event_loop *loop, source->base.interface = &timer_source_interface; source->base.loop = loop; + wl_list_init(&source->base.link); source->fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); if (source->fd < 0) { @@ -249,7 +249,7 @@ struct wl_event_source_signal { wl_event_loop_signal_func_t func; }; -static void +static int wl_event_source_signal_dispatch(struct wl_event_source *source, struct epoll_event *ep) { @@ -259,8 +259,8 @@ wl_event_source_signal_dispatch(struct wl_event_source *source, read(signal_source->fd, &signal_info, sizeof signal_info); - signal_source->func(signal_source->signal_number, - signal_source->base.data); + return signal_source->func(signal_source->signal_number, + signal_source->base.data); } static int @@ -295,6 +295,7 @@ wl_event_loop_add_signal(struct wl_event_loop *loop, source->base.interface = &signal_source_interface; source->base.loop = loop; + wl_list_init(&source->base.link); source->signal_number = signal_number; sigemptyset(&mask); @@ -329,7 +330,7 @@ struct wl_event_source_idle { void *data; }; -static void +static int wl_event_source_idle_dispatch(struct wl_event_source *source, struct epoll_event *ep) { @@ -375,20 +376,15 @@ wl_event_loop_add_idle(struct wl_event_loop *loop, } WL_EXPORT void -wl_event_source_check(struct wl_event_source *source, - wl_event_source_check_func_t check) +wl_event_source_check(struct wl_event_source *source) { - source->check = check; - if (check) - wl_list_insert(source->loop->check_list.prev, &source->link); - else - wl_list_remove(&source->link); + wl_list_insert(source->loop->check_list.prev, &source->link); } WL_EXPORT int wl_event_source_remove(struct wl_event_source *source) { - if (source->check) + if (!wl_list_empty(&source->link)) wl_list_remove(&source->link); source->interface->remove(source); @@ -411,7 +407,6 @@ wl_event_loop_create(void) return NULL; } wl_list_init(&loop->idle_list); - wl_list_init(&loop->ready_list); wl_list_init(&loop->check_list); return loop; @@ -424,31 +419,41 @@ wl_event_loop_destroy(struct wl_event_loop *loop) free(loop); } +static int +post_dispatch_check(struct wl_event_loop *loop) +{ + struct epoll_event ep; + struct wl_event_source *source, *next; + int n; + + ep.events = 0; + n = 0; + wl_list_for_each_safe(source, next, &loop->check_list, link) + n += source->interface->dispatch(source, &ep); + + return n; +} + WL_EXPORT int wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout) { struct epoll_event ep[32]; - struct wl_event_source *source, *next; + struct wl_event_source *source; struct wl_event_source_idle *idle; - int i, count; - - ep[0].events = 0; - while (!wl_list_empty(&loop->ready_list)) { - source = container_of(loop->ready_list.next, - struct wl_event_source, link); - wl_list_remove(&source->link); - wl_list_insert(loop->check_list.prev, &source->link); - source->interface->dispatch(source, &ep[0]); - } + int i, count, n; count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout); if (count < 0) return -1; + n = 0; for (i = 0; i < count; i++) { source = ep[i].data.ptr; - source->interface->dispatch(source, &ep[i]); + n += source->interface->dispatch(source, &ep[i]); } + while (n > 0) + n = post_dispatch_check(loop); + while (!wl_list_empty(&loop->idle_list)) { idle = container_of(loop->idle_list.next, struct wl_event_source_idle, base.link); @@ -456,13 +461,6 @@ wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout) idle->func(idle->data); free(idle); } - - wl_list_for_each_safe(source, next, &loop->check_list, link) { - if (source->check(source, source->data)) { - wl_list_remove(&source->link); - wl_list_insert(loop->ready_list.prev, &source->link); - } - } return 0; } diff --git a/wayland/wayland-server.c b/wayland/wayland-server.c index ed16300..daa6989 100644 --- a/wayland/wayland-server.c +++ b/wayland/wayland-server.c @@ -113,7 +113,7 @@ wl_client_post_event(struct wl_client *client, struct wl_object *sender, wl_closure_destroy(closure); } -static void +static int wl_client_connection_data(int fd, uint32_t mask, void *data) { struct wl_client *client = data; @@ -133,7 +133,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) len = wl_connection_data(connection, cmask); if (len < 0) { wl_client_destroy(client); - return; + return 1; } while (len >= sizeof p) { @@ -185,6 +185,8 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) wl_closure_destroy(closure); } + + return 1; } static int @@ -654,7 +656,7 @@ wl_display_run(struct wl_display *display) wl_event_loop_dispatch(display->loop, -1); } -static void +static int socket_data(int fd, uint32_t mask, void *data) { struct wl_display *display = data; @@ -669,6 +671,8 @@ socket_data(int fd, uint32_t mask, void *data) fprintf(stderr, "failed to accept\n"); wl_client_create(display, client_fd); + + return 1; } static int diff --git a/wayland/wayland-server.h b/wayland/wayland-server.h index 27139c0..0a6931c 100644 --- a/wayland/wayland-server.h +++ b/wayland/wayland-server.h @@ -38,11 +38,9 @@ enum { struct wl_event_loop; struct wl_event_source; -typedef int (*wl_event_source_check_func_t)(struct wl_event_source *source, - void *data); -typedef void (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data); -typedef void (*wl_event_loop_timer_func_t)(void *data); -typedef void (*wl_event_loop_signal_func_t)(int signal_number, void *data); +typedef int (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data); +typedef int (*wl_event_loop_timer_func_t)(void *data); +typedef int (*wl_event_loop_signal_func_t)(int signal_number, void *data); typedef void (*wl_event_loop_idle_func_t)(void *data); struct wl_event_loop *wl_event_loop_create(void); @@ -64,8 +62,7 @@ wl_event_loop_add_signal(struct wl_event_loop *loop, int wl_event_source_timer_update(struct wl_event_source *source, int ms_delay); int wl_event_source_remove(struct wl_event_source *source); -void wl_event_source_check(struct wl_event_source *source, - wl_event_source_check_func_t check); +void wl_event_source_check(struct wl_event_source *source); int wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout); -- 2.7.4