Split mainloop_iterate() into three, distinct parts. Allows for more flexible

use, like having the poll() run in a separate thread.


git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@478 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Pierre Ossman 2006-02-13 13:28:45 +00:00
parent 4ab432a819
commit bbaf1543bd
2 changed files with 137 additions and 53 deletions

View file

@ -84,10 +84,20 @@ struct pa_mainloop {
unsigned max_pollfds, n_pollfds;
int rebuild_pollfds;
int quit, running, retval;
int prepared_timeout;
int quit, retval;
pa_mainloop_api api;
int deferred_pending;
enum {
STATE_PASSIVE,
STATE_PREPARED,
STATE_POLLING,
STATE_POLLED,
STATE_QUIT
} state;
};
/* IO events */
@ -145,11 +155,7 @@ static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
assert(e && e->mainloop);
e->events = events;
if (e->pollfd)
e->pollfd->events =
(events & PA_IO_EVENT_INPUT ? POLLIN : 0) |
(events & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
POLLERR | POLLHUP;
e->mainloop->rebuild_pollfds = 1;
}
static void mainloop_io_free(pa_io_event *e) {
@ -310,12 +316,14 @@ pa_mainloop *pa_mainloop_new(void) {
m->pollfds = NULL;
m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0;
m->quit = m->running = m->retval = 0;
m->quit = m->retval = 0;
m->api = vtable;
m->api.userdata = m;
m->deferred_pending = 0;
m->state = STATE_PASSIVE;
return m;
}
@ -367,7 +375,7 @@ static int defer_foreach(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void*use
void pa_mainloop_free(pa_mainloop* m) {
int all = 1;
assert(m);
assert(m && (m->state != STATE_POLLING));
pa_idxset_foreach(m->io_events, io_foreach, &all);
pa_idxset_foreach(m->time_events, time_foreach, &all);
@ -427,6 +435,8 @@ static void rebuild_pollfds(pa_mainloop *m) {
p++;
m->n_pollfds++;
}
m->rebuild_pollfds = 0;
}
static int dispatch_pollfds(pa_mainloop *m) {
@ -548,65 +558,122 @@ static int dispatch_timeout(pa_mainloop *m) {
return r;
}
int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
int r, t, dispatched = 0;
assert(m && !m->running);
int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
int dispatched = 0;
m->running ++;
assert(m && (m->state == STATE_PASSIVE));
scan_dead(m);
if (m->quit)
goto quit;
scan_dead(m);
dispatched += dispatch_defer(m);
if(m->quit)
if (m->quit)
goto quit;
if (m->rebuild_pollfds) {
if (m->rebuild_pollfds)
rebuild_pollfds(m);
m->rebuild_pollfds = 0;
}
t = block ? calc_next_timeout(m) : 0;
m->prepared_timeout = calc_next_timeout(m);
if ((timeout >= 0) && (m->prepared_timeout > timeout))
m->prepared_timeout = timeout;
r = poll(m->pollfds, m->n_pollfds, t);
m->state = STATE_PREPARED;
if (r < 0) {
if (errno == EINTR)
r = 0;
else
pa_log(__FILE__": select(): %s\n", strerror(errno));
} else {
dispatched += dispatch_timeout(m);
if(m->quit)
goto quit;
if (r > 0) {
dispatched += dispatch_pollfds(m);
if(m->quit)
goto quit;
}
}
m->running--;
/* pa_log("dispatched: %i\n", dispatched); */
return r < 0 ? -1 : dispatched;
return dispatched;
quit:
m->running--;
if (retval)
*retval = m->retval;
m->state = STATE_QUIT;
return -2;
}
int pa_mainloop_poll(pa_mainloop *m) {
int r;
assert(m && (m->state == STATE_PREPARED));
m->state = STATE_POLLING;
r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout);
if ((r < 0) && (errno == EINTR))
r = 0;
if (r < 0)
m->state = STATE_PASSIVE;
else
m->state = STATE_POLLED;
return r;
}
int pa_mainloop_dispatch(pa_mainloop *m) {
int dispatched = 0;
assert(m && (m->state == STATE_POLLED));
dispatched += dispatch_timeout(m);
if (m->quit)
goto quit;
dispatched += dispatch_pollfds(m);
if (m->quit)
goto quit;
m->state = STATE_PASSIVE;
return dispatched;
quit:
m->state = STATE_QUIT;
return -2;
}
int pa_mainloop_get_retval(pa_mainloop *m) {
assert(m);
return m->retval;
}
int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
int r, dispatched = 0;
assert(m);
r = pa_mainloop_prepare(m, block ? -1 : 0);
if (r < 0) {
if ((r == -2) && retval)
*retval = pa_mainloop_get_retval(m);
return r;
}
dispatched += r;
r = pa_mainloop_poll(m);
if (r < 0) {
pa_log(__FILE__": poll(): %s\n", strerror(errno));
return r;
}
r = pa_mainloop_dispatch(m);
if (r < 0) {
if ((r == -2) && retval)
*retval = pa_mainloop_get_retval(m);
return r;
}
dispatched += r;
return dispatched;
}
int pa_mainloop_run(pa_mainloop *m, int *retval) {
int r;
while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);

View file

@ -46,10 +46,27 @@ pa_mainloop *pa_mainloop_new(void);
/** Free a main loop object */
void pa_mainloop_free(pa_mainloop* m);
/** Run a single iteration of the main loop. Returns a negative value
on error or exit request. If block is nonzero, block for events if
none are queued. Optionally return the return value as specified with
the main loop's quit() routine in the integer variable retval points
/** Prepare for a single iteration of the main loop. Returns a negative value
on error or exit request. timeout specifies a maximum timeout for the subsequent
poll, or -1 for blocking behaviour. Defer events are also dispatched when this
function is called. On success returns the number of source dispatched in this
iteration.*/
int pa_mainloop_prepare(pa_mainloop *m, int timeout);
/** Execute the previously prepared poll. Returns a negative value on error.*/
int pa_mainloop_poll(pa_mainloop *m);
/** Dispatch timeout and io events from the previously executed poll. Returns
a negative value on error. On success returns the number of source dispatched. */
int pa_mainloop_dispatch(pa_mainloop *m);
/** Return the return value as specified with the main loop's quit() routine. */
int pa_mainloop_get_retval(pa_mainloop *m);
/** Run a single iteration of the main loop. This is a convenience function
for pa_mainloop_prepare(), pa_mainloop_poll() and pa_mainloop_dispatch().
Returns a negative value on error or exit request. If block is nonzero,
block for events if none are queued. Optionally return the return value as
specified with the main loop's quit() routine in the integer variable retval points
to. On success returns the number of source dispatched in this iteration. */
int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval);