From bbaf1543bd77e5c428e5e4c7d40fde0a42bf3daf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 13 Feb 2006 13:28:45 +0000 Subject: 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 --- polyp/mainloop.c | 157 +++++++++++++++++++++++++++++++++++++++---------------- polyp/mainloop.h | 25 +++++++-- 2 files changed, 133 insertions(+), 49 deletions(-) (limited to 'polyp') diff --git a/polyp/mainloop.c b/polyp/mainloop.c index 26ba2425..e131e1a1 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -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; + + assert(m && (m->state == STATE_PASSIVE)); - m->running ++; + 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); + return dispatched; - if(m->quit) - goto quit; - - if (r > 0) { - dispatched += dispatch_pollfds(m); +quit: - if(m->quit) - goto quit; - } - } - - m->running--; + m->state = STATE_QUIT; -/* pa_log("dispatched: %i\n", dispatched); */ + 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; - return r < 0 ? -1 : dispatched; + dispatched += dispatch_pollfds(m); + + if (m->quit) + goto quit; + + m->state = STATE_PASSIVE; + + return dispatched; quit: - - m->running--; - - if (retval) - *retval = m->retval; + + 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); diff --git a/polyp/mainloop.h b/polyp/mainloop.h index 06764907..2be9e6ff 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -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); -- cgit