#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#else
-#include "poll.h"
+#include "../polypcore/poll.h"
#endif
#include "../polypcore/winsock.h"
-#include <polypcore/util.h>
+#ifndef HAVE_PIPE
+#include "../polypcore/pipe.h"
+#endif
+
+#include <polypcore/core-error.h>
+#include <polyp/timeval.h>
+#include <polyp/xmalloc.h>
+
+#include <polypcore/core-util.h>
#include <polypcore/idxset.h>
-#include <polypcore/xmalloc.h>
#include <polypcore/log.h>
#include "mainloop.h"
STATE_POLLED,
STATE_QUIT
} state;
+
+ pa_poll_func poll_func;
+ void *poll_func_userdata;
};
/* IO events */
m = a->userdata;
assert(a == &m->api);
- pa_mainloop_wakeup(m);
-
e = pa_xmalloc(sizeof(pa_io_event));
e->mainloop = m;
e->dead = 0;
if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset,
SELECT_TYPE_ARG5 &tv) == -1) &&
(WSAGetLastError() == WSAENOTSOCK)) {
- pa_log_warn(__FILE__": WARNING: cannot monitor non-socket file descriptors.\n");
+ pa_log_warn(__FILE__": WARNING: cannot monitor non-socket file descriptors.");
e->dead = 1;
}
}
pa_idxset_put(m->io_events, e, NULL);
m->rebuild_pollfds = 1;
+
+ pa_mainloop_wakeup(m);
+
return e;
}
static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
assert(e && e->mainloop);
- pa_mainloop_wakeup(e->mainloop);
-
e->events = events;
e->mainloop->rebuild_pollfds = 1;
+
+ pa_mainloop_wakeup(e->mainloop);
}
static void mainloop_io_free(pa_io_event *e) {
assert(e && e->mainloop);
- pa_mainloop_wakeup(e->mainloop);
-
e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1;
+
+ pa_mainloop_wakeup(e->mainloop);
}
static void mainloop_io_set_destroy(pa_io_event *e, void (*callback)(pa_mainloop_api*a, pa_io_event *e, void *userdata)) {
pa_idxset_put(m->defer_events, e, NULL);
m->deferred_pending++;
+
+ pa_mainloop_wakeup(e->mainloop);
+
return e;
}
if (e->enabled && !b) {
assert(e->mainloop->deferred_pending > 0);
e->mainloop->deferred_pending--;
- } else if (!e->enabled && b)
+ } else if (!e->enabled && b) {
e->mainloop->deferred_pending++;
+ pa_mainloop_wakeup(e->mainloop);
+ }
e->enabled = b;
}
m = a->userdata;
assert(a == &m->api);
- pa_mainloop_wakeup(m);
-
e = pa_xmalloc(sizeof(pa_time_event));
e->mainloop = m;
e->dead = 0;
e->destroy_callback = NULL;
pa_idxset_put(m->time_events, e, NULL);
+
+ if (e->enabled)
+ pa_mainloop_wakeup(m);
return e;
}
static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
assert(e);
- pa_mainloop_wakeup(e->mainloop);
-
if (tv) {
e->enabled = 1;
e->timeval = *tv;
+
+ pa_mainloop_wakeup(e->mainloop);
} else
e->enabled = 0;
}
static void mainloop_time_free(pa_time_event *e) {
assert(e);
- pa_mainloop_wakeup(e->mainloop);
-
e->dead = e->mainloop->time_events_scan_dead = 1;
+
+ /* no wakeup needed here. Think about it! */
}
static void mainloop_time_set_destroy(pa_time_event *e, void (*callback)(pa_mainloop_api*a, pa_time_event *e, void *userdata)) {
m = a->userdata;
assert(a == &m->api);
- pa_mainloop_wakeup(m);
-
- m->quit = 1;
- m->retval = retval;
+ pa_mainloop_quit(m, retval);
}
static const pa_mainloop_api vtable = {
m = pa_xmalloc(sizeof(pa_mainloop));
-#ifndef OS_IS_WIN32
if (pipe(m->wakeup_pipe) < 0) {
+ pa_log_error(__FILE__": ERROR: cannot create wakeup pipe");
pa_xfree(m);
return NULL;
}
pa_make_nonblock_fd(m->wakeup_pipe[0]);
pa_make_nonblock_fd(m->wakeup_pipe[1]);
-#else
- m->wakeup_pipe[0] = -1;
- m->wakeup_pipe[1] = -1;
-#endif
m->io_events = pa_idxset_new(NULL, NULL);
m->defer_events = pa_idxset_new(NULL, NULL);
m->io_events_scan_dead = m->defer_events_scan_dead = m->time_events_scan_dead = 0;
m->pollfds = NULL;
- m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0;
+ m->max_pollfds = m->n_pollfds = 0;
+ m->rebuild_pollfds = 1;
m->quit = m->retval = 0;
m->deferred_pending = 0;
m->state = STATE_PASSIVE;
+
+ m->poll_func = NULL;
+ m->poll_func_userdata = NULL;
+
+ m->retval = -1;
return m;
}
void pa_mainloop_free(pa_mainloop* m) {
int all = 1;
- assert(m && (m->state != STATE_POLLING));
+ assert(m);
pa_idxset_foreach(m->io_events, io_foreach, &all);
pa_idxset_foreach(m->time_events, time_foreach, &all);
assert(m);
if (m->wakeup_pipe[1] >= 0)
- write(m->wakeup_pipe[1], &c, sizeof(c));
+ pa_write(m->wakeup_pipe[1], &c, sizeof(c));
}
static void clear_wakeup(pa_mainloop *m) {
if (m->wakeup_pipe[0] < 0)
return;
- while (read(m->wakeup_pipe[0], &c, sizeof(c)) == sizeof(c));
+ while (pa_read(m->wakeup_pipe[0], &c, sizeof(c)) == sizeof(c));
}
int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
- int dispatched = 0;
-
- assert(m && (m->state == STATE_PASSIVE));
+ assert(m);
+ assert(m->state == STATE_PASSIVE);
clear_wakeup(m);
-
scan_dead(m);
if (m->quit)
goto quit;
- dispatched += dispatch_defer(m);
-
- if (m->quit)
- goto quit;
-
- if (m->rebuild_pollfds)
- rebuild_pollfds(m);
-
- m->prepared_timeout = calc_next_timeout(m);
- if ((timeout >= 0) && (m->prepared_timeout > timeout))
- m->prepared_timeout = timeout;
+ if (!m->deferred_pending) {
+
+ if (m->rebuild_pollfds)
+ rebuild_pollfds(m);
+
+ m->prepared_timeout = calc_next_timeout(m);
+ if (timeout >= 0 && (timeout < m->prepared_timeout || m->prepared_timeout < 0))
+ m->prepared_timeout = timeout;
+ }
m->state = STATE_PREPARED;
-
- return dispatched;
+ return 0;
quit:
-
m->state = STATE_QUIT;
-
return -2;
}
int pa_mainloop_poll(pa_mainloop *m) {
int r;
- assert(m && (m->state == STATE_PREPARED));
+ assert(m);
+ assert(m->state == STATE_PREPARED);
- m->state = STATE_POLLING;
+ if (m->quit)
+ goto quit;
- r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout);
+ m->state = STATE_POLLING;
- if ((r < 0) && (errno == EINTR))
- r = 0;
+ if (m->deferred_pending)
+ r = 0;
+ else {
+ if (m->poll_func)
+ r = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata);
+ else
+ r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout);
- if (r < 0)
- m->state = STATE_PASSIVE;
- else
- m->state = STATE_POLLED;
+ if (r < 0) {
+ if (errno == EINTR)
+ r = 0;
+ else
+ pa_log(__FILE__": poll(): %s", pa_cstrerror(errno));
+ }
+ }
+ m->state = r < 0 ? STATE_PASSIVE : STATE_POLLED;
return r;
+
+quit:
+ m->state = STATE_QUIT;
+ return -2;
}
int pa_mainloop_dispatch(pa_mainloop *m) {
int dispatched = 0;
- assert(m && (m->state == STATE_POLLED));
-
- dispatched += dispatch_timeout(m);
+ assert(m);
+ assert(m->state == STATE_POLLED);
if (m->quit)
goto quit;
- dispatched += dispatch_pollfds(m);
+ if (m->deferred_pending)
+ dispatched += dispatch_defer(m);
+ else {
+ 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_iterate(pa_mainloop *m, int block, int *retval) {
- int r, dispatched = 0;
-
+ int r;
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;
+ if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
+ goto quit;
- r = pa_mainloop_poll(m);
- if (r < 0) {
- pa_log(__FILE__": poll(): %s\n", strerror(errno));
- return r;
- }
+ if ((r = pa_mainloop_poll(m)) < 0)
+ goto quit;
- r = pa_mainloop_dispatch(m);
- if (r < 0) {
- if ((r == -2) && retval)
- *retval = pa_mainloop_get_retval(m);
- return r;
- }
+ if ((r = pa_mainloop_dispatch(m)) < 0)
+ goto quit;
- dispatched += r;
+ return r;
- return dispatched;
+quit:
+
+ if ((r == -2) && retval)
+ *retval = pa_mainloop_get_retval(m);
+ return r;
}
int pa_mainloop_run(pa_mainloop *m, int *retval) {
int r;
+
while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
if (r == -2)
return 0;
}
-void pa_mainloop_quit(pa_mainloop *m, int r) {
+void pa_mainloop_quit(pa_mainloop *m, int retval) {
assert(m);
+
+ m->quit = 1;
+ m->retval = retval;
pa_mainloop_wakeup(m);
- m->quit = r;
}
pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
return &m->api;
}
-int pa_mainloop_deferred_pending(pa_mainloop *m) {
+void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
assert(m);
- return m->deferred_pending > 0;
+
+ m->poll_func = poll_func;
+ m->poll_func_userdata = userdata;
}
void pa_mainloop_dump(pa_mainloop *m) {
assert(m);
- pa_log(__FILE__": Dumping mainloop sources START\n");
+ pa_log(__FILE__": Dumping mainloop sources START");
{
uint32_t idx = PA_IDXSET_INVALID;
if (e->dead)
continue;
- pa_log(__FILE__": kind=io fd=%i events=%i callback=%p userdata=%p\n", e->fd, (int) e->events, (void*) e->callback, (void*) e->userdata);
+ pa_log(__FILE__": kind=io fd=%i events=%i callback=%p userdata=%p", e->fd, (int) e->events, (void*) e->callback, (void*) e->userdata);
}
}
{
if (e->dead)
continue;
- pa_log(__FILE__": kind=defer enabled=%i callback=%p userdata=%p\n", e->enabled, (void*) e->callback, (void*) e->userdata);
+ pa_log(__FILE__": kind=defer enabled=%i callback=%p userdata=%p", e->enabled, (void*) e->callback, (void*) e->userdata);
}
}
{
if (e->dead)
continue;
- pa_log(__FILE__": kind=time enabled=%i time=%lu.%lu callback=%p userdata=%p\n", e->enabled, (unsigned long) e->timeval.tv_sec, (unsigned long) e->timeval.tv_usec, (void*) e->callback, (void*) e->userdata);
+ pa_log(__FILE__": kind=time enabled=%i time=%lu.%lu callback=%p userdata=%p", e->enabled, (unsigned long) e->timeval.tv_sec, (unsigned long) e->timeval.tv_usec, (void*) e->callback, (void*) e->userdata);
}
}
- pa_log(__FILE__": Dumping mainloop sources STOP\n");
+ pa_log(__FILE__": Dumping mainloop sources STOP");
}
#endif