summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2011-08-21 14:07:08 -0700
committerDavid Schleef <ds@schleef.org>2011-08-21 14:07:08 -0700
commitec6e452f6314b10e883c6f95366867a02c775ff0 (patch)
tree8a05552c617402d81ffcda58849c22a08aa869fa
parentcce32ba0a29cdebc34cf6bf66e72a3f554be3028 (diff)
object: make gst_object_replace() atomic
-rw-r--r--gst/gstobject.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/gst/gstobject.c b/gst/gstobject.c
index f06d798e4..8efadeb4c 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