blob: 40f1c86ae576fd3fa80b41e39c542836c8a50309 [file] [log] [blame]
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -04001#include <stddef.h>
2#include <stdio.h>
3#include <errno.h>
4#include <stdlib.h>
5#include <string.h>
6#include <sys/socket.h>
7#include <sys/un.h>
8#include <sys/epoll.h>
9#include <unistd.h>
10#include "wayland.h"
11
12struct wl_event_loop {
13 int epoll_fd;
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -040014 wl_event_loop_idle_func_t idle_func;
15 void *idle_data;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040016};
17
18struct wl_event_source {
19 int fd;
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -040020 wl_event_loop_fd_func_t func;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040021 void *data;
22};
23
24struct wl_event_source *
25wl_event_loop_add_fd(struct wl_event_loop *loop,
26 int fd, uint32_t mask,
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -040027 wl_event_loop_fd_func_t func,
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040028 void *data)
29{
30 struct wl_event_source *source;
31 struct epoll_event ep;
32
33 source = malloc(sizeof *source);
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050034 if (source == NULL)
35 return NULL;
36
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040037 source->fd = fd;
38 source->func = func;
39 source->data = data;
40
41 ep.events = 0;
42 if (mask & WL_EVENT_READABLE)
43 ep.events |= EPOLLIN;
44 if (mask & WL_EVENT_WRITEABLE)
45 ep.events |= EPOLLOUT;
46 ep.data.ptr = source;
47
48 if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
49 free(source);
50 return NULL;
51 }
52
53 return source;
54}
55
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -040056struct wl_event_source idle_source;
57
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040058int
59wl_event_loop_remove_source(struct wl_event_loop *loop,
60 struct wl_event_source *source)
61{
62 int fd;
63
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -040064 if (source == &idle_source) {
65 loop->idle_func = NULL;
66 return 0;
67 } else {
68 fd = source->fd;
69 free(source);
70 return epoll_ctl(loop->epoll_fd,
71 EPOLL_CTL_DEL, fd, NULL);
72 };
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040073}
74
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040075int
76wl_event_loop_update_source(struct wl_event_loop *loop,
77 struct wl_event_source *source,
78 uint32_t mask)
79{
80 struct epoll_event ep;
81
82 ep.events = 0;
83 if (mask & WL_EVENT_READABLE)
84 ep.events |= EPOLLIN;
85 if (mask & WL_EVENT_WRITEABLE)
86 ep.events |= EPOLLOUT;
87 ep.data.ptr = source;
88
89 return epoll_ctl(loop->epoll_fd,
90 EPOLL_CTL_MOD, source->fd, &ep);
91}
92
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040093struct wl_event_loop *
94wl_event_loop_create(void)
95{
96 struct wl_event_loop *loop;
97
98 loop = malloc(sizeof *loop);
99 if (loop == NULL)
100 return NULL;
101
102 loop->epoll_fd = epoll_create(16);
103 if (loop->epoll_fd < 0) {
104 free(loop);
105 return NULL;
106 }
107
108 return loop;
109}
110
111void
112wl_event_loop_destroy(struct wl_event_loop *loop)
113{
114 close(loop->epoll_fd);
115 free(loop);
116}
117
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -0400118struct wl_event_source *
119wl_event_loop_add_idle(struct wl_event_loop *loop,
120 wl_event_loop_idle_func_t func,
121 void *data)
122{
123 loop->idle_func = func;
124 loop->idle_data = data;
125
126 return &idle_source;
127}
128
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400129#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
130
131int
132wl_event_loop_wait(struct wl_event_loop *loop)
133{
134 struct epoll_event ep[32];
135 struct wl_event_source *source;
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -0400136 int i, count, timeout;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400137 uint32_t mask;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400138
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -0400139 if (loop->idle_func)
140 timeout = 0;
141 else
142 timeout = -1;
143
144 count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400145 if (count < 0)
146 return -1;
147
148 for (i = 0; i < count; i++) {
149 source = ep[i].data.ptr;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400150 mask = 0;
151 if (ep[i].events & EPOLLIN)
152 mask |= WL_EVENT_READABLE;
153 if (ep[i].events & EPOLLOUT)
154 mask |= WL_EVENT_WRITEABLE;
155
156 source->func(source->fd, mask, source->data);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400157 }
158
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -0400159 if (count == 0 && loop->idle_func != NULL) {
160 loop->idle_func(loop->idle_data);
161 loop->idle_func = NULL;
162 }
163
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400164 return 0;
165}