static void ListChildren ( vlc_list_t *, vlc_object_t *, int );
static void vlc_object_destroy( vlc_object_t *p_this );
-static void vlc_object_yield_locked( vlc_object_t *p_this );
/*****************************************************************************
* Local structure lock
}
}
+ vlc_spin_init( &p_priv->ref_spin );
p_priv->i_refcount = 1;
p_priv->pf_destructor = kVLCDestructor;
p_priv->b_thread = false;
vlc_mutex_lock( &structure_lock );
p_new->i_object_id = p_libvlc_global->i_counter++;
-
/* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's
* useless to try and recover anything if pp_objects gets smashed. */
TAB_APPEND( p_libvlc_global->i_objects, p_libvlc_global->pp_objects,
CloseHandle(p_priv->thread_id.hThread);
#endif
+ vlc_spin_destroy( &p_priv->ref_spin );
vlc_mutex_destroy( &p_this->object_lock );
vlc_cond_destroy( &p_this->object_wait );
vlc_spin_destroy( &p_priv->spin );
/* This happens when there are only two remaining objects */
if( pp_objects[i_middle+1]->i_object_id == i_id )
{
- vlc_object_yield_locked( pp_objects[i_middle+1] );
+ vlc_object_yield( pp_objects[i_middle+1] );
obj = pp_objects[i_middle+1];
}
break;
}
else
{
- vlc_object_yield_locked( pp_objects[i_middle] );
+ vlc_object_yield( pp_objects[i_middle] );
vlc_mutex_unlock( &structure_lock );
return pp_objects[i_middle];
}
/* If we are of the requested type ourselves, don't look further */
if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type )
{
- vlc_object_yield_locked( p_this );
+ vlc_object_yield( p_this );
vlc_mutex_unlock( &structure_lock );
return p_this;
}
vlc_mutex_lock( &structure_lock );
- /* Avoid obvious freed object uses */
- assert( vlc_internals( p_this )->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 ) )
{
- vlc_object_yield_locked( p_this );
+ vlc_object_yield( p_this );
vlc_mutex_unlock( &structure_lock );
return p_this;
}
}
/**
- ****************************************************************************
- * increment an object refcount
- *****************************************************************************/
-
-/* When the structure_lock is locked */
-static void vlc_object_yield_locked( vlc_object_t *p_this )
+ * Increment an object reference counter.
+ */
+void __vlc_object_yield( vlc_object_t *p_this )
{
- vlc_assert_locked (&structure_lock);
+ vlc_object_internals_t *internals = vlc_internals( p_this );
+ vlc_spin_lock( &internals->ref_spin );
/* Avoid obvious freed object uses */
- assert( vlc_internals( p_this )->i_refcount > 0 );
-
+ assert( internals->i_refcount > 0 );
/* Increment the counter */
- vlc_internals( p_this )->i_refcount++;
-}
-
-/* Public function */
-void __vlc_object_yield( vlc_object_t *p_this )
-{
- vlc_mutex_lock( &structure_lock );
- vlc_object_yield_locked( p_this );
- vlc_mutex_unlock( &structure_lock );
+ internals->i_refcount++;
+ vlc_spin_unlock( &internals->ref_spin );
}
-
/*****************************************************************************
* decrement an object refcount
* And destroy the object if its refcount reach zero.
*****************************************************************************/
void __vlc_object_release( vlc_object_t *p_this )
{
+ vlc_object_internals_t *internals = vlc_internals( p_this );
bool b_should_destroy;
- vlc_mutex_lock( &structure_lock );
+ vlc_spin_lock( &internals->ref_spin );
+ assert( internals->i_refcount > 0 );
- assert( vlc_internals( p_this )->i_refcount > 0 );
- vlc_internals( p_this )->i_refcount--;
- b_should_destroy = (vlc_internals( p_this )->i_refcount == 0);
+ if( internals->i_refcount > 1 )
+ {
+ /* Fast path */
+ /* There are still other references to the object */
+ internals->i_refcount--;
+ vlc_spin_unlock( &internals->ref_spin );
+ return;
+ }
+ vlc_spin_unlock( &internals->ref_spin );
+
+ /* Slow path */
+ /* Remember that we cannot hold the spin while waiting on the mutex */
+ vlc_mutex_lock( &structure_lock );
+ /* Take the spin again. Note that another thread may have yielded 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 );
if( b_should_destroy )
{
- /* Make sure this object can't be obtained via vlc_find_object now that
- * it is freed */
+ /* Remove the object from the table so that it cannot be returned from
+ * vlc_object_find() and friends. */
libvlc_global_data_t *p_libvlc_global = vlc_global();
int i_index;
- /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's
- * useless to try and recover anything if pp_objects gets smashed. */
i_index = FindIndex( p_this, p_libvlc_global->pp_objects,
p_libvlc_global->i_objects );
REMOVE_ELEM( p_libvlc_global->pp_objects,
vlc_mutex_lock( &structure_lock );
- /* Avoid obvious freed object uses */
- assert( vlc_internals( p_this )->i_refcount > 0 );
-
/* Attach the parent to its child */
p_this->p_parent = p_parent;
{
if( p_tmp->i_object_type == i_type )
{
- vlc_object_yield_locked( p_tmp );
+ vlc_object_yield( p_tmp );
return p_tmp;
}
else
p_tmp = p_this->pp_children[i];
if( p_tmp->i_object_type == i_type )
{
- vlc_object_yield_locked( p_tmp );
+ vlc_object_yield( p_tmp );
return p_tmp;
}
else if( p_tmp->i_children )
if( p_tmp->psz_object_name
&& !strcmp( p_tmp->psz_object_name, psz_name ) )
{
- vlc_object_yield_locked( p_tmp );
+ vlc_object_yield( p_tmp );
return p_tmp;
}
else
if( p_tmp->psz_object_name
&& !strcmp( p_tmp->psz_object_name, psz_name ) )
{
- vlc_object_yield_locked( p_tmp );
+ vlc_object_yield( p_tmp );
return p_tmp;
}
else if( p_tmp->i_children )
return;
}
- vlc_object_yield_locked( p_object );
+ vlc_object_yield( p_object );
p_list->p_values[i_index].p_object = p_object;
return;
}
- vlc_object_yield_locked( p_object );
+ vlc_object_yield( p_object );
p_list->p_values[p_list->i_count].p_object = p_object;
p_list->i_count++;