[vlc-devel] [PATCH 4/5] vlccore: implement timeout-free poll()
Rémi Denis-Courmont
remi at remlab.net
Sat Mar 2 17:27:45 CET 2013
Le samedi 2 mars 2013 17:11:09, KO Myung-Hun a écrit :
> ---
> 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>
Not that I care personally, but does this not break Windows?
> +
> +# ifndef INT64_C
> +# define INT64_C(c) (c ## LL)
> +# endif
int64_t is not necessarily long long.
> +
> +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);
That's wrong. poll() is always a cancellation point even if the timeout is
zeor.
> +
> + 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)
And that's quite much code for an inline function.
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list