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
default:
msg_Err( p_playlist, "unknown playlist query" );
return VLC_EBADVAR;
break;
}
vlc_object_signal_unlocked( p_playlist );
......@@ -190,37 +189,29 @@ static int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args
int playlist_PreparseEnqueue( playlist_t *p_playlist,
input_item_t *p_item )
{
vlc_object_lock( p_playlist->p->p_preparse );
if( !vlc_object_alive( p_playlist->p->p_preparse ) )
{
vlc_object_unlock( p_playlist->p->p_preparse );
return VLC_EGENERIC;
}
playlist_preparse_t *p_preparse = &p_playlist->p->preparse;
vlc_gc_incref( p_item );
INSERT_ELEM( p_playlist->p->p_preparse->pp_waiting,
p_playlist->p->p_preparse->i_waiting,
p_playlist->p->p_preparse->i_waiting,
p_item );
vlc_object_signal_unlocked( p_playlist->p->p_preparse );
vlc_object_unlock( p_playlist->p->p_preparse );
vlc_mutex_lock( &p_preparse->lock );
INSERT_ELEM( p_preparse->pp_waiting, p_preparse->i_waiting,
p_preparse->i_waiting, p_item );
vlc_cond_signal( &p_preparse->wait );
vlc_mutex_unlock( &p_preparse->lock );
return VLC_SUCCESS;
}
/** Enqueue a playlist item or a node for peparsing.
* This function should be entered without playlist and preparser locks */
/** Enqueue a playlist item or a node for preparsing.
* This function shall be called without playlist and preparser locks */
int playlist_PreparseEnqueueItem( playlist_t *p_playlist,
playlist_item_t *p_item )
{
playlist_preparse_t *p_preparse = &p_playlist->p->preparse;
vlc_object_lock( p_playlist );
vlc_object_lock( p_playlist->p->p_preparse );
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;
}
vlc_mutex_lock( &p_preparse->lock );
PreparseEnqueueItemSub( p_playlist, p_item );
vlc_object_unlock( p_playlist->p->p_preparse );
vlc_mutex_unlock( &p_preparse->lock );
vlc_object_unlock( p_playlist );
return VLC_SUCCESS;
}
......@@ -247,18 +238,21 @@ int playlist_AskForArtEnqueue( playlist_t *p_playlist,
static void PreparseEnqueueItemSub( playlist_t *p_playlist,
playlist_item_t *p_item )
{
int i;
playlist_preparse_t *p_preparse = &p_playlist->p->preparse;
if( p_item->i_children == -1 )
{
/* Leaf item */
vlc_gc_incref( p_item->p_input );
INSERT_ELEM( p_playlist->p->p_preparse->pp_waiting,
p_playlist->p->p_preparse->i_waiting,
p_playlist->p->p_preparse->i_waiting,
INSERT_ELEM( p_preparse->pp_waiting,
p_preparse->i_waiting,
p_preparse->i_waiting,
p_item->p_input );
}
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] );
}
......
......@@ -25,6 +25,7 @@
# include "config.h"
#endif
#include <stddef.h>
#include <assert.h>
#include <vlc_common.h>
#include <vlc_sout.h>
......@@ -77,6 +78,7 @@ playlist_t * playlist_Create( vlc_object_t *p_parent )
VariablesInit( p_playlist );
/* Initialise data structures */
p_playlist->p->p_playlist = p_playlist;
p_playlist->i_last_playlist_id = 0;
p_playlist->p_input = NULL;
......@@ -174,12 +176,23 @@ playlist_t * playlist_Create( vlc_object_t *p_parent )
static void playlist_Destructor( vlc_object_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 )
{
vlc_object_release( p_playlist->p->p_fetcher );
......@@ -517,8 +530,6 @@ void playlist_LastLoop( playlist_t *p_playlist )
playlist_ServicesDiscoveryKillAll( 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_thread_join( p_playlist->p->p_fetcher );
......@@ -550,35 +561,36 @@ void playlist_LastLoop( playlist_t *p_playlist )
}
/**
* Preparse loop
* Preparse queue loop
*
* Main loop for preparser queue
* \param p_obj items to preparse
* \return nothing
* @param p_obj preparse structure
* @return never
*/
void playlist_PreparseLoop( playlist_preparse_t *p_obj )
void *playlist_PreparseLoop( void *data )
{
playlist_t *p_playlist = (playlist_t *)p_obj->p_parent;
input_item_t *p_current;
playlist_preparse_t *p_preparse = data;
playlist_t *p_playlist = ((playlist_private_t *)(((char *)p_preparse)
- offsetof(playlist_private_t, preparse)))->p_playlist;
int i_activity;
vlc_object_lock( p_obj );
while( vlc_object_alive( p_obj ) )
for( ;; )
{
if( p_obj->i_waiting == 0 )
{
vlc_object_wait( p_obj );
continue;
}
input_item_t *p_current;
p_current = p_obj->pp_waiting[0];
REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 );
vlc_object_unlock( p_obj );
vlc_mutex_lock( &p_preparse->lock );
mutex_cleanup_push( &p_preparse->lock );
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 )
{
int canc = vlc_savecancel ();
PL_LOCK;
if( p_current->i_type == ITEM_TYPE_FILE )
{
stats_TimerStart( p_playlist, "Preparse run",
......@@ -628,26 +640,17 @@ void playlist_PreparseLoop( playlist_preparse_t *p_obj )
free( psz_name );
free( psz_arturl );
PL_UNLOCK;
vlc_restorecancel( canc );
}
else
PL_UNLOCK;
vlc_object_lock( p_obj );
i_activity = var_GetInteger( p_playlist, "activity" );
if( i_activity < 0 ) i_activity = 0;
vlc_object_unlock( p_obj );
/* Sleep at least 1ms */
msleep( (i_activity+1) * 1000 );
vlc_object_lock( p_obj );
}
while( p_obj->i_waiting > 0 )
{
vlc_gc_decref( p_obj->pp_waiting[0] );
REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 );
}
vlc_object_unlock( p_obj );
assert( 0 );
return NULL;
}
/**
......
/*****************************************************************************
* 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$
*
* Authors: Samuel Hocevar <sam@zoy.org>
......@@ -39,10 +39,12 @@
typedef struct playlist_preparse_t
{
VLC_COMMON_MEMBERS
vlc_thread_t thread;
vlc_mutex_t lock;
int i_waiting;
vlc_cond_t wait;
input_item_t **pp_waiting;
int i_waiting;
bool up;
} playlist_preparse_t;
typedef struct playlist_fetcher_t
......@@ -58,7 +60,8 @@ typedef struct playlist_fetcher_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 */
sout_instance_t *p_sout; /**< Kept sout instance */
};
......@@ -80,7 +83,7 @@ playlist_t *playlist_Create ( vlc_object_t * );
/* Engine */
void playlist_MainLoop( playlist_t * );
void playlist_LastLoop( playlist_t * );
void playlist_PreparseLoop( playlist_preparse_t * );
void *playlist_PreparseLoop( void * );
void playlist_FetcherLoop( playlist_fetcher_t * );
void ResetCurrentlyPlaying( playlist_t *, bool, playlist_item_t * );
......
......@@ -36,9 +36,7 @@
* Local prototypes
*****************************************************************************/
static void* RunControlThread ( vlc_object_t * );
static void* RunPreparse ( vlc_object_t * );
static void* RunFetcher ( vlc_object_t * );
static void PreparseDestructor ( vlc_object_t * );
static void FetcherDestructor ( vlc_object_t * );
/*****************************************************************************
......@@ -59,29 +57,20 @@ void __playlist_ThreadCreate( vlc_object_t *p_parent )
if( !p_playlist ) return;
// Preparse
static const char ppname[] = "preparser";
p_playlist->p->p_preparse =
vlc_custom_create( p_playlist, sizeof( playlist_preparse_t ),
VLC_OBJECT_GENERIC, ppname );
if( !p_playlist->p->p_preparse )
{
msg_Err( p_playlist, "unable to create preparser" );
vlc_object_release( p_playlist );
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 ) )
playlist_preparse_t *p_preparse = &p_playlist->p->preparse;
vlc_mutex_init (&p_preparse->lock);
vlc_cond_init (&p_preparse->wait);
p_preparse->i_waiting = 0;
p_preparse->pp_waiting = NULL;
if( vlc_clone( &p_preparse->thread, playlist_PreparseLoop, p_preparse,
VLC_THREAD_PRIORITY_LOW ) )
{
msg_Err( p_playlist, "cannot spawn preparse thread" );
vlc_object_release( p_playlist->p->p_preparse );
p_preparse->up = false;
return;
}
p_preparse->up = true;
// Secondary Preparse
static const char fname[] = "fetcher";
......@@ -166,20 +155,6 @@ static void* RunControlThread ( vlc_object_t *p_this )
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 )
{
playlist_fetcher_t *p_obj = (playlist_fetcher_t *)p_this;
......@@ -189,13 +164,6 @@ static void* RunFetcher( vlc_object_t *p_this )
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 )
{
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