]> code.delx.au - pulseaudio/blobdiff - src/polyp/mainloop.c
* split pa_cstrerror() into its own file polypcore/core-error.[ch]
[pulseaudio] / src / polyp / mainloop.c
index da3f57b2e91949cfc3cb2071bc07638fa4e57164..61d8b4881093164244401b5634dfbc60e5c0bd16 100644 (file)
 
 #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"
@@ -101,6 +108,9 @@ struct pa_mainloop {
         STATE_POLLED,
         STATE_QUIT
     } state;
+
+    pa_poll_func poll_func;
+    void *poll_func_userdata;
 };
 
 /* IO events */
@@ -118,8 +128,6 @@ 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;
@@ -153,24 +161,27 @@ static pa_io_event* mainloop_io_new(
 
     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)) {
@@ -199,6 +210,9 @@ static pa_defer_event* mainloop_defer_new(pa_mainloop_api*a, void (*callback) (p
     pa_idxset_put(m->defer_events, e, NULL);
 
     m->deferred_pending++;
+
+    pa_mainloop_wakeup(e->mainloop);
+
     return e;
 }
 
@@ -208,8 +222,10 @@ static void mainloop_defer_enable(pa_defer_event *e, int b) {
     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;
 }
@@ -239,8 +255,6 @@ 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;
@@ -254,6 +268,9 @@ static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval
     e->destroy_callback = NULL;
 
     pa_idxset_put(m->time_events, e, NULL);
+
+    if (e->enabled)
+        pa_mainloop_wakeup(m);
     
     return e;
 }
@@ -261,11 +278,11 @@ 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;
+
+        pa_mainloop_wakeup(e->mainloop);
     } else
         e->enabled = 0;
 }
@@ -273,9 +290,9 @@ 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;
+
+    /* 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)) {
@@ -291,10 +308,7 @@ 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;
+    pa_mainloop_quit(m, retval);
 }
     
 static const pa_mainloop_api vtable = {
@@ -323,18 +337,14 @@ pa_mainloop *pa_mainloop_new(void) {
 
     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);
@@ -345,7 +355,8 @@ pa_mainloop *pa_mainloop_new(void) {
     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;
 
@@ -355,6 +366,11 @@ pa_mainloop *pa_mainloop_new(void) {
     m->deferred_pending = 0;
 
     m->state = STATE_PASSIVE;
+
+    m->poll_func = NULL;
+    m->poll_func_userdata = NULL;
+
+    m->retval = -1;
     
     return m;
 }
@@ -406,7 +422,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 && (m->state != STATE_POLLING));
+    assert(m);
 
     pa_idxset_foreach(m->io_events, io_foreach, &all);
     pa_idxset_foreach(m->time_events, time_foreach, &all);
@@ -609,7 +625,7 @@ void pa_mainloop_wakeup(pa_mainloop *m) {
     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) {
@@ -620,7 +636,7 @@ 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) {
@@ -665,13 +681,16 @@ int pa_mainloop_poll(pa_mainloop *m) {
     if (m->deferred_pending)
         r = 0;
     else {
-        r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout);
+        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) {
             if (errno == EINTR)
                 r = 0;
             else
-                pa_log(__FILE__": poll(): %s", strerror(errno));
+                pa_log(__FILE__": poll(): %s", pa_cstrerror(errno));
         }
     }
 
@@ -756,10 +775,12 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) {
         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) {
@@ -767,6 +788,14 @@ pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
     return &m->api;
 }
 
+void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
+    assert(m);
+
+    m->poll_func = poll_func;
+    m->poll_func_userdata = userdata;
+}
+
+
 #if 0
 void pa_mainloop_dump(pa_mainloop *m) {
     assert(m);