object: make gst_object_replace() atomic

This commit is contained in:
David Schleef 2011-08-21 14:07:08 -07:00
parent cce32ba0a2
commit ec6e452f63

View file

@ -421,10 +421,14 @@ gst_object_sink (gpointer object)
* *
* Make sure not to LOCK @oldobj because it might be unreffed * Make sure not to LOCK @oldobj because it might be unreffed
* which could cause a deadlock when it is disposed. * which could cause a deadlock when it is disposed.
*
* Since 0.10.36, this function operates atomically.
*/ */
void void
gst_object_replace (GstObject ** oldobj, GstObject * newobj) gst_object_replace (GstObject ** oldobj, GstObject * newobj)
{ {
GstObject *oldptr;
g_return_if_fail (oldobj != NULL); g_return_if_fail (oldobj != NULL);
g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj)); g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj));
g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj)); g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj));
@ -437,14 +441,14 @@ gst_object_replace (GstObject ** oldobj, GstObject * newobj)
newobj ? G_OBJECT (newobj)->ref_count : 0); newobj ? G_OBJECT (newobj)->ref_count : 0);
#endif #endif
if (G_LIKELY (*oldobj != newobj)) { if (newobj)
if (newobj) g_object_ref (newobj);
gst_object_ref (newobj); do {
if (*oldobj) oldptr = *oldobj;
gst_object_unref (*oldobj); } while (!g_atomic_pointer_compare_and_exchange ((void *) oldobj,
oldptr, newobj));
*oldobj = newobj; if (oldptr)
} g_object_unref (oldptr);
} }
/* dispose is called when the object has to release all links /* dispose is called when the object has to release all links