[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