mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
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:
parent
4ab432a819
commit
bbaf1543bd
2 changed files with 137 additions and 53 deletions
165
polyp/mainloop.c
165
polyp/mainloop.c
|
|
@ -84,10 +84,20 @@ struct pa_mainloop {
|
||||||
unsigned max_pollfds, n_pollfds;
|
unsigned max_pollfds, n_pollfds;
|
||||||
int rebuild_pollfds;
|
int rebuild_pollfds;
|
||||||
|
|
||||||
int quit, running, retval;
|
int prepared_timeout;
|
||||||
|
|
||||||
|
int quit, retval;
|
||||||
pa_mainloop_api api;
|
pa_mainloop_api api;
|
||||||
|
|
||||||
int deferred_pending;
|
int deferred_pending;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
STATE_PASSIVE,
|
||||||
|
STATE_PREPARED,
|
||||||
|
STATE_POLLING,
|
||||||
|
STATE_POLLED,
|
||||||
|
STATE_QUIT
|
||||||
|
} state;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* IO events */
|
/* 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);
|
assert(e && e->mainloop);
|
||||||
|
|
||||||
e->events = events;
|
e->events = events;
|
||||||
if (e->pollfd)
|
e->mainloop->rebuild_pollfds = 1;
|
||||||
e->pollfd->events =
|
|
||||||
(events & PA_IO_EVENT_INPUT ? POLLIN : 0) |
|
|
||||||
(events & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
|
|
||||||
POLLERR | POLLHUP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mainloop_io_free(pa_io_event *e) {
|
static void mainloop_io_free(pa_io_event *e) {
|
||||||
|
|
@ -310,12 +316,14 @@ pa_mainloop *pa_mainloop_new(void) {
|
||||||
m->pollfds = NULL;
|
m->pollfds = NULL;
|
||||||
m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0;
|
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 = vtable;
|
||||||
m->api.userdata = m;
|
m->api.userdata = m;
|
||||||
|
|
||||||
m->deferred_pending = 0;
|
m->deferred_pending = 0;
|
||||||
|
|
||||||
|
m->state = STATE_PASSIVE;
|
||||||
|
|
||||||
return m;
|
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) {
|
void pa_mainloop_free(pa_mainloop* m) {
|
||||||
int all = 1;
|
int all = 1;
|
||||||
assert(m);
|
assert(m && (m->state != STATE_POLLING));
|
||||||
|
|
||||||
pa_idxset_foreach(m->io_events, io_foreach, &all);
|
pa_idxset_foreach(m->io_events, io_foreach, &all);
|
||||||
pa_idxset_foreach(m->time_events, time_foreach, &all);
|
pa_idxset_foreach(m->time_events, time_foreach, &all);
|
||||||
|
|
@ -427,6 +435,8 @@ static void rebuild_pollfds(pa_mainloop *m) {
|
||||||
p++;
|
p++;
|
||||||
m->n_pollfds++;
|
m->n_pollfds++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m->rebuild_pollfds = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dispatch_pollfds(pa_mainloop *m) {
|
static int dispatch_pollfds(pa_mainloop *m) {
|
||||||
|
|
@ -548,65 +558,122 @@ static int dispatch_timeout(pa_mainloop *m) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
|
int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
|
||||||
int r, t, dispatched = 0;
|
int dispatched = 0;
|
||||||
assert(m && !m->running);
|
|
||||||
|
|
||||||
m->running ++;
|
assert(m && (m->state == STATE_PASSIVE));
|
||||||
|
|
||||||
|
scan_dead(m);
|
||||||
|
|
||||||
if (m->quit)
|
if (m->quit)
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
||||||
scan_dead(m);
|
|
||||||
dispatched += dispatch_defer(m);
|
dispatched += dispatch_defer(m);
|
||||||
|
|
||||||
if(m->quit)
|
if (m->quit)
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
||||||
if (m->rebuild_pollfds) {
|
if (m->rebuild_pollfds)
|
||||||
rebuild_pollfds(m);
|
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) {
|
return dispatched;
|
||||||
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;
|
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
|
|
||||||
m->running--;
|
m->state = STATE_QUIT;
|
||||||
|
|
||||||
if (retval)
|
|
||||||
*retval = m->retval;
|
|
||||||
|
|
||||||
return -2;
|
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 pa_mainloop_run(pa_mainloop *m, int *retval) {
|
||||||
int r;
|
int r;
|
||||||
while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
|
while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,27 @@ pa_mainloop *pa_mainloop_new(void);
|
||||||
/** Free a main loop object */
|
/** Free a main loop object */
|
||||||
void pa_mainloop_free(pa_mainloop* m);
|
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
|
/** Prepare for a single iteration of the main loop. Returns a negative value
|
||||||
none are queued. Optionally return the return value as specified with
|
on error or exit request. timeout specifies a maximum timeout for the subsequent
|
||||||
the main loop's quit() routine in the integer variable retval points
|
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. */
|
to. On success returns the number of source dispatched in this iteration. */
|
||||||
int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval);
|
int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue