[vlc-commits] preparser: interrupt the thread by stopping input_thread_t
Thomas Guillem
git at videolan.org
Sun Jun 5 13:02:13 CEST 2016
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Sat Jun 4 16:22:22 2016 +0200| [f30ae6b016b6dca3a4c072f98486f9e81044ead3] | committer: Thomas Guillem
preparser: interrupt the thread by stopping input_thread_t
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f30ae6b016b6dca3a4c072f98486f9e81044ead3
---
src/playlist/preparser.c | 61 +++++++++++++++++++++++++++-------------------
1 file changed, 36 insertions(+), 25 deletions(-)
diff --git a/src/playlist/preparser.c b/src/playlist/preparser.c
index 5315dc4..f360a47 100644
--- a/src/playlist/preparser.c
+++ b/src/playlist/preparser.c
@@ -25,6 +25,8 @@
# include "config.h"
#endif
+#include <assert.h>
+
#include <vlc_common.h>
#include "fetcher.h"
@@ -47,9 +49,12 @@ struct playlist_preparser_t
vlc_object_t *object;
playlist_fetcher_t *p_fetcher;
+ input_thread_t *input;
+ bool input_done;
+
vlc_mutex_t lock;
vlc_cond_t wait;
- vlc_sem_t item_done;
+ vlc_cond_t thread_wait;
bool b_live;
preparser_entry_t **pp_waiting;
int i_waiting;
@@ -66,6 +71,8 @@ playlist_preparser_t *playlist_preparser_New( vlc_object_t *parent )
if( !p_preparser )
return NULL;
+ p_preparser->input = NULL;
+ p_preparser->input_done = false;
p_preparser->object = parent;
p_preparser->p_fetcher = playlist_fetcher_New( parent );
if( unlikely(p_preparser->p_fetcher == NULL) )
@@ -73,7 +80,7 @@ playlist_preparser_t *playlist_preparser_New( vlc_object_t *parent )
vlc_mutex_init( &p_preparser->lock );
vlc_cond_init( &p_preparser->wait );
- vlc_sem_init( &p_preparser->item_done, 0 );
+ vlc_cond_init( &p_preparser->thread_wait );
p_preparser->b_live = false;
p_preparser->i_waiting = 0;
p_preparser->pp_waiting = NULL;
@@ -125,14 +132,15 @@ void playlist_preparser_Delete( playlist_preparser_t *p_preparser )
REMOVE_ELEM( p_preparser->pp_waiting, p_preparser->i_waiting, 0 );
}
- vlc_sem_post( &p_preparser->item_done );
+ if( p_preparser->input != NULL )
+ input_Stop( p_preparser->input );
while( p_preparser->b_live )
vlc_cond_wait( &p_preparser->wait, &p_preparser->lock );
vlc_mutex_unlock( &p_preparser->lock );
/* Destroy the item preparser */
- vlc_sem_destroy( &p_preparser->item_done );
+ vlc_cond_destroy( &p_preparser->thread_wait );
vlc_cond_destroy( &p_preparser->wait );
vlc_mutex_destroy( &p_preparser->lock );
@@ -148,11 +156,14 @@ void playlist_preparser_Delete( playlist_preparser_t *p_preparser )
static int InputEvent( vlc_object_t *obj, const char *varname,
vlc_value_t old, vlc_value_t cur, void *data )
{
- vlc_sem_t *done = data;
+ playlist_preparser_t *preparser = data;
int event = cur.i_int;
if( event == INPUT_EVENT_DEAD )
- vlc_sem_post( done );
+ {
+ preparser->input_done = true;
+ vlc_cond_signal( &preparser->thread_wait );
+ }
(void) obj; (void) varname; (void) old;
return VLC_SUCCESS;
@@ -183,25 +194,26 @@ static void Preparse( playlist_preparser_t *preparser, input_item_t *p_item,
/* Do not preparse if it is already done (like by playing it) */
if( b_preparse && !input_item_IsPreparsed( p_item ) )
{
- input_thread_t *input = input_CreatePreparser( preparser->object,
- p_item );
- if( input == NULL )
+ preparser->input = input_CreatePreparser( preparser->object, p_item );
+ if( preparser->input == NULL )
{
input_item_SignalPreparseEnded( p_item, ITEM_PREPARSE_FAILED );
return;
}
+ preparser->input_done = false;
+
+ var_AddCallback( preparser->input, "intf-event", InputEvent,
+ preparser );
+ if( input_Start( preparser->input ) == VLC_SUCCESS )
+ {
+ while( !preparser->input_done )
+ vlc_cond_wait( &preparser->thread_wait, &preparser->lock );
+ }
- var_AddCallback( input, "intf-event", InputEvent,
- &preparser->item_done );
- if( input_Start( input ) == VLC_SUCCESS )
- vlc_sem_wait( &preparser->item_done );
- var_DelCallback( input, "intf-event", InputEvent,
- &preparser->item_done );
- /* Normally, the input is already stopped since we waited for it. But
- * if the playlist preparser is being deleted, then the input might
- * still be running. Force it to stop. */
- input_Stop( input );
- input_Close( input );
+ var_DelCallback( preparser->input, "intf-event", InputEvent,
+ preparser );
+ input_Close( preparser->input );
+ preparser->input = NULL;
var_SetAddress( preparser->object, "item-change", p_item );
input_item_SetPreparsed( p_item, true );
@@ -260,13 +272,13 @@ static void *Thread( void *data )
{
playlist_preparser_t *p_preparser = data;
+ vlc_mutex_lock( &p_preparser->lock );
for( ;; )
{
input_item_t *p_current;
input_item_meta_request_option_t i_options;
/* */
- vlc_mutex_lock( &p_preparser->lock );
if( p_preparser->i_waiting > 0 )
{
preparser_entry_t *p_entry = p_preparser->pp_waiting[0];
@@ -280,17 +292,16 @@ static void *Thread( void *data )
p_current = NULL;
p_preparser->b_live = false;
vlc_cond_signal( &p_preparser->wait );
- }
- vlc_mutex_unlock( &p_preparser->lock );
-
- if( !p_current )
break;
+ }
+ assert( p_current );
Preparse( p_preparser, p_current, i_options );
Art( p_preparser, p_current );
vlc_gc_decref(p_current);
}
+ vlc_mutex_unlock( &p_preparser->lock );
return NULL;
}
More information about the vlc-commits
mailing list