vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Sat Nov 10 18:59:18 2012 +0200| [95b0fabc32bdc5886aa32c40bec421c99320107c] | committer: Rémi Denis-Courmont
objects: use atomic reference counter instead of spin lock + counter > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=95b0fabc32bdc5886aa32c40bec421c99320107c --- src/libvlc.c | 8 +------ src/misc/objects.c | 65 +++++++++++++++++++------------------------------- src/misc/variables.h | 5 ++-- 3 files changed, 28 insertions(+), 50 deletions(-) diff --git a/src/libvlc.c b/src/libvlc.c index abbe7d3..65e27fe 100644 --- a/src/libvlc.c +++ b/src/libvlc.c @@ -682,13 +682,7 @@ void libvlc_InternalDestroy( libvlc_int_t *p_libvlc ) vlc_ExitDestroy( &priv->exit ); vlc_mutex_destroy( &priv->ml_lock ); -#ifndef NDEBUG /* Hack to dump leaked objects tree */ - if( vlc_internals( p_libvlc )->i_refcount > 1 ) - while( vlc_internals( p_libvlc )->i_refcount > 0 ) - vlc_object_release( p_libvlc ); -#endif - - assert( vlc_internals( p_libvlc )->i_refcount == 1 ); + assert( atomic_load(&(vlc_internals(p_libvlc)->refs)) == 1 ); vlc_object_release( p_libvlc ); } diff --git a/src/misc/objects.c b/src/misc/objects.c index c8d90d8..292bba3 100644 --- a/src/misc/objects.c +++ b/src/misc/objects.c @@ -133,8 +133,7 @@ void *vlc_custom_create (vlc_object_t *parent, size_t length, vlc_mutex_init (&priv->var_lock); vlc_cond_init (&priv->var_wait); priv->pipes[0] = priv->pipes[1] = -1; - vlc_spin_init (&priv->ref_spin); - priv->i_refcount = 1; + atomic_init (&priv->refs, 1); priv->pf_destructor = NULL; priv->prev = NULL; priv->first = NULL; @@ -213,9 +212,7 @@ void vlc_object_set_destructor( vlc_object_t *p_this, { vlc_object_internals_t *p_priv = vlc_internals(p_this ); - vlc_spin_lock( &p_priv->ref_spin ); p_priv->pf_destructor = pf_destructor; - vlc_spin_unlock( &p_priv->ref_spin ); } static vlc_mutex_t name_lock = VLC_STATIC_MUTEX; @@ -279,7 +276,6 @@ static void vlc_object_destroy( vlc_object_t *p_this ) free( p_priv->psz_name ); - vlc_spin_destroy( &p_priv->ref_spin ); if( p_priv->pipes[1] != -1 && p_priv->pipes[1] != p_priv->pipes[0] ) close( p_priv->pipes[1] ); if( p_priv->pipes[0] != -1 ) @@ -452,13 +448,9 @@ vlc_object_t *vlc_object_find_name( vlc_object_t *p_this, const char *psz_name ) void * vlc_object_hold( vlc_object_t *p_this ) { vlc_object_internals_t *internals = vlc_internals( p_this ); + unsigned refs = atomic_fetch_add (&internals->refs, 1); - vlc_spin_lock( &internals->ref_spin ); - /* Avoid obvious freed object uses */ - assert( internals->i_refcount > 0 ); - /* Increment the counter */ - internals->i_refcount++; - vlc_spin_unlock( &internals->ref_spin ); + assert (refs > 0); /* Avoid obvious freed object uses */ (void) refs; return p_this; } @@ -471,43 +463,38 @@ void vlc_object_release( vlc_object_t *p_this ) { vlc_object_internals_t *internals = vlc_internals( p_this ); vlc_object_t *parent = NULL; - bool b_should_destroy; + unsigned refs = atomic_load (&internals->refs); - vlc_spin_lock( &internals->ref_spin ); - assert( internals->i_refcount > 0 ); - - if( internals->i_refcount > 1 ) + /* Fast path */ + while (refs > 1) { - /* Fast path */ - /* There are still other references to the object */ - internals->i_refcount--; - vlc_spin_unlock( &internals->ref_spin ); - return; + if (atomic_compare_exchange_weak (&internals->refs, &refs, refs - 1)) + return; /* There are still other references to the object */ + + assert (refs > 0); } - vlc_spin_unlock( &internals->ref_spin ); /* Slow path */ - /* Remember that we cannot hold the spin while waiting on the mutex */ libvlc_lock (p_this->p_libvlc); - /* Take the spin again. Note that another thread may have held the - * object in the (very short) mean time. */ - vlc_spin_lock( &internals->ref_spin ); - b_should_destroy = --internals->i_refcount == 0; - vlc_spin_unlock( &internals->ref_spin ); + refs = atomic_fetch_sub (&internals->refs, 1); + assert (refs > 0); - if( b_should_destroy ) + if (likely(refs == 1)) { /* Detach from parent to protect against vlc_object_find_name() */ parent = p_this->p_parent; if (likely(parent)) { /* Unlink */ - if (internals->prev != NULL) - internals->prev->next = internals->next; + vlc_object_internals_t *prev = internals->prev; + vlc_object_internals_t *next = internals->next; + + if (prev != NULL) + prev->next = next; else - vlc_internals(parent)->first = internals->next; - if (internals->next != NULL) - internals->next->prev = internals->prev; + vlc_internals (parent)->first = next; + if (next != NULL) + next->prev = prev; } /* We have no children */ @@ -515,11 +502,9 @@ void vlc_object_release( vlc_object_t *p_this ) } libvlc_unlock (p_this->p_libvlc); - if( b_should_destroy ) + if (likely(refs == 1)) { - int canc; - - canc = vlc_savecancel (); + int canc = vlc_savecancel (); vlc_object_destroy( p_this ); vlc_restorecancel (canc); if (parent) @@ -727,9 +712,7 @@ static void PrintObject( vlc_object_internals_t *priv, } vlc_mutex_unlock (&name_lock); - psz_refcount[0] = '\0'; - if( priv->i_refcount > 0 ) - snprintf( psz_refcount, 19, ", %u refs", priv->i_refcount ); + snprintf( psz_refcount, 19, ", %u refs", atomic_load( &priv->refs ) ); psz_parent[0] = '\0'; /* FIXME: need structure lock!!! */ diff --git a/src/misc/variables.h b/src/misc/variables.h index 7d56caf..671f337 100644 --- a/src/misc/variables.h +++ b/src/misc/variables.h @@ -23,6 +23,8 @@ #ifndef LIBVLC_VARIABLES_H # define LIBVLC_VARIABLES_H 1 +# include <vlc_atomic.h> + /** * Private LibVLC data for each object. */ @@ -41,8 +43,7 @@ struct vlc_object_internals int pipes[2]; /* Objects management */ - vlc_spinlock_t ref_spin; - unsigned i_refcount; + atomic_uint refs; vlc_destructor_t pf_destructor; /* Objects tree structure */ _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
