summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2011-04-22 12:06:34 -0400
committerKristian Høgsberg <krh@bitplanet.net>2011-04-22 12:06:36 -0400
commitf8bb7f435b884eacc2d2468b9defe5f2d5a479eb (patch)
treeaa364d1d82c9f90386d4693fc2366b1c0af50bad
parent1c88cffa3250fbf5cb485733c4954d04b3f48ee3 (diff)
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."
-rw-r--r--wayland/event-loop.c78
-rw-r--r--wayland/wayland-server.c10
-rw-r--r--wayland/wayland-server.h11
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);