summaryrefslogtreecommitdiff
path: root/event-loop.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2008-09-30 09:46:10 -0400
committerKristian Høgsberg <krh@redhat.com>2008-09-30 09:56:42 -0400
commit97f1ebe8d5c2e166fabf757182c289fed266a45a (patch)
tree3eb472ec9d560becb94e08650629d376d763d2b6 /event-loop.c
Initial commit.
This has the basic event loop, and a first cut of the libffi dispatcher.
Diffstat (limited to 'event-loop.c')
-rw-r--r--event-loop.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/event-loop.c b/event-loop.c
new file mode 100644
index 0000000..2946a64
--- /dev/null
+++ b/event-loop.c
@@ -0,0 +1,107 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/epoll.h>
+#include <unistd.h>
+#include "wayland.h"
+
+struct wl_event_loop {
+ int epoll_fd;
+};
+
+struct wl_event_source {
+ int fd;
+ wl_event_loop_func_t func;
+ void *data;
+};
+
+struct wl_event_source *
+wl_event_loop_add_fd(struct wl_event_loop *loop,
+ int fd, uint32_t mask,
+ wl_event_loop_func_t func,
+ void *data)
+{
+ struct wl_event_source *source;
+ struct epoll_event ep;
+
+ source = malloc(sizeof *source);
+ source->fd = fd;
+ source->func = func;
+ source->data = data;
+
+ ep.events = 0;
+ if (mask & WL_EVENT_READABLE)
+ ep.events |= EPOLLIN;
+ if (mask & WL_EVENT_WRITEABLE)
+ ep.events |= EPOLLOUT;
+ ep.data.ptr = source;
+
+ if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
+ free(source);
+ return NULL;
+ }
+
+ return source;
+}
+
+int
+wl_event_loop_remove_source(struct wl_event_loop *loop,
+ struct wl_event_source *source)
+{
+ int fd;
+
+ fd = source->fd;
+ free(source);
+
+ return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
+}
+
+struct wl_event_loop *
+wl_event_loop_create(void)
+{
+ struct wl_event_loop *loop;
+
+ loop = malloc(sizeof *loop);
+ if (loop == NULL)
+ return NULL;
+
+ loop->epoll_fd = epoll_create(16);
+ if (loop->epoll_fd < 0) {
+ free(loop);
+ return NULL;
+ }
+
+ return loop;
+}
+
+void
+wl_event_loop_destroy(struct wl_event_loop *loop)
+{
+ close(loop->epoll_fd);
+ free(loop);
+}
+
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+int
+wl_event_loop_wait(struct wl_event_loop *loop)
+{
+ struct epoll_event ep[32];
+ struct wl_event_source *source;
+ int i, count;
+
+ count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), -1);
+ if (count < 0)
+ return -1;
+
+ for (i = 0; i < count; i++) {
+ source = ep[i].data.ptr;
+ source->func(source->fd, ep[i].events, source->data);
+ }
+
+ return 0;
+}