4 This file is part of avahi.
6 avahi is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 avahi is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14 Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with avahi; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include <avahi-common/llist.h>
32 #include <avahi-common/malloc.h>
34 #include "simple-watch.h"
37 AvahiSimplePoll *simple_poll;
41 AvahiWatchCallback callback;
44 AVAHI_LLIST_FIELDS(AvahiWatch, watches);
47 struct AvahiSimplePoll {
50 struct pollfd* pollfds;
51 int n_pollfds, max_pollfds, rebuild_pollfds;
53 struct timeval wakeup;
54 AvahiWakeupCallback wakeup_callback;
55 void *wakeup_userdata;
62 AVAHI_LLIST_HEAD(AvahiWatch, watches);
65 static AvahiWatch* watch_new(AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) {
76 if (!(w = avahi_new(AvahiWatch, 1)))
81 w->pollfd.events = event;
82 w->callback = callback;
83 w->userdata = userdata;
86 if (s->n_pollfds < s->max_pollfds) {
87 /* If there's space for this pollfd, go on and allocate it */
88 w->idx = s->n_pollfds++;
89 s->pollfds[w->idx] = w->pollfd;
92 /* Unfortunately there's no place for this pollfd, so request a rebuild of the array */
94 s->rebuild_pollfds = 1;
97 AVAHI_LLIST_PREPEND(AvahiWatch, watches, s->watches, w);
103 static void watch_update(AvahiWatch *w, AvahiWatchEvent events) {
107 w->pollfd.events = events;
110 assert(w->simple_poll);
111 w->simple_poll->pollfds[w->idx] = w->pollfd;
113 w->simple_poll->rebuild_pollfds = 1;
116 static void remove_pollfd(AvahiWatch *w) {
122 if (w->idx == w->simple_poll->n_pollfds-1) {
124 /* This pollfd is at the end of the array, so we can easily cut it */
126 assert(w->simple_poll->n_pollfds > 0);
127 w->simple_poll->n_pollfds -= 1;
130 /* Unfortunately this pollfd is in the middle of the array, so request a rebuild of it */
131 w->simple_poll->rebuild_pollfds = 1;
134 static void watch_free(AvahiWatch *w) {
141 w->simple_poll->n_watches --;
142 w->simple_poll->req_cleanup = 1;
145 static void set_wakeup(AvahiPoll *api, const struct timeval *tv, AvahiWakeupCallback callback, void *userdata) {
155 s->wakeup.tv_sec = 0;
156 s->wakeup.tv_usec = 0;
159 s->wakeup_callback = callback;
160 s->wakeup_userdata = userdata;
162 s->wakeup_callback = NULL;
165 static void destroy_watch(AvahiWatch *w) {
169 AVAHI_LLIST_REMOVE(AvahiWatch, watches, w->simple_poll->watches, w);
172 w->simple_poll->n_watches --;
177 static void cleanup(AvahiSimplePoll *s, int all) {
178 AvahiWatch *w, *next;
181 for (w = s->watches; w; w = next) {
182 next = w->watches_next;
191 AvahiSimplePoll *avahi_simple_poll_new(void) {
194 if (!(s = avahi_new(AvahiSimplePoll, 1)))
198 s->api.watch_new = watch_new;
199 s->api.watch_free = watch_free;
200 s->api.watch_update = watch_update;
201 s->api.set_wakeup = set_wakeup;
203 s->max_pollfds = s->n_pollfds = 0;
204 s->wakeup_callback = NULL;
205 s->rebuild_pollfds = 0;
210 AVAHI_LLIST_HEAD_INIT(AvahiWatch, s->watches);
215 void avahi_simple_poll_free(AvahiSimplePoll *s) {
220 assert(s->n_watches == 0);
222 avahi_free(s->pollfds);
226 static int rebuild(AvahiSimplePoll *s) {
232 if (s->n_watches > s->max_pollfds) {
235 s->max_pollfds = s->n_watches + 10;
237 if (!(n = avahi_realloc(s->pollfds, sizeof(struct pollfd) * s->max_pollfds)))
243 for (idx = 0, w = s->watches; w; w = w->watches_next) {
248 assert(w->idx < s->max_pollfds);
249 s->pollfds[w->idx = idx++] = w->pollfd;
254 s->rebuild_pollfds = 0;
259 static int start_wakeup_callback(AvahiSimplePoll *s) {
260 AvahiWakeupCallback callback;
265 /* Reset the wakeup functions, but allow changing of the two
266 values from the callback function */
268 callback = s->wakeup_callback;
269 userdata = s->wakeup_userdata;
270 s->wakeup_callback = NULL;
271 s->wakeup_userdata = NULL;
275 callback(&s->api, userdata);
279 int avahi_simple_poll_iterate(AvahiSimplePoll *s, int timeout) {
283 /* Cleanup things first */
287 /* Check whether a quit was requested */
291 /* Do we need to rebuild our array of pollfds? */
292 if (s->rebuild_pollfds)
296 /* Calculate the wakeup time */
297 if (s->wakeup_callback) {
302 gettimeofday(&now, NULL);
303 usec = avahi_timeval_diff(&s->wakeup, &now);
306 /* Timeout elapsed */
308 return start_wakeup_callback(s);
310 /* Calculate sleep time. We add 1ms because otherwise we'd
311 * wake up too early most of the time */
312 t = (int) (usec / 1000) + 1;
314 if (timeout < 0 || timeout > t)
318 if ((r = poll(s->pollfds, s->n_pollfds, timeout)) < 0)
321 /* Check whether the wakeup time has been reached now */
322 if (s->wakeup_callback) {
325 gettimeofday(&now, NULL);
327 if (avahi_timeval_compare(&s->wakeup, &now) <= 0)
329 return start_wakeup_callback(s);
335 /* Look for some kind of I/O event */
337 for (w = s->watches; w; w = w->watches_next) {
343 assert(w->idx < s->n_pollfds);
345 if (s->pollfds[w->idx].revents > 0) {
346 /* We execute only on callback in every iteration */
347 w->callback(w, w->pollfd.fd, s->pollfds[w->idx].revents, w->userdata);
356 void avahi_simple_poll_quit(AvahiSimplePoll *w) {
362 AvahiPoll* avahi_simple_poll_get(AvahiSimplePoll *s) {