X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fobjects.c;h=440a739a43e3033240a16055b37150f5266ef174;hb=9fc1c6d158fdc6bd7691f79396a7bd5e22805705;hp=508137c3cc86e99fe21bc44b249effb764e65068;hpb=68aaf2c9253dbe1c11b8900c3b5205438c66a9de;p=vlc diff --git a/src/misc/objects.c b/src/misc/objects.c index 508137c3cc..440a739a43 100644 --- a/src/misc/objects.c +++ b/src/misc/objects.c @@ -1,7 +1,7 @@ /***************************************************************************** * objects.c: vlc_object_t handling ***************************************************************************** - * Copyright (C) 2004-2007 the VideoLAN team + * Copyright (C) 2004-2008 the VideoLAN team * $Id$ * * Authors: Samuel Hocevar @@ -56,9 +56,6 @@ #include "vlc_httpd.h" #include "vlc_vlm.h" #include "input/vlm_internal.h" -#include "vlc_vod.h" -#include "vlc_tls.h" -#include "vlc_xml.h" #include "vlc_osd.h" #include "vlc_meta.h" @@ -73,14 +70,14 @@ #include /***************************************************************************** - * Local prototypes + * Constants *****************************************************************************/ -typedef enum vlc_lock_state_t -{ - vlc_Locked, - vlc_Unlocked -} vlc_lock_state_t; +const vlc_destructor_t kVLCDestructor = NULL; + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ static int DumpCommand( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); @@ -99,7 +96,7 @@ static int CountChildren ( vlc_object_t *, int ); static void ListChildren ( vlc_list_t *, vlc_object_t *, int ); static void vlc_object_destroy( vlc_object_t *p_this ); -static void vlc_object_release_locked( vlc_object_t *p_this, vlc_lock_state_t locked ); +static void vlc_object_yield_locked( vlc_object_t *p_this ); /***************************************************************************** * Local structure lock @@ -199,6 +196,8 @@ vlc_object_t *vlc_custom_create( vlc_object_t *p_this, size_t i_size, } p_priv->i_refcount = 1; + p_priv->pf_destructor = kVLCDestructor; + p_priv->b_thread = VLC_FALSE; p_new->p_parent = NULL; p_new->pp_children = NULL; p_new->i_children = 0; @@ -266,10 +265,6 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof(playlist_t); psz_type = "playlist"; break; - case VLC_OBJECT_SD: - i_size = sizeof(services_discovery_t); - psz_type = "services discovery"; - break; case VLC_OBJECT_INPUT: i_size = sizeof(input_thread_t); psz_type = "input"; @@ -302,10 +297,6 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof(vout_thread_t); psz_type = "video output"; break; - case VLC_OBJECT_SPU: - i_size = sizeof(spu_t); - psz_type = "subpicture"; - break; case VLC_OBJECT_AOUT: i_size = sizeof(aout_instance_t); psz_type = "audio output"; @@ -318,14 +309,6 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof( vlm_t ); psz_type = "vlm dameon"; break; - case VLC_OBJECT_VOD: - i_size = sizeof( vod_t ); - psz_type = "vod server"; - break; - case VLC_OBJECT_XML: - i_size = sizeof( xml_t ); - psz_type = "xml"; - break; case VLC_OBJECT_OPENGL: i_size = sizeof( vout_thread_t ); psz_type = "opengl"; @@ -334,14 +317,14 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof( announce_handler_t ); psz_type = "announce"; break; - case VLC_OBJECT_META_ENGINE: - i_size = sizeof( meta_engine_t ); - psz_type = "meta engine"; - break; case VLC_OBJECT_OSDMENU: i_size = sizeof( osd_menu_t ); psz_type = "osd menu"; break; + case VLC_OBJECT_INTERACTION: + i_size = sizeof( interaction_t ); + psz_type = "interaction"; + break; default: i_size = i_type > (int)sizeof(vlc_object_t) ? i_type : (int)sizeof(vlc_object_t); @@ -354,6 +337,24 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) } +/** + **************************************************************************** + * Set the destructor of a vlc object + * + * This function sets the destructor of the vlc object. It will be called + * when the object is destroyed when the its refcount reaches 0. + * (It is called by the internal function vlc_object_destroy()) + *****************************************************************************/ +void __vlc_object_set_destructor( vlc_object_t *p_this, + vlc_destructor_t pf_destructor ) +{ + vlc_object_internals_t *p_priv = vlc_internals(p_this ); + + vlc_mutex_lock( &structure_lock ); + p_priv->pf_destructor = pf_destructor; + vlc_mutex_unlock( &structure_lock ); +} + /** **************************************************************************** * Destroy a vlc object (Internal) @@ -366,44 +367,44 @@ static void vlc_object_destroy( vlc_object_t *p_this ) { vlc_object_internals_t *p_priv = vlc_internals( p_this ); - /* FIXME: ugly hack - we cannot use the message queue after - * msg_Destroy(). */ - vlc_object_t *logger = p_this; - if( (vlc_object_t *)p_this->p_libvlc == p_this ) - logger = NULL; + /* Automatically detach the object from its parents */ + if( p_this->p_parent ) vlc_object_detach( p_this ); + + + /* Send a kill to the object's thread if applicable */ + vlc_object_kill( p_this ); + + /* If we are running on a thread, wait until it ends */ + if( p_priv->b_thread ) + vlc_thread_join( p_this ); + + /* Call the custom "subclass" destructor */ + if( p_priv->pf_destructor ) + p_priv->pf_destructor( p_this ); /* Sanity checks */ if( p_this->i_children ) { int i; - fprintf( stderr, "ERROR: cannot delete object (%i, %s) with %d children\n", - p_this->i_object_id, p_this->psz_object_name, p_this->i_children ); + fprintf( stderr, + "ERROR: cannot delete object (%i, %s) with %d children\n", + p_this->i_object_id, p_this->psz_object_name, + p_this->i_children ); for( i = 0; i < p_this->i_children; i++ ) { - fprintf( stderr, "ERROR: Remaining children object (id:%i, type:%s, name:%s)\n", - p_this->pp_children[i]->i_object_id, - p_this->pp_children[i]->psz_object_type, - p_this->pp_children[i]->psz_object_name ); + fprintf( stderr, + "ERROR: Remaining children object " + "(id:%i, type:%s, name:%s)\n", + p_this->pp_children[i]->i_object_id, + p_this->pp_children[i]->psz_object_type, + p_this->pp_children[i]->psz_object_name ); } fflush(stderr); abort(); } - if( p_this->p_parent ) - { - fprintf( stderr, "ERROR: cannot delete object (id:%i, type:%s, name:%s) with a parent (id:%i, type:%s, name:%s)\n", - p_this->i_object_id, - p_this->psz_object_type, - p_this->psz_object_name, - p_this->p_parent->i_object_id, - p_this->p_parent->psz_object_type, - p_this->p_parent->psz_object_name ); - fflush(stderr); - abort(); - } - /* Destroy the associated variables, starting from the end so that * no memmove calls have to be done. */ while( p_priv->i_vars ) @@ -414,7 +415,7 @@ static void vlc_object_destroy( vlc_object_t *p_this ) free( p_priv->p_vars ); vlc_mutex_destroy( &p_priv->var_lock ); - if( p_this->psz_header ) free( p_this->psz_header ); + free( p_this->psz_header ); if( p_this->i_object_type == VLC_OBJECT_GLOBAL ) { @@ -428,10 +429,10 @@ static void vlc_object_destroy( vlc_object_t *p_this ) { /* We are leaking this object */ fprintf( stderr, - "ERROR: We are leaking object (id:%i, type:%s, name:%s)\n", - p_global->pp_objects[i]->i_object_id, - p_global->pp_objects[i]->psz_object_type, - p_global->pp_objects[i]->psz_object_name ); + "ERROR: leaking object (id:%i, type:%s, name:%s)\n", + p_global->pp_objects[i]->i_object_id, + p_global->pp_objects[i]->psz_object_type, + p_global->pp_objects[i]->psz_object_name ); fflush(stderr); } /* Strongly abort, cause we want these to be fixed */ @@ -739,19 +740,20 @@ void * vlc_object_get( int i_id ) else { /* This happens when there are only two remaining objects */ - if( pp_objects[i_middle+1]->i_object_id == i_id ) + if( pp_objects[i_middle+1]->i_object_id == i_id + && pp_objects[i_middle+1]->p_internals->i_refcount > 0 ) { + vlc_object_yield_locked( pp_objects[i_middle+1] ); vlc_mutex_unlock( &structure_lock ); - pp_objects[i_middle+1]->p_internals->i_refcount++; return pp_objects[i_middle+1]; } break; } } - else + else if( pp_objects[i_middle]->p_internals->i_refcount > 0 ) { + vlc_object_yield_locked( pp_objects[i_middle] ); vlc_mutex_unlock( &structure_lock ); - pp_objects[i_middle]->p_internals->i_refcount++; return pp_objects[i_middle]; } @@ -781,9 +783,10 @@ void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode ) vlc_mutex_lock( &structure_lock ); /* If we are of the requested type ourselves, don't look further */ - if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type ) + if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type + && p_this->p_internals->i_refcount > 0 ) { - p_this->p_internals->i_refcount++; + vlc_object_yield_locked( p_this ); vlc_mutex_unlock( &structure_lock ); return p_this; } @@ -831,12 +834,16 @@ void * __vlc_object_find_name( vlc_object_t *p_this, const char *psz_name, vlc_mutex_lock( &structure_lock ); + /* Avoid obvious freed object uses */ + assert( p_this->p_internals->i_refcount > 0 ); + /* If have the requested name ourselves, don't look further */ if( !(i_mode & FIND_STRICT) && p_this->psz_object_name - && !strcmp( p_this->psz_object_name, psz_name ) ) + && !strcmp( p_this->psz_object_name, psz_name ) + && p_this->p_internals->i_refcount > 0 ) { - p_this->p_internals->i_refcount++; + vlc_object_yield_locked( p_this ); vlc_mutex_unlock( &structure_lock ); return p_this; } @@ -875,28 +882,37 @@ void * __vlc_object_find_name( vlc_object_t *p_this, const char *psz_name, **************************************************************************** * increment an object refcount *****************************************************************************/ + +/* When the structure_lock is locked */ +static void vlc_object_yield_locked( vlc_object_t *p_this ) +{ + vlc_assert_locked (&structure_lock); + + /* Avoid obvious freed object uses */ + assert( p_this->p_internals->i_refcount > 0 ); + + /* Increment the counter */ + p_this->p_internals->i_refcount++; +} + +/* Public function */ void __vlc_object_yield( vlc_object_t *p_this ) { vlc_mutex_lock( &structure_lock ); - p_this->p_internals->i_refcount++; + vlc_object_yield_locked( p_this ); vlc_mutex_unlock( &structure_lock ); } + /***************************************************************************** * decrement an object refcount * And destroy the object if its refcount reach zero. *****************************************************************************/ void __vlc_object_release( vlc_object_t *p_this ) -{ - vlc_object_release_locked( p_this, vlc_Unlocked ); -} - -/* Version without the lock */ -static void vlc_object_release_locked( vlc_object_t *p_this, vlc_lock_state_t locked ) { vlc_bool_t b_should_destroy; - if(locked == vlc_Unlocked) vlc_mutex_lock( &structure_lock ); + vlc_mutex_lock( &structure_lock ); assert( p_this->p_internals->i_refcount > 0 ); p_this->p_internals->i_refcount--; @@ -917,7 +933,7 @@ static void vlc_object_release_locked( vlc_object_t *p_this, vlc_lock_state_t lo p_libvlc_global->i_objects, i_index ); } - if(locked == vlc_Unlocked) vlc_mutex_unlock( &structure_lock ); + vlc_mutex_unlock( &structure_lock ); if( b_should_destroy ) vlc_object_destroy( p_this ); @@ -936,6 +952,9 @@ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent ) vlc_mutex_lock( &structure_lock ); + /* Avoid obvious freed object uses */ + assert( p_this->p_internals->i_refcount > 0 ); + /* Attach the parent to its child */ p_this->p_parent = p_parent; @@ -963,6 +982,7 @@ void __vlc_object_detach( vlc_object_t *p_this ) if( !p_this ) return; vlc_mutex_lock( &structure_lock ); + if( !p_this->p_parent ) { msg_Err( p_this, "object is not attached" ); @@ -1241,12 +1261,10 @@ void vlc_list_release( vlc_list_t *p_list ) { int i_index; - vlc_mutex_lock( &structure_lock ); for( i_index = 0; i_index < p_list->i_count; i_index++ ) { - vlc_object_release_locked( p_list->p_values[i_index].p_object, vlc_Locked ); + vlc_object_release( p_list->p_values[i_index].p_object ); } - vlc_mutex_unlock( &structure_lock ); free( p_list->p_values ); free( p_list ); @@ -1305,9 +1323,10 @@ static vlc_object_t * FindObject( vlc_object_t *p_this, int i_type, int i_mode ) p_tmp = p_this->p_parent; if( p_tmp ) { - if( p_tmp->i_object_type == i_type ) + if( p_tmp->i_object_type == i_type + && p_tmp->p_internals->i_refcount > 0 ) { - p_tmp->p_internals->i_refcount++; + vlc_object_yield_locked( p_tmp ); return p_tmp; } else @@ -1321,9 +1340,10 @@ static vlc_object_t * FindObject( vlc_object_t *p_this, int i_type, int i_mode ) for( i = p_this->i_children; i--; ) { p_tmp = p_this->pp_children[i]; - if( p_tmp->i_object_type == i_type ) + if( p_tmp->i_object_type == i_type + && p_tmp->p_internals->i_refcount > 0 ) { - p_tmp->p_internals->i_refcount++; + vlc_object_yield_locked( p_tmp ); return p_tmp; } else if( p_tmp->i_children ) @@ -1359,9 +1379,10 @@ static vlc_object_t * FindObjectName( vlc_object_t *p_this, if( p_tmp ) { if( p_tmp->psz_object_name - && !strcmp( p_tmp->psz_object_name, psz_name ) ) + && !strcmp( p_tmp->psz_object_name, psz_name ) + && p_tmp->p_internals->i_refcount > 0 ) { - p_tmp->p_internals->i_refcount++; + vlc_object_yield_locked( p_tmp ); return p_tmp; } else @@ -1376,9 +1397,10 @@ static vlc_object_t * FindObjectName( vlc_object_t *p_this, { p_tmp = p_this->pp_children[i]; if( p_tmp->psz_object_name - && !strcmp( p_tmp->psz_object_name, psz_name ) ) + && !strcmp( p_tmp->psz_object_name, psz_name ) + && p_tmp->p_internals->i_refcount > 0 ) { - p_tmp->p_internals->i_refcount++; + vlc_object_yield_locked( p_tmp ); return p_tmp; } else if( p_tmp->i_children ) @@ -1579,7 +1601,7 @@ static void ListReplace( vlc_list_t *p_list, vlc_object_t *p_object, return; } - p_object->p_internals->i_refcount++; + vlc_object_yield_locked( p_object ); p_list->p_values[i_index].p_object = p_object; @@ -1601,7 +1623,7 @@ static void ListReplace( vlc_list_t *p_list, vlc_object_t *p_object, return; } - p_object->p_internals->i_refcount++; + vlc_object_yield_locked( p_object ); p_list->p_values[p_list->i_count].p_object = p_object; p_list->i_count++;