From ec6e452f6314b10e883c6f95366867a02c775ff0 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 21 Aug 2011 14:07:08 -0700 Subject: [PATCH] object: make gst_object_replace() atomic --- gst/gstobject.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/gst/gstobject.c b/gst/gstobject.c index f06d798..8efadeb 100644 --- a/gst/gstobject.c +++ b/gst/gstobject.c @@ -421,10 +421,14 @@ gst_object_sink (gpointer object) * * Make sure not to LOCK @oldobj because it might be unreffed * which could cause a deadlock when it is disposed. + * + * Since 0.10.36, this function operates atomically. */ void gst_object_replace (GstObject ** oldobj, GstObject * newobj) { + GstObject *oldptr; + g_return_if_fail (oldobj != NULL); g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj)); 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); #endif - if (G_LIKELY (*oldobj != newobj)) { - if (newobj) - gst_object_ref (newobj); - if (*oldobj) - gst_object_unref (*oldobj); - - *oldobj = newobj; - } + if (newobj) + g_object_ref (newobj); + do { + oldptr = *oldobj; + } while (!g_atomic_pointer_compare_and_exchange ((void *) oldobj, + oldptr, newobj)); + if (oldptr) + g_object_unref (oldptr); } /* dispose is called when the object has to release all links -- 2.7.4