VLC 4.0.0-dev
mta_holder.h
Go to the documentation of this file.
1/*****************************************************************************
2 * mta_holder.c: Hold a MTA from another thread
3 *****************************************************************************
4 * Copyright (C) 2002-2017 the VideoLAN and AUTHORS
5 *
6 * Author: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
22
23#ifndef MTA_HOLDER_H
24# define MTA_HOLDER_H
25
26#include <vlc_common.h>
27#include <vlc_threads.h>
28
29#include <assert.h>
30#include <windows.h>
31#include <objbase.h>
32
33typedef struct vlc_mta_holder
34{
40
41static inline void* MtaMainLoop( void* opaque )
42{
43 vlc_thread_set_name("vlc-mta");
44
45 vlc_mta_holder* p_mta = (vlc_mta_holder*)opaque;
46 CoInitializeEx( NULL, COINIT_MULTITHREADED );
47
48 vlc_sem_post( &p_mta->ready_sem );
49
50 vlc_sem_wait( &p_mta->release_sem );
51
52 CoUninitialize();
53 return NULL;
54}
55
56/**
57 * Ensure an MTA context will be available until vlc_mta_release gets called.
58 *
59 * In the background, this will create a thread that does nothing but to keep the MTA
60 * refcount greater than 0.
61 *
62 * This is useful in order not to commit a thread to a specific concurrency model.
63 * This function is win32 specific.
64 */
65static inline bool vlc_mta_acquire( vlc_object_t *p_parent )
66{
68
69 vlc_global_lock( VLC_MTA_MUTEX );
70 vlc_mta_holder* p_mta = (vlc_mta_holder*)var_CreateGetAddress( vlc, "mta-holder" );
71 if ( p_mta == NULL )
72 {
73 p_mta = (vlc_mta_holder*)malloc( sizeof( *p_mta ) );
74 if ( unlikely( p_mta == NULL ) )
75 {
76 vlc_global_unlock( VLC_MTA_MUTEX );
77 return false;
78 }
79 vlc_sem_init( &p_mta->ready_sem, 0 );
80 vlc_sem_init( &p_mta->release_sem, 0 );
81 p_mta->i_refcount = 1;
82 if ( vlc_clone( &p_mta->thread, MtaMainLoop, p_mta ) )
83 {
84 free( p_mta );
85 p_mta = NULL;
86 vlc_global_unlock( VLC_MTA_MUTEX );
87 return false;
88 }
89 var_SetAddress( vlc, "mta-holder", p_mta );
90 vlc_sem_wait( &p_mta->ready_sem );
91 }
92 else
93 ++p_mta->i_refcount;
94 vlc_global_unlock( VLC_MTA_MUTEX );
95 return true;
96}
97
98/**
99 * Releases a reference to the MTA holder.
100 *
101 * When its refcount reaches 0, the thread created by
102 */
103static inline void vlc_mta_release( vlc_object_t* p_parent )
104{
106
107 vlc_global_lock( VLC_MTA_MUTEX );
108 vlc_mta_holder *p_mta = (vlc_mta_holder*)var_InheritAddress( vlc, "mta-holder" );
109 assert( p_mta != NULL );
110 int i_refcount = --p_mta->i_refcount;
111 if ( i_refcount == 0 )
112 var_SetAddress( vlc, "mta-holder", NULL );
113 vlc_global_unlock( VLC_MTA_MUTEX );
114 if ( i_refcount == 0 )
115 {
116 vlc_sem_post( &p_mta->release_sem );
117
118 vlc_join( p_mta->thread, NULL );
119
120 free( p_mta );
121 }
122}
123
124#endif
#define unlikely(p)
Predicted false condition.
Definition: vlc_common.h:257
void vlc_sem_wait(vlc_sem_t *sem)
Waits on a semaphore.
Definition: threads.c:355
int vlc_sem_post(vlc_sem_t *sem)
Increments the value of a semaphore.
Definition: threads.c:339
void vlc_sem_init(vlc_sem_t *sem, unsigned value)
Initializes a semaphore.
Definition: threads.c:334
#define vlc_global_lock(n)
Acquires a global mutex.
Definition: vlc_threads.h:1158
void vlc_join(vlc_thread_t handle, void **result)
Waits for a thread to complete (if needed), then destroys it.
Definition: thread.c:146
int vlc_clone(vlc_thread_t *th, void *(*entry)(void *), void *data)
Creates and starts a new thread.
Definition: thread.c:141
#define vlc_global_unlock(n)
Releases a global mutex.
Definition: vlc_threads.h:1163
void() vlc_thread_set_name(const char *name)
Set the thread name of the current thread.
Definition: thread.c:28
static void * var_CreateGetAddress(vlc_object_t *p_obj, const char *psz_name)
Create an address variable with inherit and get its value.
Definition: vlc_variables.h:584
static int var_SetAddress(vlc_object_t *p_obj, const char *psz_name, void *ptr)
Set the value of a pointer variable.
Definition: vlc_variables.h:360
static void * var_InheritAddress(vlc_object_t *obj, const char *name)
Definition: vlc_variables.h:720
#define VLC_OBJECT(x)
Type-safe vlc_object_t cast.
Definition: vlc_objects.h:71
#define vlc_object_instance(o)
Definition: vlc_objects.h:178
static void vlc_mta_release(vlc_object_t *p_parent)
Releases a reference to the MTA holder.
Definition: mta_holder.h:103
struct vlc_mta_holder vlc_mta_holder
static bool vlc_mta_acquire(vlc_object_t *p_parent)
Ensure an MTA context will be available until vlc_mta_release gets called.
Definition: mta_holder.h:65
static void * MtaMainLoop(void *opaque)
Definition: mta_holder.h:41
Definition: mta_holder.h:34
int i_refcount
Definition: mta_holder.h:36
vlc_sem_t release_sem
Definition: mta_holder.h:38
vlc_thread_t thread
Definition: mta_holder.h:35
vlc_sem_t ready_sem
Definition: mta_holder.h:37
VLC object common members.
Definition: vlc_objects.h:45
Semaphore.
Definition: vlc_threads.h:422
Thread handle.
Definition: vlc_threads.h:160
This file is a collection of common definitions and types.
Thread primitive declarations.