[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