]> 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 a694c14430e09c3037702e67eca57100f49732ee..61d8b4881093164244401b5634dfbc60e5c0bd16 100644 (file)
 #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"
@@ -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;
@@ -145,7 +153,7 @@ static pa_io_event* mainloop_io_new(
         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;
         }
     }
@@ -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,87 +636,102 @@ 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;
 }
 
@@ -710,39 +741,30 @@ int pa_mainloop_get_retval(pa_mainloop *m) {
 }
 
 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)
@@ -753,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) {
@@ -764,9 +788,11 @@ 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;
 }
 
 
@@ -774,7 +800,7 @@ int pa_mainloop_deferred_pending(pa_mainloop *m) {
 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;
@@ -783,7 +809,7 @@ void pa_mainloop_dump(pa_mainloop *m) {
             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);
         }
     }
     {
@@ -793,7 +819,7 @@ void pa_mainloop_dump(pa_mainloop *m) {
             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);
         }
     }
     {
@@ -803,11 +829,11 @@ void pa_mainloop_dump(pa_mainloop *m) {
             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