object: make _replace like the miniobject version

This commit is contained in:
Wim Taymans 2011-08-22 12:49:04 +02:00
parent 8170c34c94
commit 655f1b9c57
2 changed files with 23 additions and 17 deletions

View file

@ -292,25 +292,20 @@ gst_object_ref_sink (gpointer object)
* replace * replace
* @newobj: (transfer none): a new #GstObject * @newobj: (transfer none): a new #GstObject
* *
* Unrefs the #GstObject pointed to by @oldobj, refs @newobj and * Atomically modifies a pointer to point to a new object.
* puts @newobj in *@oldobj. Be carefull when calling this * The reference count of @oldobj is decreased and the reference count of
* function, it does not take any locks. You might want to lock * @newobj is increased.
* the object owning @oldobj pointer before calling this
* function.
* *
* Make sure not to LOCK @oldobj because it might be unreffed * Either @newobj and the value pointed to by @oldobj may be NULL.
* which could cause a deadlock when it is disposed.
* *
* Since 0.10.36, this function operates atomically. * Returns: TRUE if @newobj was different from @oldobj
*/ */
void gboolean
gst_object_replace (GstObject ** oldobj, GstObject * newobj) gst_object_replace (GstObject ** oldobj, GstObject * newobj)
{ {
GstObject *oldptr; GstObject *oldptr;
g_return_if_fail (oldobj != NULL); g_return_val_if_fail (oldobj != NULL, FALSE);
g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj));
g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj));
#ifdef DEBUG_REFCOUNT #ifdef DEBUG_REFCOUNT
GST_CAT_TRACE (GST_CAT_REFCOUNTING, "replace %p %s (%d) with %p %s (%d)", GST_CAT_TRACE (GST_CAT_REFCOUNTING, "replace %p %s (%d) with %p %s (%d)",
@ -320,14 +315,25 @@ gst_object_replace (GstObject ** oldobj, GstObject * newobj)
newobj ? G_OBJECT (newobj)->ref_count : 0); newobj ? G_OBJECT (newobj)->ref_count : 0);
#endif #endif
oldptr = g_atomic_pointer_get ((gpointer *) oldobj);
if (G_UNLIKELY (oldptr == newobj))
return FALSE;
if (newobj) if (newobj)
g_object_ref (newobj); g_object_ref (newobj);
do {
oldptr = *oldobj; while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
} while (!g_atomic_pointer_compare_and_exchange ((void *) oldobj, oldobj, oldptr, newobj))) {
oldptr, newobj)); oldptr = g_atomic_pointer_get ((gpointer *) oldobj);
if (G_UNLIKELY (oldptr == newobj))
break;
}
if (oldptr) if (oldptr)
g_object_unref (oldptr); g_object_unref (oldptr);
return oldptr != newobj;
} }
/* dispose is called when the object has to release all links /* dispose is called when the object has to release all links

View file

@ -220,7 +220,7 @@ void gst_object_unref (gpointer object);
gpointer gst_object_ref_sink (gpointer object); gpointer gst_object_ref_sink (gpointer object);
/* replace object pointer */ /* replace object pointer */
void gst_object_replace (GstObject **oldobj, GstObject *newobj); gboolean gst_object_replace (GstObject **oldobj, GstObject *newobj);
/* printing out the 'path' of the object */ /* printing out the 'path' of the object */
gchar * gst_object_get_path_string (GstObject *object); gchar * gst_object_get_path_string (GstObject *object);