15 struct mainloop_source_header
{
16 struct pa_mainloop
*mainloop
;
20 struct mainloop_source_io
{
21 struct mainloop_source_header header
;
24 enum pa_mainloop_api_io_events events
;
25 void (*callback
) (struct pa_mainloop_api
*a
, void *id
, int fd
, enum pa_mainloop_api_io_events events
, void *userdata
);
28 struct pollfd
*pollfd
;
31 struct mainloop_source_fixed_or_idle
{
32 struct mainloop_source_header header
;
35 void (*callback
)(struct pa_mainloop_api
*a
, void *id
, void *userdata
);
39 struct mainloop_source_time
{
40 struct mainloop_source_header header
;
43 struct timeval timeval
;
44 void (*callback
)(struct pa_mainloop_api
*a
, void *id
, const struct timeval
*tv
, void *userdata
);
49 struct idxset
*io_sources
, *fixed_sources
, *idle_sources
, *time_sources
;
50 int io_sources_scan_dead
, fixed_sources_scan_dead
, idle_sources_scan_dead
, time_sources_scan_dead
;
52 struct pollfd
*pollfds
;
53 unsigned max_pollfds
, n_pollfds
;
56 int quit
, running
, retval
;
57 struct pa_mainloop_api api
;
60 static void setup_api(struct pa_mainloop
*m
);
62 struct pa_mainloop
*pa_mainloop_new(void) {
63 struct pa_mainloop
*m
;
65 m
= malloc(sizeof(struct pa_mainloop
));
68 m
->io_sources
= idxset_new(NULL
, NULL
);
69 m
->fixed_sources
= idxset_new(NULL
, NULL
);
70 m
->idle_sources
= idxset_new(NULL
, NULL
);
71 m
->time_sources
= idxset_new(NULL
, NULL
);
73 assert(m
->io_sources
&& m
->fixed_sources
&& m
->idle_sources
&& m
->time_sources
);
75 m
->io_sources_scan_dead
= m
->fixed_sources_scan_dead
= m
->idle_sources_scan_dead
= m
->time_sources_scan_dead
= 0;
78 m
->max_pollfds
= m
->n_pollfds
= m
->rebuild_pollfds
= 0;
80 m
->quit
= m
->running
= m
->retval
= 0;
87 static int foreach(void *p
, uint32_t index
, int *del
, void*userdata
) {
88 struct mainloop_source_header
*h
= p
;
90 assert(p
&& del
&& all
);
92 if (*all
|| h
->dead
) {
100 void pa_mainloop_free(struct pa_mainloop
* m
) {
103 idxset_foreach(m
->io_sources
, foreach
, &all
);
104 idxset_foreach(m
->fixed_sources
, foreach
, &all
);
105 idxset_foreach(m
->idle_sources
, foreach
, &all
);
106 idxset_foreach(m
->time_sources
, foreach
, &all
);
108 idxset_free(m
->io_sources
, NULL
, NULL
);
109 idxset_free(m
->fixed_sources
, NULL
, NULL
);
110 idxset_free(m
->idle_sources
, NULL
, NULL
);
111 idxset_free(m
->time_sources
, NULL
, NULL
);
117 static void scan_dead(struct pa_mainloop
*m
) {
120 if (m
->io_sources_scan_dead
)
121 idxset_foreach(m
->io_sources
, foreach
, &all
);
122 if (m
->fixed_sources_scan_dead
)
123 idxset_foreach(m
->fixed_sources
, foreach
, &all
);
124 if (m
->idle_sources_scan_dead
)
125 idxset_foreach(m
->idle_sources
, foreach
, &all
);
126 if (m
->time_sources_scan_dead
)
127 idxset_foreach(m
->time_sources
, foreach
, &all
);
130 static void rebuild_pollfds(struct pa_mainloop
*m
) {
131 struct mainloop_source_io
*s
;
133 uint32_t index
= IDXSET_INVALID
;
136 l
= idxset_ncontents(m
->io_sources
);
137 if (m
->max_pollfds
< l
) {
138 m
->pollfds
= realloc(m
->pollfds
, sizeof(struct pollfd
)*l
);
144 for (s
= idxset_first(m
->io_sources
, &index
); s
; s
= idxset_next(m
->io_sources
, &index
)) {
145 if (s
->header
.dead
) {
152 p
->events
= ((s
->events
& PA_MAINLOOP_API_IO_EVENT_INPUT
) ? POLLIN
: 0) | ((s
->events
& PA_MAINLOOP_API_IO_EVENT_OUTPUT
) ? POLLOUT
: 0);
160 static void dispatch_pollfds(struct pa_mainloop
*m
) {
161 uint32_t index
= IDXSET_INVALID
;
162 struct mainloop_source_io
*s
;
164 for (s
= idxset_first(m
->io_sources
, &index
); s
; s
= idxset_next(m
->io_sources
, &index
)) {
165 if (s
->header
.dead
|| !s
->events
|| !s
->pollfd
|| !s
->pollfd
->revents
)
168 assert(s
->pollfd
->revents
<= s
->pollfd
->events
&& s
->pollfd
->fd
== s
->fd
&& s
->callback
);
169 s
->callback(&m
->api
, s
, s
->fd
, ((s
->pollfd
->revents
& POLLIN
) ? PA_MAINLOOP_API_IO_EVENT_INPUT
: 0) | ((s
->pollfd
->revents
& POLLOUT
) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT
: 0), s
->userdata
);
173 static void run_fixed_or_idle(struct pa_mainloop
*m
, struct idxset
*i
) {
174 uint32_t index
= IDXSET_INVALID
;
175 struct mainloop_source_fixed_or_idle
*s
;
177 for (s
= idxset_first(i
, &index
); s
; s
= idxset_next(i
, &index
)) {
178 if (s
->header
.dead
|| !s
->enabled
)
182 s
->callback(&m
->api
, s
, s
->userdata
);
186 static int calc_next_timeout(struct pa_mainloop
*m
) {
187 uint32_t index
= IDXSET_INVALID
;
188 struct mainloop_source_time
*s
;
192 if (idxset_isempty(m
->time_sources
))
195 gettimeofday(&now
, NULL
);
197 for (s
= idxset_first(m
->time_sources
, &index
); s
; s
= idxset_next(m
->time_sources
, &index
)) {
200 if (s
->header
.dead
|| !s
->enabled
)
203 if (s
->timeval
.tv_sec
< now
.tv_sec
|| (s
->timeval
.tv_sec
== now
.tv_sec
&& s
->timeval
.tv_usec
<= now
.tv_usec
))
206 tmp
= (s
->timeval
.tv_sec
- now
.tv_sec
)*1000;
208 if (s
->timeval
.tv_usec
> now
.tv_usec
)
209 tmp
+= (s
->timeval
.tv_usec
- now
.tv_usec
)/1000;
211 tmp
-= (now
.tv_usec
- s
->timeval
.tv_usec
)/1000;
222 static void dispatch_timeout(struct pa_mainloop
*m
) {
223 uint32_t index
= IDXSET_INVALID
;
224 struct mainloop_source_time
*s
;
228 if (idxset_isempty(m
->time_sources
))
231 gettimeofday(&now
, NULL
);
232 for (s
= idxset_first(m
->time_sources
, &index
); s
; s
= idxset_next(m
->time_sources
, &index
)) {
234 if (s
->header
.dead
|| !s
->enabled
)
237 if (s
->timeval
.tv_sec
< now
.tv_sec
|| (s
->timeval
.tv_sec
== now
.tv_sec
&& s
->timeval
.tv_usec
<= now
.tv_usec
)) {
241 s
->callback(&m
->api
, s
, &s
->timeval
, s
->userdata
);
246 static int any_idle_sources(struct pa_mainloop
*m
) {
247 struct mainloop_source_fixed_or_idle
*s
;
251 for (s
= idxset_first(m
->idle_sources
, &index
); s
; s
= idxset_next(m
->idle_sources
, &index
))
252 if (!s
->header
.dead
&& s
->enabled
)
258 int pa_mainloop_iterate(struct pa_mainloop
*m
, int block
, int *retval
) {
260 assert(m
&& !m
->running
);
271 run_fixed_or_idle(m
, m
->fixed_sources
);
273 if (m
->rebuild_pollfds
) {
275 m
->rebuild_pollfds
= 0;
278 idle
= any_idle_sources(m
);
286 t
= calc_next_timeout(m
);
288 r
= poll(m
->pollfds
, m
->n_pollfds
, t
);
289 } while (r
< 0 && errno
== EINTR
);
295 else if (r
== 0 && idle
)
296 run_fixed_or_idle(m
, m
->idle_sources
);
298 fprintf(stderr
, "select(): %s\n", strerror(errno
));
301 return r
< 0 ? -1 : 0;
304 int pa_mainloop_run(struct pa_mainloop
*m
, int *retval
) {
306 while ((r
= pa_mainloop_iterate(m
, 1, retval
)) == 0);
310 void pa_mainloop_quit(struct pa_mainloop
*m
, int r
) {
316 static void* mainloop_source_io(struct pa_mainloop_api
*a
, int fd
, enum pa_mainloop_api_io_events events
, void (*callback
) (struct pa_mainloop_api
*a
, void *id
, int fd
, enum pa_mainloop_api_io_events events
, void *userdata
), void *userdata
) {
317 struct pa_mainloop
*m
;
318 struct mainloop_source_io
*s
;
319 assert(a
&& a
->userdata
&& fd
>= 0 && callback
);
321 assert(a
== &m
->api
);
323 s
= malloc(sizeof(struct mainloop_source_io
));
325 s
->header
.mainloop
= m
;
330 s
->callback
= callback
;
331 s
->userdata
= userdata
;
334 idxset_put(m
->io_sources
, s
, NULL
);
335 m
->rebuild_pollfds
= 1;
339 static void mainloop_enable_io(struct pa_mainloop_api
*a
, void* id
, enum pa_mainloop_api_io_events events
) {
340 struct pa_mainloop
*m
;
341 struct mainloop_source_io
*s
= id
;
342 assert(a
&& a
->userdata
&& s
&& !s
->header
.dead
);
344 assert(a
== &m
->api
&& s
->header
.mainloop
== m
);
348 s
->pollfd
->events
= ((s
->events
& PA_MAINLOOP_API_IO_EVENT_INPUT
) ? POLLIN
: 0) | ((s
->events
& PA_MAINLOOP_API_IO_EVENT_OUTPUT
) ? POLLOUT
: 0);
351 static void mainloop_cancel_io(struct pa_mainloop_api
*a
, void* id
) {
352 struct pa_mainloop
*m
;
353 struct mainloop_source_io
*s
= id
;
354 assert(a
&& a
->userdata
&& s
&& !s
->header
.dead
);
356 assert(a
== &m
->api
&& s
->header
.mainloop
== m
);
359 m
->io_sources_scan_dead
= 1;
363 static void* mainloop_source_fixed(struct pa_mainloop_api
*a
, void (*callback
) (struct pa_mainloop_api
*a
, void *id
, void *userdata
), void *userdata
) {
364 struct pa_mainloop
*m
;
365 struct mainloop_source_fixed_or_idle
*s
;
366 assert(a
&& a
->userdata
&& callback
);
368 assert(a
== &m
->api
);
370 s
= malloc(sizeof(struct mainloop_source_fixed_or_idle
));
372 s
->header
.mainloop
= m
;
376 s
->callback
= callback
;
377 s
->userdata
= userdata
;
379 idxset_put(m
->fixed_sources
, s
, NULL
);
383 static void mainloop_enable_fixed(struct pa_mainloop_api
*a
, void* id
, int b
) {
384 struct pa_mainloop
*m
;
385 struct mainloop_source_fixed_or_idle
*s
= id
;
386 assert(a
&& a
->userdata
&& s
&& !s
->header
.dead
);
388 assert(a
== &m
->api
);
393 static void mainloop_cancel_fixed(struct pa_mainloop_api
*a
, void* id
) {
394 struct pa_mainloop
*m
;
395 struct mainloop_source_fixed_or_idle
*s
= id
;
396 assert(a
&& a
->userdata
&& s
&& !s
->header
.dead
);
398 assert(a
== &m
->api
);
401 m
->fixed_sources_scan_dead
= 1;
405 static void* mainloop_source_idle(struct pa_mainloop_api
*a
, void (*callback
) (struct pa_mainloop_api
*a
, void *id
, void *userdata
), void *userdata
) {
406 struct pa_mainloop
*m
;
407 struct mainloop_source_fixed_or_idle
*s
;
408 assert(a
&& a
->userdata
&& callback
);
410 assert(a
== &m
->api
);
412 s
= malloc(sizeof(struct mainloop_source_fixed_or_idle
));
414 s
->header
.mainloop
= m
;
418 s
->callback
= callback
;
419 s
->userdata
= userdata
;
421 idxset_put(m
->idle_sources
, s
, NULL
);
425 static void mainloop_cancel_idle(struct pa_mainloop_api
*a
, void* id
) {
426 struct pa_mainloop
*m
;
427 struct mainloop_source_fixed_or_idle
*s
= id
;
428 assert(a
&& a
->userdata
&& s
&& !s
->header
.dead
);
430 assert(a
== &m
->api
);
433 m
->idle_sources_scan_dead
= 1;
437 static void* mainloop_source_time(struct pa_mainloop_api
*a
, const struct timeval
*tv
, void (*callback
) (struct pa_mainloop_api
*a
, void *id
, const struct timeval
*tv
, void *userdata
), void *userdata
) {
438 struct pa_mainloop
*m
;
439 struct mainloop_source_time
*s
;
440 assert(a
&& a
->userdata
&& callback
);
442 assert(a
== &m
->api
);
444 s
= malloc(sizeof(struct mainloop_source_time
));
446 s
->header
.mainloop
= m
;
453 s
->callback
= callback
;
454 s
->userdata
= userdata
;
456 idxset_put(m
->time_sources
, s
, NULL
);
460 static void mainloop_enable_time(struct pa_mainloop_api
*a
, void *id
, const struct timeval
*tv
) {
461 struct pa_mainloop
*m
;
462 struct mainloop_source_time
*s
= id
;
463 assert(a
&& a
->userdata
&& s
&& !s
->header
.dead
);
465 assert(a
== &m
->api
);
474 static void mainloop_cancel_time(struct pa_mainloop_api
*a
, void* id
) {
475 struct pa_mainloop
*m
;
476 struct mainloop_source_time
*s
= id
;
477 assert(a
&& a
->userdata
&& s
&& !s
->header
.dead
);
479 assert(a
== &m
->api
);
482 m
->time_sources_scan_dead
= 1;
486 static void mainloop_quit(struct pa_mainloop_api
*a
, int retval
) {
487 struct pa_mainloop
*m
;
488 assert(a
&& a
->userdata
);
490 assert(a
== &m
->api
);
496 static void setup_api(struct pa_mainloop
*m
) {
500 m
->api
.source_io
= mainloop_source_io
;
501 m
->api
.enable_io
= mainloop_enable_io
;
502 m
->api
.cancel_io
= mainloop_cancel_io
;
504 m
->api
.source_fixed
= mainloop_source_fixed
;
505 m
->api
.enable_fixed
= mainloop_enable_fixed
;
506 m
->api
.cancel_fixed
= mainloop_cancel_fixed
;
508 m
->api
.source_idle
= mainloop_source_idle
;
509 m
->api
.enable_idle
= mainloop_enable_fixed
; /* (!) */
510 m
->api
.cancel_idle
= mainloop_cancel_idle
;
512 m
->api
.source_time
= mainloop_source_time
;
513 m
->api
.enable_time
= mainloop_enable_time
;
514 m
->api
.cancel_time
= mainloop_cancel_time
;
516 m
->api
.quit
= mainloop_quit
;
519 struct pa_mainloop_api
* pa_mainloop_get_api(struct pa_mainloop
*m
) {