X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fplaylist%2Ffetcher.c;h=db8423efa6cc1c13d9b9009d77387510e23d9f01;hb=c75c32cba26287652dcfe33e06007a887030a338;hp=f8d8a422a761934057acb2eb61ac7a7d6bc1bb5e;hpb=52c18c4dec68158eedd655e0502820b7d7b6128f;p=vlc diff --git a/src/playlist/fetcher.c b/src/playlist/fetcher.c index f8d8a422a7..db8423efa6 100644 --- a/src/playlist/fetcher.c +++ b/src/playlist/fetcher.c @@ -46,7 +46,7 @@ struct playlist_fetcher_t vlc_thread_t thread; vlc_mutex_t lock; - vlc_cond_t wait; + bool b_live, b_zombie; int i_art_policy; int i_waiting; input_item_t **pp_waiting; @@ -72,20 +72,13 @@ playlist_fetcher_t *playlist_fetcher_New( playlist_t *p_playlist ) vlc_object_attach( p_fetcher, p_playlist ); p_fetcher->p_playlist = p_playlist; vlc_mutex_init( &p_fetcher->lock ); - vlc_cond_init( &p_fetcher->wait ); + p_fetcher->b_live = false; + p_fetcher->b_zombie = false; p_fetcher->i_waiting = 0; p_fetcher->pp_waiting = NULL; p_fetcher->i_art_policy = var_GetInteger( p_playlist, "album-art" ); ARRAY_INIT( p_fetcher->albums ); - if( vlc_clone( &p_fetcher->thread, Thread, p_fetcher, - VLC_THREAD_PRIORITY_LOW ) ) - { - msg_Err( p_fetcher, "cannot spawn secondary preparse thread" ); - vlc_object_release( p_fetcher ); - return NULL; - } - return p_fetcher; } @@ -94,27 +87,45 @@ void playlist_fetcher_Push( playlist_fetcher_t *p_fetcher, input_item_t *p_item vlc_gc_incref( p_item ); vlc_mutex_lock( &p_fetcher->lock ); + if( p_fetcher->b_zombie ) /* FIXME: detach the thread */ + { + vlc_join( p_fetcher->thread, NULL ); + p_fetcher->b_zombie = false; + } + INSERT_ELEM( p_fetcher->pp_waiting, p_fetcher->i_waiting, p_fetcher->i_waiting, p_item ); - vlc_cond_signal( &p_fetcher->wait ); + if( !p_fetcher->b_live ) + { + if( vlc_clone( &p_fetcher->thread, Thread, p_fetcher, + VLC_THREAD_PRIORITY_LOW ) ) + msg_Err( p_fetcher, "cannot spawn secondary preparse thread" ); + else + p_fetcher->b_live = true; + } vlc_mutex_unlock( &p_fetcher->lock ); } void playlist_fetcher_Delete( playlist_fetcher_t *p_fetcher ) { - /* */ - vlc_object_kill( p_fetcher ); - + bool b_join; /* Destroy the item meta-infos fetcher */ - vlc_cancel( p_fetcher->thread ); - vlc_join( p_fetcher->thread, NULL ); + vlc_mutex_lock( &p_fetcher->lock ); + if( p_fetcher->b_live ) + { + vlc_object_kill( p_fetcher ); + vlc_cancel( p_fetcher->thread ); + } + b_join = p_fetcher->b_live || p_fetcher->b_zombie; + vlc_mutex_unlock( &p_fetcher->lock ); + if( b_join ) + vlc_join( p_fetcher->thread, NULL ); while( p_fetcher->i_waiting > 0 ) { /* Any left-over unparsed item? */ vlc_gc_decref( p_fetcher->pp_waiting[0] ); REMOVE_ELEM( p_fetcher->pp_waiting, p_fetcher->i_waiting, 0 ); } - vlc_cond_destroy( &p_fetcher->wait ); vlc_mutex_destroy( &p_fetcher->lock ); vlc_object_release( p_fetcher ); } @@ -319,11 +330,11 @@ static int InputEvent( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { VLC_UNUSED(p_this); VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); - playlist_fetcher_t *p_fetcher = p_data; + vlc_cond_t *p_cond = p_data; if( newval.i_int == INPUT_EVENT_ITEM_META || newval.i_int == INPUT_EVENT_DEAD ) - vlc_cond_signal( &p_fetcher->wait ); + vlc_cond_signal( p_cond ); return VLC_SUCCESS; } @@ -346,22 +357,26 @@ static void WaitPreparsed( playlist_fetcher_t *p_fetcher, input_item_t *p_item ) if( input_GetItem( p_input ) != p_item ) goto exit; - var_AddCallback( p_input, "intf-event", InputEvent, p_fetcher ); + vlc_cond_t cond; + vlc_cond_init( &cond ); + var_AddCallback( p_input, "intf-event", InputEvent, &cond ); const mtime_t i_deadline = mdate() + 500*1000; + bool b_timeout = false; - while( !p_input->b_eof && !p_input->b_error && !input_item_IsPreparsed( p_item ) ) + while( !p_input->b_eof && !p_input->b_error + && !input_item_IsPreparsed( p_item ) && !b_timeout ) { - /* A bit weird, but input_item_IsPreparsed does held the protected value */ + /* A bit weird, but input_item_IsPreparsed holds the protected value */ + /* FIXME: locking looks wrong here */ vlc_mutex_lock( &p_fetcher->lock ); - vlc_cond_timedwait( &p_fetcher->wait, &p_fetcher->lock, i_deadline ); + if( vlc_cond_timedwait( &cond, &p_fetcher->lock, i_deadline ) ) + b_timeout = true; vlc_mutex_unlock( &p_fetcher->lock ); - - if( i_deadline <= mdate() ) - break; } var_DelCallback( p_input, "intf-event", InputEvent, p_fetcher ); + vlc_cond_destroy( &cond ); exit: vlc_object_release( p_input ); @@ -374,24 +389,23 @@ static void *Thread( void *p_data ) for( ;; ) { - input_item_t *p_item; + input_item_t *p_item = NULL; - /* Be sure to be cancellable before our queue is empty */ - vlc_testcancel(); - - /* */ vlc_mutex_lock( &p_fetcher->lock ); - mutex_cleanup_push( &p_fetcher->lock ); - - while( p_fetcher->i_waiting == 0 ) - vlc_cond_wait( &p_fetcher->wait, &p_fetcher->lock ); - - p_item = p_fetcher->pp_waiting[0]; - REMOVE_ELEM( p_fetcher->pp_waiting, p_fetcher->i_waiting, 0 ); - vlc_cleanup_run( ); + if( p_fetcher->i_waiting != 0 ) + { + p_item = p_fetcher->pp_waiting[0]; + REMOVE_ELEM( p_fetcher->pp_waiting, p_fetcher->i_waiting, 0 ); + } + else + { + p_fetcher->b_live = false; + p_fetcher->b_zombie = true; + } + vlc_mutex_unlock( &p_fetcher->lock ); if( !p_item ) - continue; + break; /* */ int canc = vlc_savecancel(); @@ -435,10 +449,8 @@ static void *Thread( void *p_data ) int i_activity = var_GetInteger( p_playlist, "activity" ); if( i_activity < 0 ) i_activity = 0; - /* Sleep at least 1ms */ + /* Sleep at least 1ms and handle potential thread cancellation */ msleep( (i_activity+1) * 1000 ); } return NULL; } - -