]> code.delx.au - pulseaudio/blob - polyp/mainloop.c
22cd85c8dd99531675c70e420de16197d9fea5f3
[pulseaudio] / polyp / mainloop.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <sys/poll.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33 #include <fcntl.h>
34 #include <errno.h>
35
36 #include "mainloop.h"
37 #include "util.h"
38 #include "idxset.h"
39 #include "xmalloc.h"
40 #include "log.h"
41
42 struct pa_io_event {
43 struct pa_mainloop *mainloop;
44 int dead;
45 int fd;
46 enum pa_io_event_flags events;
47 void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata);
48 struct pollfd *pollfd;
49 void *userdata;
50 void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata);
51 };
52
53 struct pa_time_event {
54 struct pa_mainloop *mainloop;
55 int dead;
56 int enabled;
57 struct timeval timeval;
58 void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval*tv, void *userdata);
59 void *userdata;
60 void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata);
61 };
62
63 struct pa_defer_event {
64 struct pa_mainloop *mainloop;
65 int dead;
66 int enabled;
67 void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata);
68 void *userdata;
69 void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata);
70 };
71
72 struct pa_mainloop {
73 struct pa_idxset *io_events, *time_events, *defer_events;
74 int io_events_scan_dead, defer_events_scan_dead, time_events_scan_dead;
75
76 struct pollfd *pollfds;
77 unsigned max_pollfds, n_pollfds;
78 int rebuild_pollfds;
79
80 int quit, running, retval;
81 struct pa_mainloop_api api;
82 };
83
84 /* IO events */
85 static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) {
86 struct pa_mainloop *m;
87 struct pa_io_event *e;
88
89 assert(a && a->userdata && fd >= 0 && callback);
90 m = a->userdata;
91 assert(a == &m->api);
92
93 e = pa_xmalloc(sizeof(struct pa_io_event));
94 e->mainloop = m;
95 e->dead = 0;
96
97 e->fd = fd;
98 e->events = events;
99 e->callback = callback;
100 e->userdata = userdata;
101 e->destroy_callback = NULL;
102 e->pollfd = NULL;
103
104 pa_idxset_put(m->io_events, e, NULL);
105 m->rebuild_pollfds = 1;
106 return e;
107 }
108
109 static void mainloop_io_enable(struct pa_io_event *e, enum pa_io_event_flags events) {
110 assert(e && e->mainloop);
111
112 e->events = events;
113 if (e->pollfd)
114 e->pollfd->events =
115 (events & PA_IO_EVENT_INPUT ? POLLIN : 0) |
116 (events & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
117 POLLHUP |
118 POLLERR;
119 }
120
121 static void mainloop_io_free(struct pa_io_event *e) {
122 assert(e && e->mainloop);
123 e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1;
124 }
125
126 static void mainloop_io_set_destroy(struct pa_io_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)) {
127 assert(e);
128 e->destroy_callback = callback;
129 }
130
131 /* Defer events */
132 struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata), void *userdata) {
133 struct pa_mainloop *m;
134 struct pa_defer_event *e;
135
136 assert(a && a->userdata && callback);
137 m = a->userdata;
138 assert(a == &m->api);
139
140 e = pa_xmalloc(sizeof(struct pa_defer_event));
141 e->mainloop = m;
142 e->dead = 0;
143
144 e->enabled = 1;
145 e->callback = callback;
146 e->userdata = userdata;
147 e->destroy_callback = NULL;
148
149 pa_idxset_put(m->defer_events, e, NULL);
150 return e;
151 }
152
153 static void mainloop_defer_enable(struct pa_defer_event *e, int b) {
154 assert(e);
155 e->enabled = b;
156 }
157
158 static void mainloop_defer_free(struct pa_defer_event *e) {
159 assert(e);
160 e->dead = e->mainloop->defer_events_scan_dead = 1;
161 }
162
163 static void mainloop_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)) {
164 assert(e);
165 e->destroy_callback = callback;
166 }
167
168 /* Time events */
169 static struct pa_time_event* mainloop_time_new(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) {
170 struct pa_mainloop *m;
171 struct pa_time_event *e;
172
173 assert(a && a->userdata && callback);
174 m = a->userdata;
175 assert(a == &m->api);
176
177 e = pa_xmalloc(sizeof(struct pa_time_event));
178 e->mainloop = m;
179 e->dead = 0;
180
181 e->enabled = !!tv;
182 if (tv)
183 e->timeval = *tv;
184
185 e->callback = callback;
186 e->userdata = userdata;
187 e->destroy_callback = NULL;
188
189 pa_idxset_put(m->time_events, e, NULL);
190
191 return e;
192 }
193
194 static void mainloop_time_restart(struct pa_time_event *e, const struct timeval *tv) {
195 assert(e);
196
197 if (tv) {
198 e->enabled = 1;
199 e->timeval = *tv;
200 } else
201 e->enabled = 0;
202 }
203
204 static void mainloop_time_free(struct pa_time_event *e) {
205 assert(e);
206
207 e->dead = e->mainloop->time_events_scan_dead = 1;
208 }
209
210 static void mainloop_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)) {
211 assert(e);
212 e->destroy_callback = callback;
213 }
214
215 /* quit() */
216
217 static void mainloop_quit(struct pa_mainloop_api*a, int retval) {
218 struct pa_mainloop *m;
219 assert(a && a->userdata);
220 m = a->userdata;
221 assert(a == &m->api);
222
223 m->quit = 1;
224 m->retval = retval;
225 }
226
227 static const struct pa_mainloop_api vtable = {
228 .userdata = NULL,
229
230 .io_new= mainloop_io_new,
231 .io_enable= mainloop_io_enable,
232 .io_free= mainloop_io_free,
233 .io_set_destroy= mainloop_io_set_destroy,
234
235 .time_new = mainloop_time_new,
236 .time_restart = mainloop_time_restart,
237 .time_free = mainloop_time_free,
238 .time_set_destroy = mainloop_time_set_destroy,
239
240 .defer_new = mainloop_defer_new,
241 .defer_enable = mainloop_defer_enable,
242 .defer_free = mainloop_defer_free,
243 .defer_set_destroy = mainloop_defer_set_destroy,
244
245 .quit = mainloop_quit,
246 };
247
248 struct pa_mainloop *pa_mainloop_new(void) {
249 struct pa_mainloop *m;
250
251 m = pa_xmalloc(sizeof(struct pa_mainloop));
252
253 m->io_events = pa_idxset_new(NULL, NULL);
254 m->defer_events = pa_idxset_new(NULL, NULL);
255 m->time_events = pa_idxset_new(NULL, NULL);
256
257 assert(m->io_events && m->defer_events && m->time_events);
258
259 m->io_events_scan_dead = m->defer_events_scan_dead = m->time_events_scan_dead = 0;
260
261 m->pollfds = NULL;
262 m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0;
263
264 m->quit = m->running = m->retval = 0;
265
266 m->api = vtable;
267 m->api.userdata = m;
268
269 return m;
270 }
271
272 static int io_foreach(void *p, uint32_t index, int *del, void*userdata) {
273 struct pa_io_event *e = p;
274 int *all = userdata;
275 assert(e && del && all);
276
277 if (!*all && !e->dead)
278 return 0;
279
280 if (e->destroy_callback)
281 e->destroy_callback(&e->mainloop->api, e, e->userdata);
282 pa_xfree(e);
283 *del = 1;
284 return 0;
285 }
286
287 static int time_foreach(void *p, uint32_t index, int *del, void*userdata) {
288 struct pa_time_event *e = p;
289 int *all = userdata;
290 assert(e && del && all);
291
292 if (!*all && !e->dead)
293 return 0;
294
295 if (e->destroy_callback)
296 e->destroy_callback(&e->mainloop->api, e, e->userdata);
297 pa_xfree(e);
298 *del = 1;
299 return 0;
300 }
301
302 static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) {
303 struct pa_defer_event *e = p;
304 int *all = userdata;
305 assert(e && del && all);
306
307 if (!*all && !e->dead)
308 return 0;
309
310 if (e->destroy_callback)
311 e->destroy_callback(&e->mainloop->api, e, e->userdata);
312 pa_xfree(e);
313 *del = 1;
314 return 0;
315 }
316
317 void pa_mainloop_free(struct pa_mainloop* m) {
318 int all = 1;
319 assert(m);
320
321 pa_idxset_foreach(m->io_events, io_foreach, &all);
322 pa_idxset_foreach(m->time_events, time_foreach, &all);
323 pa_idxset_foreach(m->defer_events, defer_foreach, &all);
324
325 pa_idxset_free(m->io_events, NULL, NULL);
326 pa_idxset_free(m->time_events, NULL, NULL);
327 pa_idxset_free(m->defer_events, NULL, NULL);
328
329 pa_xfree(m->pollfds);
330 pa_xfree(m);
331 }
332
333 static void scan_dead(struct pa_mainloop *m) {
334 int all = 0;
335 assert(m);
336
337 if (m->io_events_scan_dead)
338 pa_idxset_foreach(m->io_events, io_foreach, &all);
339 if (m->time_events_scan_dead)
340 pa_idxset_foreach(m->time_events, time_foreach, &all);
341 if (m->defer_events_scan_dead)
342 pa_idxset_foreach(m->defer_events, defer_foreach, &all);
343
344 m->io_events_scan_dead = m->time_events_scan_dead = m->defer_events_scan_dead = 0;
345 }
346
347 static void rebuild_pollfds(struct pa_mainloop *m) {
348 struct pa_io_event*e;
349 struct pollfd *p;
350 uint32_t index = PA_IDXSET_INVALID;
351 unsigned l;
352
353 l = pa_idxset_ncontents(m->io_events);
354 if (m->max_pollfds < l) {
355 m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l);
356 m->max_pollfds = l;
357 }
358
359 m->n_pollfds = 0;
360 p = m->pollfds;
361 for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) {
362 if (e->dead) {
363 e->pollfd = NULL;
364 continue;
365 }
366
367 e->pollfd = p;
368 p->fd = e->fd;
369 p->events =
370 ((e->events & PA_IO_EVENT_INPUT) ? POLLIN : 0) |
371 ((e->events & PA_IO_EVENT_OUTPUT) ? POLLOUT : 0) |
372 POLLHUP |
373 POLLERR;
374 p->revents = 0;
375
376 p++;
377 m->n_pollfds++;
378 }
379 }
380
381 static void dispatch_pollfds(struct pa_mainloop *m) {
382 uint32_t index = PA_IDXSET_INVALID;
383 struct pa_io_event *e;
384
385 for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) {
386 if (e->dead || !e->pollfd || !e->pollfd->revents)
387 continue;
388
389 assert(e->pollfd->fd == e->fd && e->callback);
390 e->callback(&m->api, e, e->fd,
391 (e->pollfd->revents & POLLHUP ? PA_IO_EVENT_HANGUP : 0) |
392 (e->pollfd->revents & POLLIN ? PA_IO_EVENT_INPUT : 0) |
393 (e->pollfd->revents & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) |
394 (e->pollfd->revents & POLLERR ? PA_IO_EVENT_ERROR : 0),
395 e->userdata);
396 e->pollfd->revents = 0;
397 }
398 }
399
400 static void dispatch_defer(struct pa_mainloop *m) {
401 uint32_t index;
402 struct pa_defer_event *e;
403
404 for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) {
405 if (e->dead || !e->enabled)
406 continue;
407
408 assert(e->callback);
409 e->callback(&m->api, e, e->userdata);
410 }
411 }
412
413 static int calc_next_timeout(struct pa_mainloop *m) {
414 uint32_t index;
415 struct pa_time_event *e;
416 struct timeval now;
417 int t = -1;
418 int got_time = 0;
419
420 if (pa_idxset_isempty(m->time_events))
421 return -1;
422
423 for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) {
424 int tmp;
425
426 if (e->dead || !e->enabled)
427 continue;
428
429 /* Let's save a system call */
430 if (!got_time) {
431 gettimeofday(&now, NULL);
432 got_time = 1;
433 }
434
435 if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec))
436 return 0;
437
438 tmp = (e->timeval.tv_sec - now.tv_sec)*1000;
439
440 if (e->timeval.tv_usec > now.tv_usec)
441 tmp += (e->timeval.tv_usec - now.tv_usec)/1000;
442 else
443 tmp -= (now.tv_usec - e->timeval.tv_usec)/1000;
444
445 if (tmp == 0)
446 return 0;
447 else if (t == -1 || tmp < t)
448 t = tmp;
449 }
450
451 return t;
452 }
453
454 static void dispatch_timeout(struct pa_mainloop *m) {
455 uint32_t index;
456 struct pa_time_event *e;
457 struct timeval now;
458 int got_time = 0;
459 assert(m);
460
461 if (pa_idxset_isempty(m->time_events))
462 return;
463
464 for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) {
465
466 if (e->dead || !e->enabled)
467 continue;
468
469 /* Let's save a system call */
470 if (!got_time) {
471 gettimeofday(&now, NULL);
472 got_time = 1;
473 }
474
475 if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) {
476 assert(e->callback);
477
478 e->enabled = 0;
479 e->callback(&m->api, e, &e->timeval, e->userdata);
480 }
481 }
482 }
483
484 int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) {
485 int r;
486 assert(m && !m->running);
487
488 if(m->quit) {
489 if (retval)
490 *retval = m->retval;
491 return 1;
492 }
493
494 m->running = 1;
495
496 scan_dead(m);
497 dispatch_defer(m);
498
499 if (m->rebuild_pollfds) {
500 rebuild_pollfds(m);
501 m->rebuild_pollfds = 0;
502 }
503
504 do {
505 int t = block ? calc_next_timeout(m) : 0;
506 /*pa_log(__FILE__": %u\n", t);*/
507 r = poll(m->pollfds, m->n_pollfds, t);
508 } while (r < 0 && errno == EINTR);
509
510 dispatch_timeout(m);
511
512 if (r > 0)
513 dispatch_pollfds(m);
514 else if (r < 0)
515 pa_log(__FILE__": select(): %s\n", strerror(errno));
516
517 m->running = 0;
518 return r < 0 ? -1 : 0;
519 }
520
521 int pa_mainloop_run(struct pa_mainloop *m, int *retval) {
522 int r;
523 while ((r = pa_mainloop_iterate(m, 1, retval)) == 0);
524 return r;
525 }
526
527 void pa_mainloop_quit(struct pa_mainloop *m, int r) {
528 assert(m);
529 m->quit = r;
530 }
531
532 struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m) {
533 assert(m);
534 return &m->api;
535 }