[vlc-devel] [PATCH 1/2] win32: Add a vlc_mta_holder

Hugo Beauzée-Luyssen hugo at beauzee.fr
Fri Jun 23 13:00:27 CEST 2017


On Fri, Jun 23, 2017, at 12:58 PM, Hugo Beauzée-Luyssen wrote:
> This small helper will hold on to the MTA to ensure it won't be
> destroyed between two calls to CoInitializeEx.
> This will help us not leaking our TA configurations to libvlc/libvlccore
> threads
> ---
>  include/vlc_threads.h  |   1 +
>  src/Makefile.am        |   2 +-
>  src/misc/threads.c     |   1 +
>  src/win32/mta_holder.h | 121
>  +++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 124 insertions(+), 1 deletion(-)
>  create mode 100644 src/win32/mta_holder.h
> 
> diff --git a/include/vlc_threads.h b/include/vlc_threads.h
> index 9911d2eacf..fdf1dc4a9d 100644
> --- a/include/vlc_threads.h
> +++ b/include/vlc_threads.h
> @@ -1053,6 +1053,7 @@ enum
>     VLC_XLIB_MUTEX,
>     VLC_MOSAIC_MUTEX,
>     VLC_HIGHLIGHT_MUTEX,
> +   VLC_MTA_MUTEX,
>     /* Insert new entry HERE */
>     VLC_MAX_MUTEX
>  };
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 87cf8e3e29..c93a4021ee 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -468,7 +468,7 @@ libvlccore_la_LDFLAGS = \
>  libvlccore_la_DEPENDENCIES = libvlccore.sym
>  if HAVE_WIN32
>  libvlccore_la_DEPENDENCIES += libvlc_win32_rc.$(OBJEXT)
> -libvlccore_la_LDFLAGS += -Wl,libvlc_win32_rc.$(OBJEXT) -avoid-version
> -Wc,-static
> +libvlccore_la_LDFLAGS += -Wl,libvlc_win32_rc.$(OBJEXT) -avoid-version
> -Wc,-static $(LIBCOM)
>  endif
>  if HAVE_OS2
>  libvlccore_la_LDFLAGS += -avoid-version
> diff --git a/src/misc/threads.c b/src/misc/threads.c
> index dc8b89f702..f95a06c0e6 100644
> --- a/src/misc/threads.c
> +++ b/src/misc/threads.c
> @@ -37,6 +37,7 @@ void vlc_global_mutex (unsigned n, bool acquire)
>          VLC_STATIC_MUTEX,
>          VLC_STATIC_MUTEX,
>          VLC_STATIC_MUTEX,
> +        VLC_STATIC_MUTEX,
>      };
>      static_assert (VLC_MAX_MUTEX == (sizeof (locks) / sizeof
>      (locks[0])),
>                     "Wrong number of global mutexes");
> diff --git a/src/win32/mta_holder.h b/src/win32/mta_holder.h
> new file mode 100644
> index 0000000000..e5f4523b0a
> --- /dev/null
> +++ b/src/win32/mta_holder.h
> @@ -0,0 +1,121 @@
> +/*****************************************************************************
> + * mta_holder.c: Hold a MTA from another thread
> +
> *****************************************************************************
> + * Copyright (C) 2002-2017 the VideoLAN and AUTHORS
> + *
> + * Author: Hugo Beauzée-Luyssen <hugo at beauzee.fr>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
> 02110-1301, USA.
> +
> *****************************************************************************/
> +
> +#ifndef MTA_HOLDER_H
> +# define MTA_HOLDER_H
> +
> +#include <vlc_common.h>
> +
> +#include <assert.h>
> +#include <windows.h>
> +#include <objbase.h>
> +
> +typedef struct vlc_mta_holder
> +{
> +    vlc_thread_t thread;
> +    int          i_refcount;
> +    vlc_sem_t    ready_sem;
> +    vlc_sem_t    release_sem;
> +} vlc_mta_holder;
> +
> +static inline void* MtaMainLoop( void* opaque )
> +{
> +    vlc_mta_holder* p_mta = (vlc_mta_holder*)opaque;
> +    CoInitializeEx( NULL, COINIT_MULTITHREADED );
> +
> +    vlc_sem_post( &p_mta->ready_sem );
> +
> +    vlc_sem_wait( &p_mta->release_sem );
> +
> +    CoUninitialize();
> +    return NULL;
> +}
> +
> +/**
> + * Ensure an MTA context will be available until vlc_mta_release gets
> called.
> + *
> + * In the background, this will create a thread that does nothing but to
> keep the MTA
> + * refcount greater than 0.
> + *
> + * This is usefull in order not to commit a thread to a specific
> concurrency model.
> + * This function is win32 specific.
> + */
> +static inline vlc_mta_holder* vlc_mta_acquire( vlc_object_t *p_parent )
> +{
> +    vlc_global_lock( VLC_MTA_MUTEX );
> +    vlc_mta_holder* p_mta = (vlc_mta_holder*)var_CreateGetAddress(
> p_parent->obj.libvlc, "mta-holder" );
> +    if ( p_mta == NULL )
> +    {
> +        p_mta = (vlc_mta_holder*)malloc( sizeof( *p_mta ) );
> +        if ( unlikely( p_mta == NULL ) )
> +        {
> +            vlc_global_unlock( VLC_MTA_MUTEX );
> +            return NULL;
> +        }
> +        vlc_sem_init( &p_mta->ready_sem, 0 );
> +        vlc_sem_init( &p_mta->release_sem, 0 );
> +        p_mta->i_refcount = 1;
> +        if ( vlc_clone( &p_mta->thread, MtaMainLoop, p_mta,
> VLC_THREAD_PRIORITY_LOW ) )
> +        {
> +            vlc_sem_destroy( &p_mta->release_sem );
> +            vlc_sem_destroy( &p_mta->ready_sem );
> +            free( p_mta );
> +            p_mta = NULL;
> +            vlc_global_unlock( VLC_MTA_MUTEX );
> +            return NULL;
> +        }
> +        var_SetAddress( p_parent->obj.libvlc, "mta-holder", p_mta );
> +        vlc_sem_wait( &p_mta->ready_sem );
> +    }
> +    else
> +        ++p_mta->i_refcount;
> +    vlc_global_unlock( VLC_MTA_MUTEX );
> +    return p_mta;
> +}
> +
> +/**
> + * Releases a reference to the MTA holder.
> + *
> + * When its refcount reaches 0, the thread created by
> + */
> +static inline void vlc_mta_release( vlc_object_t* p_parent )
> +{
> +    vlc_global_lock( VLC_MTA_MUTEX );
> +    vlc_mta_holder *p_mta = (vlc_mta_holder*)var_InheritAddress(
> p_parent->obj.libvlc, "mta-holder" );
> +    assert( p_mta != NULL );
> +    int i_refcount = --p_mta->i_refcount;
> +    if ( i_refcount == 0 )
> +        var_SetAddress( p_parent->obj.libvlc, "mta-holder", NULL );
> +    vlc_global_unlock( VLC_MTA_MUTEX );
> +    if ( i_refcount == 0 )
> +    {
> +        vlc_sem_post( &p_mta->release_sem );
> +
> +        vlc_join( p_mta->thread, NULL );
> +
> +        vlc_sem_destroy( &p_mta->release_sem );
> +        vlc_sem_destroy( &p_mta->ready_sem );
> +        free( p_mta );
> +    }
> +}
> +
> +#endif
> -- 
> 2.11.0
> 

Woops, I forgot to include the changes in this revision:
- Give up on VLC_ADDRESS_EXCHANGE
- Use vlc_global_lock
- Use a semaphore instead of a condition variable to wait for MTA to be
released

Regards,

-- 
  Hugo Beauzée-Luyssen
  hugo at beauzee.fr


More information about the vlc-devel mailing list