]> code.delx.au - pulseaudio/commitdiff
Add function to "wake up", i.e. interrupt, a running poll(). This is needed
authorPierre Ossman <ossman@cendio.se>
Mon, 13 Feb 2006 13:37:22 +0000 (13:37 +0000)
committerPierre Ossman <ossman@cendio.se>
Mon, 13 Feb 2006 13:37:22 +0000 (13:37 +0000)
when having the poll() in a separate thread.

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@479 fefdeb5f-60dc-0310-8127-8f9354f1896f

polyp/mainloop.c
polyp/mainloop.h

index e131e1a168ce29781e7b7f6706f86f2a7d2ebdf7..d25af78a5d1214baa6d0309c0bd96e6e1c529db6 100644 (file)
@@ -91,6 +91,8 @@ struct pa_mainloop {
 
     int deferred_pending;
 
+    int wakeup_pipe[2];
+
     enum {
         STATE_PASSIVE,
         STATE_PREPARED,
@@ -115,6 +117,8 @@ static pa_io_event* mainloop_io_new(
     m = a->userdata;
     assert(a == &m->api);
 
+    pa_mainloop_wakeup(m);
+
     e = pa_xmalloc(sizeof(pa_io_event));
     e->mainloop = m;
     e->dead = 0;
@@ -154,12 +158,17 @@ static pa_io_event* mainloop_io_new(
 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;
 }
 
 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;
 }
 
@@ -229,6 +238,8 @@ static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval
     m = a->userdata;
     assert(a == &m->api);
 
+    pa_mainloop_wakeup(m);
+
     e = pa_xmalloc(sizeof(pa_time_event));
     e->mainloop = m;
     e->dead = 0;
@@ -249,6 +260,8 @@ static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval
 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;
@@ -259,6 +272,8 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
 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;
 }
 
@@ -275,6 +290,8 @@ static void mainloop_quit(pa_mainloop_api*a, int retval) {
     m = a->userdata;
     assert(a == &m->api);
 
+    pa_mainloop_wakeup(m);
+
     m->quit = 1;
     m->retval = retval;
 }
@@ -305,6 +322,19 @@ pa_mainloop *pa_mainloop_new(void) {
 
     m = pa_xmalloc(sizeof(pa_mainloop));
 
+#ifndef OS_ISWIN32
+    if (pipe(m->wakeup_pipe) < 0) {
+        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->time_events = pa_idxset_new(NULL, NULL);
@@ -386,6 +416,12 @@ void pa_mainloop_free(pa_mainloop* m) {
     pa_idxset_free(m->defer_events, NULL, NULL);
 
     pa_xfree(m->pollfds);
+
+    if (m->wakeup_pipe[0] >= 0)
+        close(m->wakeup_pipe[0]);
+    if (m->wakeup_pipe[1] >= 0)
+        close(m->wakeup_pipe[1]);
+
     pa_xfree(m);
 }
 
@@ -409,7 +445,7 @@ static void rebuild_pollfds(pa_mainloop *m) {
     uint32_t idx = PA_IDXSET_INVALID;
     unsigned l;
 
-    l = pa_idxset_size(m->io_events);
+    l = pa_idxset_size(m->io_events) + 1;
     if (m->max_pollfds < l) {
         m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l);
         m->max_pollfds = l;
@@ -417,6 +453,15 @@ static void rebuild_pollfds(pa_mainloop *m) {
 
     m->n_pollfds = 0;
     p = m->pollfds;
+
+    if (m->wakeup_pipe[0] >= 0) {
+        m->pollfds[0].fd = m->wakeup_pipe[0];
+        m->pollfds[0].events = POLLIN;
+        m->pollfds[0].revents = 0;
+        p++;
+        m->n_pollfds++;
+    }
+
     for (e = pa_idxset_first(m->io_events, &idx); e; e = pa_idxset_next(m->io_events, &idx)) {
         if (e->dead) {
             e->pollfd = NULL;
@@ -558,11 +603,32 @@ static int dispatch_timeout(pa_mainloop *m) {
     return r;
 }
 
+void pa_mainloop_wakeup(pa_mainloop *m) {
+    char c = 'W';
+    assert(m);
+
+    if (m->wakeup_pipe[1] >= 0)
+        write(m->wakeup_pipe[1], &c, sizeof(c));
+}
+
+static void clear_wakeup(pa_mainloop *m) {
+    char c[10];
+
+    assert(m);
+
+    if (m->wakeup_pipe[0] < 0)
+        return;
+
+    while (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));
 
+    clear_wakeup(m);
+
     scan_dead(m);
 
     if (m->quit)
@@ -688,6 +754,7 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) {
 
 void pa_mainloop_quit(pa_mainloop *m, int r) {
     assert(m);
+    pa_mainloop_wakeup(m);
     m->quit = r;
 }
 
index 2be9e6ff0efb7fdb5c944322073f65530323eebc..921a070939ea7354e16a39cff56f30562b934408 100644 (file)
@@ -82,6 +82,9 @@ int pa_mainloop_deferred_pending(pa_mainloop *m);
 /** Shutdown the main loop */
 void pa_mainloop_quit(pa_mainloop *m, int r);
 
+/** Interrupt a running poll (for threaded systems) */
+void pa_mainloop_wakeup(pa_mainloop *m);
+
 PA_C_DECL_END
 
 #endif