1 /*****************************************************************************
2 * mta_holder.c: Hold a MTA from another thread
3 *****************************************************************************
4 * Copyright (C) 2002-2017 the VideoLAN and AUTHORS
6 * Author: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
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.
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.
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 *****************************************************************************/
26 #include <vlc_common.h>
32 typedef struct vlc_mta_holder
37 vlc_sem_t release_sem
;
40 static inline void* MtaMainLoop( void* opaque
)
42 vlc_mta_holder
* p_mta
= (vlc_mta_holder
*)opaque
;
43 CoInitializeEx( NULL
, COINIT_MULTITHREADED
);
45 vlc_sem_post( &p_mta
->ready_sem
);
47 vlc_sem_wait( &p_mta
->release_sem
);
54 * Ensure an MTA context will be available until vlc_mta_release gets called.
56 * In the background, this will create a thread that does nothing but to keep the MTA
57 * refcount greater than 0.
59 * This is usefull in order not to commit a thread to a specific concurrency model.
60 * This function is win32 specific.
62 static inline bool vlc_mta_acquire( vlc_object_t
*p_parent
)
64 vlc_global_lock( VLC_MTA_MUTEX
);
65 vlc_mta_holder
* p_mta
= (vlc_mta_holder
*)var_CreateGetAddress( p_parent
->obj
.libvlc
, "mta-holder" );
68 p_mta
= (vlc_mta_holder
*)malloc( sizeof( *p_mta
) );
69 if ( unlikely( p_mta
== NULL
) )
71 vlc_global_unlock( VLC_MTA_MUTEX
);
74 vlc_sem_init( &p_mta
->ready_sem
, 0 );
75 vlc_sem_init( &p_mta
->release_sem
, 0 );
76 p_mta
->i_refcount
= 1;
77 if ( vlc_clone( &p_mta
->thread
, MtaMainLoop
, p_mta
, VLC_THREAD_PRIORITY_LOW
) )
79 vlc_sem_destroy( &p_mta
->release_sem
);
80 vlc_sem_destroy( &p_mta
->ready_sem
);
83 vlc_global_unlock( VLC_MTA_MUTEX
);
86 var_SetAddress( p_parent
->obj
.libvlc
, "mta-holder", p_mta
);
87 vlc_sem_wait( &p_mta
->ready_sem
);
91 vlc_global_unlock( VLC_MTA_MUTEX
);
96 * Releases a reference to the MTA holder.
98 * When its refcount reaches 0, the thread created by
100 static inline void vlc_mta_release( vlc_object_t
* p_parent
)
102 vlc_global_lock( VLC_MTA_MUTEX
);
103 vlc_mta_holder
*p_mta
= (vlc_mta_holder
*)var_InheritAddress( p_parent
->obj
.libvlc
, "mta-holder" );
104 assert( p_mta
!= NULL
);
105 int i_refcount
= --p_mta
->i_refcount
;
106 if ( i_refcount
== 0 )
107 var_SetAddress( p_parent
->obj
.libvlc
, "mta-holder", NULL
);
108 vlc_global_unlock( VLC_MTA_MUTEX
);
109 if ( i_refcount
== 0 )
111 vlc_sem_post( &p_mta
->release_sem
);
113 vlc_join( p_mta
->thread
, NULL
);
115 vlc_sem_destroy( &p_mta
->release_sem
);
116 vlc_sem_destroy( &p_mta
->ready_sem
);