[vlc-devel] [PATCH 4/5] vlccore: implement timeout-free poll()

KO Myung-Hun komh78 at gmail.com
Sat Mar 2 16:11:09 CET 2013


---
 include/vlc_threads.h |  112 +++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 103 insertions(+), 9 deletions(-)

diff --git a/include/vlc_threads.h b/include/vlc_threads.h
index 12b56fd..475eaec 100644
--- a/include/vlc_threads.h
+++ b/include/vlc_threads.h
@@ -385,23 +385,117 @@ struct vlc_cleanup_t
 #endif /* !LIBVLC_USE_PTHREAD_CLEANUO */
 
 #ifndef LIBVLC_USE_PTHREAD_CANCEL
+# include <unistd.h>
+# include <sys/socket.h>
+
+# ifndef INT64_C
+#  define INT64_C(c) (c ## LL)
+# endif
+
+typedef struct
+{
+    int            cancel[2];
+    vlc_mutex_t    mutex;
+    vlc_cond_t     cond;
+    struct pollfd* fds;
+    unsigned       nfds;
+} vlc_poll_thread_data_t;
+
+static inline void *vlc_poll_thread (void* arg)
+{
+    vlc_poll_thread_data_t *data = (vlc_poll_thread_data_t *)arg;
+
+    int val = poll (data->fds, data->nfds, -1);
+
+    if (data->fds[data->nfds - 1].revents & POLLIN ) /* Canceled ? */
+        val = 0;
+    else
+        vlc_cond_signal (&data->cond);
+
+    return (void *)val;
+}
+
+static inline void vlc_poll_thread_cleanup (void *arg)
+{
+    vlc_poll_thread_data_t *data = (vlc_poll_thread_data_t *)arg;
+
+    /* Wake up if vlc_poll_thread() is sleeping */
+    write (data->cancel[1], &data->cancel[1], sizeof (data->cancel[1]));
+
+    vlc_mutex_unlock (&data->mutex );
+
+    vlc_cond_destroy (&data->cond);
+    vlc_mutex_destroy (&data->mutex);
+
+    close (data->cancel[0]);
+    close (data->cancel[1]);
+}
+
 /* poll() with cancellation */
 static inline int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
 {
-    int val;
+    if (!timeout)
+        return poll (fds, nfds, timeout);
+
+    vlc_poll_thread_data_t data;
+    struct pollfd          newfds[nfds + 1];
+
+    vlc_thread_t  th;
+    void         *val;
+
+    socketpair (AF_LOCAL, SOCK_STREAM, 0, data.cancel);
+
+    vlc_mutex_init (&data.mutex);
+    vlc_cond_init (&data.cond);
 
-    do
+    memcpy (newfds, fds, sizeof (*fds) * nfds);
+    newfds[nfds].fd      = data.cancel[0];
+    newfds[nfds].events  = POLLIN;
+    newfds[nfds].revents = 0;
+
+    data.fds  = newfds;
+    data.nfds = nfds + 1;
+
+    if (vlc_clone (&th, vlc_poll_thread, &data, VLC_THREAD_PRIORITY_INPUT))
     {
-        int ugly_timeout = ((unsigned)timeout >= 50) ? 50 : timeout;
-        if (timeout >= 0)
-            timeout -= ugly_timeout;
+        vlc_cond_destroy (&data.cond);
+        vlc_mutex_destroy (&data.mutex);
 
-        vlc_testcancel ();
-        val = poll (fds, nfds, ugly_timeout);
+        close (data.cancel[0]);
+        close (data.cancel[1]);
+
+        return -1;
     }
-    while (val == 0 && timeout != 0);
 
-    return val;
+    vlc_mutex_lock (&data.mutex);
+
+    vlc_cleanup_push (vlc_poll_thread_cleanup, &data);
+
+    if (timeout < 0)
+        vlc_cond_wait (&data.cond, &data.mutex);
+    else
+        vlc_cond_timedwait (&data.cond, &data.mutex,
+                            mdate () + timeout * CLOCK_FREQ / 1000);
+
+    vlc_cleanup_pop();
+
+    /* Wake up if vlcl_poll_thread() is sleeping */
+    write (data.cancel[1], &data.cancel[1], sizeof (data.cancel[1]));
+
+    vlc_mutex_unlock (&data.mutex);
+
+    /* Get a return value */
+    vlc_join (th, &val);
+
+    memcpy (fds, newfds, sizeof(*fds) * nfds);
+
+    vlc_cond_destroy (&data.cond);
+    vlc_mutex_destroy (&data.mutex);
+
+    close (data.cancel[0]);
+    close (data.cancel[1]);
+
+    return (int)val;
 }
 # define poll(u,n,t) vlc_poll(u, n, t)
 
-- 
1.7.3.2




More information about the vlc-devel mailing list