Commit 8df80e5e authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Preparser: use normal thread API

parent d62129ac
...@@ -176,7 +176,6 @@ static int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args ...@@ -176,7 +176,6 @@ static int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args
default: default:
msg_Err( p_playlist, "unknown playlist query" ); msg_Err( p_playlist, "unknown playlist query" );
return VLC_EBADVAR; return VLC_EBADVAR;
break;
} }
vlc_object_signal_unlocked( p_playlist ); vlc_object_signal_unlocked( p_playlist );
...@@ -190,37 +189,29 @@ static int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args ...@@ -190,37 +189,29 @@ static int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args
int playlist_PreparseEnqueue( playlist_t *p_playlist, int playlist_PreparseEnqueue( playlist_t *p_playlist,
input_item_t *p_item ) input_item_t *p_item )
{ {
vlc_object_lock( p_playlist->p->p_preparse ); playlist_preparse_t *p_preparse = &p_playlist->p->preparse;
if( !vlc_object_alive( p_playlist->p->p_preparse ) )
{
vlc_object_unlock( p_playlist->p->p_preparse );
return VLC_EGENERIC;
}
vlc_gc_incref( p_item ); vlc_gc_incref( p_item );
INSERT_ELEM( p_playlist->p->p_preparse->pp_waiting,
p_playlist->p->p_preparse->i_waiting, vlc_mutex_lock( &p_preparse->lock );
p_playlist->p->p_preparse->i_waiting, INSERT_ELEM( p_preparse->pp_waiting, p_preparse->i_waiting,
p_item ); p_preparse->i_waiting, p_item );
vlc_object_signal_unlocked( p_playlist->p->p_preparse ); vlc_cond_signal( &p_preparse->wait );
vlc_object_unlock( p_playlist->p->p_preparse ); vlc_mutex_unlock( &p_preparse->lock );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/** Enqueue a playlist item or a node for peparsing. /** Enqueue a playlist item or a node for preparsing.
* This function should be entered without playlist and preparser locks */ * This function shall be called without playlist and preparser locks */
int playlist_PreparseEnqueueItem( playlist_t *p_playlist, int playlist_PreparseEnqueueItem( playlist_t *p_playlist,
playlist_item_t *p_item ) playlist_item_t *p_item )
{ {
playlist_preparse_t *p_preparse = &p_playlist->p->preparse;
vlc_object_lock( p_playlist ); vlc_object_lock( p_playlist );
vlc_object_lock( p_playlist->p->p_preparse ); vlc_mutex_lock( &p_preparse->lock );
if( !vlc_object_alive( p_playlist->p->p_preparse ) )
{
vlc_object_unlock( p_playlist->p->p_preparse );
vlc_object_unlock( p_playlist );
return VLC_EGENERIC;
}
PreparseEnqueueItemSub( p_playlist, p_item ); PreparseEnqueueItemSub( p_playlist, p_item );
vlc_object_unlock( p_playlist->p->p_preparse ); vlc_mutex_unlock( &p_preparse->lock );
vlc_object_unlock( p_playlist ); vlc_object_unlock( p_playlist );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -247,18 +238,21 @@ int playlist_AskForArtEnqueue( playlist_t *p_playlist, ...@@ -247,18 +238,21 @@ int playlist_AskForArtEnqueue( playlist_t *p_playlist,
static void PreparseEnqueueItemSub( playlist_t *p_playlist, static void PreparseEnqueueItemSub( playlist_t *p_playlist,
playlist_item_t *p_item ) playlist_item_t *p_item )
{ {
int i; playlist_preparse_t *p_preparse = &p_playlist->p->preparse;
if( p_item->i_children == -1 ) if( p_item->i_children == -1 )
{ {
/* Leaf item */
vlc_gc_incref( p_item->p_input ); vlc_gc_incref( p_item->p_input );
INSERT_ELEM( p_playlist->p->p_preparse->pp_waiting, INSERT_ELEM( p_preparse->pp_waiting,
p_playlist->p->p_preparse->i_waiting, p_preparse->i_waiting,
p_playlist->p->p_preparse->i_waiting, p_preparse->i_waiting,
p_item->p_input ); p_item->p_input );
} }
else else
{ {
for( i = 0; i < p_item->i_children; i++) /* Non-leaf item: recurse */
for( int i = 0; i < p_item->i_children; i++)
{ {
PreparseEnqueueItemSub( p_playlist, p_item->pp_children[i] ); PreparseEnqueueItemSub( p_playlist, p_item->pp_children[i] );
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
# include "config.h" # include "config.h"
#endif #endif
#include <stddef.h>
#include <assert.h> #include <assert.h>
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_sout.h> #include <vlc_sout.h>
...@@ -77,6 +78,7 @@ playlist_t * playlist_Create( vlc_object_t *p_parent ) ...@@ -77,6 +78,7 @@ playlist_t * playlist_Create( vlc_object_t *p_parent )
VariablesInit( p_playlist ); VariablesInit( p_playlist );
/* Initialise data structures */ /* Initialise data structures */
p_playlist->p->p_playlist = p_playlist;
p_playlist->i_last_playlist_id = 0; p_playlist->i_last_playlist_id = 0;
p_playlist->p_input = NULL; p_playlist->p_input = NULL;
...@@ -174,12 +176,23 @@ playlist_t * playlist_Create( vlc_object_t *p_parent ) ...@@ -174,12 +176,23 @@ playlist_t * playlist_Create( vlc_object_t *p_parent )
static void playlist_Destructor( vlc_object_t * p_this ) static void playlist_Destructor( vlc_object_t * p_this )
{ {
playlist_t * p_playlist = (playlist_t *)p_this; playlist_t * p_playlist = (playlist_t *)p_this;
playlist_preparse_t *p_preparse = &p_playlist->p->preparse;
if( p_playlist->p->p_preparse ) /* Destroy the item preparser */
if (p_preparse->up)
{ {
vlc_object_release( p_playlist->p->p_preparse ); vlc_cancel (p_preparse->thread);
vlc_join (p_preparse->thread, NULL);
} }
while (p_preparse->i_waiting > 0)
{ /* Any left-over unparsed item? */
vlc_gc_decref (p_preparse->pp_waiting[0]);
REMOVE_ELEM (p_preparse->pp_waiting, p_preparse->i_waiting, 0);
}
vlc_cond_destroy (&p_preparse->wait);
vlc_mutex_destroy (&p_preparse->lock);
/* Destroy the item meta-infos fetcher */
if( p_playlist->p->p_fetcher ) if( p_playlist->p->p_fetcher )
{ {
vlc_object_release( p_playlist->p->p_fetcher ); vlc_object_release( p_playlist->p->p_fetcher );
...@@ -517,8 +530,6 @@ void playlist_LastLoop( playlist_t *p_playlist ) ...@@ -517,8 +530,6 @@ void playlist_LastLoop( playlist_t *p_playlist )
playlist_ServicesDiscoveryKillAll( p_playlist ); playlist_ServicesDiscoveryKillAll( p_playlist );
playlist_MLDump( p_playlist ); playlist_MLDump( p_playlist );
vlc_object_kill( p_playlist->p->p_preparse );
vlc_thread_join( p_playlist->p->p_preparse );
vlc_object_kill( p_playlist->p->p_fetcher ); vlc_object_kill( p_playlist->p->p_fetcher );
vlc_thread_join( p_playlist->p->p_fetcher ); vlc_thread_join( p_playlist->p->p_fetcher );
...@@ -550,35 +561,36 @@ void playlist_LastLoop( playlist_t *p_playlist ) ...@@ -550,35 +561,36 @@ void playlist_LastLoop( playlist_t *p_playlist )
} }
/** /**
* Preparse loop * Preparse queue loop
* *
* Main loop for preparser queue * @param p_obj preparse structure
* \param p_obj items to preparse * @return never
* \return nothing
*/ */
void playlist_PreparseLoop( playlist_preparse_t *p_obj ) void *playlist_PreparseLoop( void *data )
{ {
playlist_t *p_playlist = (playlist_t *)p_obj->p_parent; playlist_preparse_t *p_preparse = data;
input_item_t *p_current; playlist_t *p_playlist = ((playlist_private_t *)(((char *)p_preparse)
- offsetof(playlist_private_t, preparse)))->p_playlist;
int i_activity; int i_activity;
vlc_object_lock( p_obj ); for( ;; )
while( vlc_object_alive( p_obj ) )
{ {
if( p_obj->i_waiting == 0 ) input_item_t *p_current;
{
vlc_object_wait( p_obj );
continue;
}
p_current = p_obj->pp_waiting[0]; vlc_mutex_lock( &p_preparse->lock );
REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 ); mutex_cleanup_push( &p_preparse->lock );
vlc_object_unlock( p_obj );
while( p_preparse->i_waiting == 0 )
vlc_cond_wait( &p_preparse->wait, &p_preparse->lock );
p_current = p_preparse->pp_waiting[0];
REMOVE_ELEM( p_preparse->pp_waiting, p_preparse->i_waiting, 0 );
vlc_cleanup_run( );
PL_LOCK;
if( p_current ) if( p_current )
{ {
int canc = vlc_savecancel ();
PL_LOCK;
if( p_current->i_type == ITEM_TYPE_FILE ) if( p_current->i_type == ITEM_TYPE_FILE )
{ {
stats_TimerStart( p_playlist, "Preparse run", stats_TimerStart( p_playlist, "Preparse run",
...@@ -627,27 +639,18 @@ void playlist_PreparseLoop( playlist_preparse_t *p_obj ) ...@@ -627,27 +639,18 @@ void playlist_PreparseLoop( playlist_preparse_t *p_obj )
} }
free( psz_name ); free( psz_name );
free( psz_arturl ); free( psz_arturl );
PL_UNLOCK; PL_UNLOCK;
vlc_restorecancel( canc );
} }
else
PL_UNLOCK;
vlc_object_lock( p_obj );
i_activity = var_GetInteger( p_playlist, "activity" ); i_activity = var_GetInteger( p_playlist, "activity" );
if( i_activity < 0 ) i_activity = 0; if( i_activity < 0 ) i_activity = 0;
vlc_object_unlock( p_obj );
/* Sleep at least 1ms */ /* Sleep at least 1ms */
msleep( (i_activity+1) * 1000 ); msleep( (i_activity+1) * 1000 );
vlc_object_lock( p_obj );
} }
while( p_obj->i_waiting > 0 ) assert( 0 );
{ return NULL;
vlc_gc_decref( p_obj->pp_waiting[0] );
REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 );
}
vlc_object_unlock( p_obj );
} }
/** /**
......
/***************************************************************************** /*****************************************************************************
* playlist_internal.h : Functions for use by the playlist * playlist_internal.h : Playlist internals
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2004 the VideoLAN team * Copyright (C) 1999-2008 the VideoLAN team
* $Id$ * $Id$
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
...@@ -39,10 +39,12 @@ ...@@ -39,10 +39,12 @@
typedef struct playlist_preparse_t typedef struct playlist_preparse_t
{ {
VLC_COMMON_MEMBERS vlc_thread_t thread;
vlc_mutex_t lock; vlc_mutex_t lock;
int i_waiting; vlc_cond_t wait;
input_item_t **pp_waiting; input_item_t **pp_waiting;
int i_waiting;
bool up;
} playlist_preparse_t; } playlist_preparse_t;
typedef struct playlist_fetcher_t typedef struct playlist_fetcher_t
...@@ -58,7 +60,8 @@ typedef struct playlist_fetcher_t ...@@ -58,7 +60,8 @@ typedef struct playlist_fetcher_t
struct playlist_private_t struct playlist_private_t
{ {
playlist_preparse_t *p_preparse; /**< Preparser object */ playlist_t *p_playlist; /**< Public data */
playlist_preparse_t preparse; /**< Preparser data */
playlist_fetcher_t *p_fetcher; /**< Meta and art fetcher object */ playlist_fetcher_t *p_fetcher; /**< Meta and art fetcher object */
sout_instance_t *p_sout; /**< Kept sout instance */ sout_instance_t *p_sout; /**< Kept sout instance */
}; };
...@@ -80,7 +83,7 @@ playlist_t *playlist_Create ( vlc_object_t * ); ...@@ -80,7 +83,7 @@ playlist_t *playlist_Create ( vlc_object_t * );
/* Engine */ /* Engine */
void playlist_MainLoop( playlist_t * ); void playlist_MainLoop( playlist_t * );
void playlist_LastLoop( playlist_t * ); void playlist_LastLoop( playlist_t * );
void playlist_PreparseLoop( playlist_preparse_t * ); void *playlist_PreparseLoop( void * );
void playlist_FetcherLoop( playlist_fetcher_t * ); void playlist_FetcherLoop( playlist_fetcher_t * );
void ResetCurrentlyPlaying( playlist_t *, bool, playlist_item_t * ); void ResetCurrentlyPlaying( playlist_t *, bool, playlist_item_t * );
......
...@@ -36,9 +36,7 @@ ...@@ -36,9 +36,7 @@
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
static void* RunControlThread ( vlc_object_t * ); static void* RunControlThread ( vlc_object_t * );
static void* RunPreparse ( vlc_object_t * );
static void* RunFetcher ( vlc_object_t * ); static void* RunFetcher ( vlc_object_t * );
static void PreparseDestructor ( vlc_object_t * );
static void FetcherDestructor ( vlc_object_t * ); static void FetcherDestructor ( vlc_object_t * );
/***************************************************************************** /*****************************************************************************
...@@ -59,29 +57,20 @@ void __playlist_ThreadCreate( vlc_object_t *p_parent ) ...@@ -59,29 +57,20 @@ void __playlist_ThreadCreate( vlc_object_t *p_parent )
if( !p_playlist ) return; if( !p_playlist ) return;
// Preparse // Preparse
static const char ppname[] = "preparser"; playlist_preparse_t *p_preparse = &p_playlist->p->preparse;
p_playlist->p->p_preparse = vlc_mutex_init (&p_preparse->lock);
vlc_custom_create( p_playlist, sizeof( playlist_preparse_t ), vlc_cond_init (&p_preparse->wait);
VLC_OBJECT_GENERIC, ppname ); p_preparse->i_waiting = 0;
if( !p_playlist->p->p_preparse ) p_preparse->pp_waiting = NULL;
{
msg_Err( p_playlist, "unable to create preparser" ); if( vlc_clone( &p_preparse->thread, playlist_PreparseLoop, p_preparse,
vlc_object_release( p_playlist ); VLC_THREAD_PRIORITY_LOW ) )
return;
}
p_playlist->p->p_preparse->i_waiting = 0;
p_playlist->p->p_preparse->pp_waiting = NULL;
vlc_object_set_destructor( p_playlist->p->p_preparse, PreparseDestructor );
vlc_object_attach( p_playlist->p->p_preparse, p_playlist );
if( vlc_thread_create( p_playlist->p->p_preparse, "preparser",
RunPreparse, VLC_THREAD_PRIORITY_LOW, false ) )
{ {
msg_Err( p_playlist, "cannot spawn preparse thread" ); msg_Err( p_playlist, "cannot spawn preparse thread" );
vlc_object_release( p_playlist->p->p_preparse ); p_preparse->up = false;
return; return;
} }
p_preparse->up = true;
// Secondary Preparse // Secondary Preparse
static const char fname[] = "fetcher"; static const char fname[] = "fetcher";
...@@ -166,20 +155,6 @@ static void* RunControlThread ( vlc_object_t *p_this ) ...@@ -166,20 +155,6 @@ static void* RunControlThread ( vlc_object_t *p_this )
return NULL; return NULL;
} }
/*****************************************************************************
* Preparse-specific functions
*****************************************************************************/
static void* RunPreparse ( vlc_object_t *p_this )
{
playlist_preparse_t *p_obj = (playlist_preparse_t*)p_this;
int canc;
canc = vlc_savecancel ();
playlist_PreparseLoop( p_obj );
vlc_restorecancel (canc);
return NULL;
}
static void* RunFetcher( vlc_object_t *p_this ) static void* RunFetcher( vlc_object_t *p_this )
{ {
playlist_fetcher_t *p_obj = (playlist_fetcher_t *)p_this; playlist_fetcher_t *p_obj = (playlist_fetcher_t *)p_this;
...@@ -189,13 +164,6 @@ static void* RunFetcher( vlc_object_t *p_this ) ...@@ -189,13 +164,6 @@ static void* RunFetcher( vlc_object_t *p_this )
return NULL; return NULL;
} }
static void PreparseDestructor( vlc_object_t * p_this )
{
playlist_preparse_t * p_preparse = (playlist_preparse_t *)p_this;
free( p_preparse->pp_waiting );
msg_Dbg( p_this, "Destroyed" );
}
static void FetcherDestructor( vlc_object_t * p_this ) static void FetcherDestructor( vlc_object_t * p_this )
{ {
playlist_fetcher_t * p_fetcher = (playlist_fetcher_t *)p_this; playlist_fetcher_t * p_fetcher = (playlist_fetcher_t *)p_this;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment