[gobject-introspection] girepository: Use g_atomic for refcounting



commit 4b1bf70c93acb3446c1e9049ac422d911a10762d
Author: Colin Walters <walters verbum org>
Date:   Mon Nov 19 21:42:44 2012 -0500

    girepository: Use g_atomic for refcounting
    
    They could be freed in separate threads (e.g. language binding GC
    thread).  But no particular reason to change other than noticing it
    during code inspection for a different bug.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=688694

 girepository/gibaseinfo.c           |   25 ++++++++++++-------------
 girepository/girepository-private.h |    9 +++++++--
 2 files changed, 19 insertions(+), 15 deletions(-)
---
diff --git a/girepository/gibaseinfo.c b/girepository/gibaseinfo.c
index ff9c939..37893e6 100644
--- a/girepository/gibaseinfo.c
+++ b/girepository/gibaseinfo.c
@@ -226,7 +226,7 @@ g_base_info_ref (GIBaseInfo *info)
   GIRealInfo *rinfo = (GIRealInfo*)info;
 
   g_assert (rinfo->ref_count != INVALID_REFCOUNT);
-  ((GIRealInfo*)info)->ref_count++;
+  g_atomic_int_inc (&rinfo->ref_count);
 
   return info;
 }
@@ -244,21 +244,20 @@ g_base_info_unref (GIBaseInfo *info)
   GIRealInfo *rinfo = (GIRealInfo*)info;
 
   g_assert (rinfo->ref_count > 0 && rinfo->ref_count != INVALID_REFCOUNT);
-  rinfo->ref_count--;
 
-  if (!rinfo->ref_count)
-    {
-      if (rinfo->container && ((GIRealInfo *) rinfo->container)->ref_count != INVALID_REFCOUNT)
-        g_base_info_unref (rinfo->container);
+  if (!g_atomic_int_dec_and_test (&rinfo->ref_count))
+    return;
 
-      if (rinfo->repository)
-        g_object_unref (rinfo->repository);
+  if (rinfo->container && ((GIRealInfo *) rinfo->container)->ref_count != INVALID_REFCOUNT)
+    g_base_info_unref (rinfo->container);
 
-      if (rinfo->type == GI_INFO_TYPE_UNRESOLVED)
-        g_slice_free (GIUnresolvedInfo, (GIUnresolvedInfo *) rinfo);
-      else
-        g_slice_free (GIRealInfo, rinfo);
-    }
+  if (rinfo->repository)
+    g_object_unref (rinfo->repository);
+
+  if (rinfo->type == GI_INFO_TYPE_UNRESOLVED)
+    g_slice_free (GIUnresolvedInfo, (GIUnresolvedInfo *) rinfo);
+  else
+    g_slice_free (GIRealInfo, rinfo);
 }
 
 /**
diff --git a/girepository/girepository-private.h b/girepository/girepository-private.h
index 275776d..bbd34e3 100644
--- a/girepository/girepository-private.h
+++ b/girepository/girepository-private.h
@@ -33,6 +33,11 @@
 
 typedef struct _GIRealInfo GIRealInfo;
 
+/* We changed a gint32 -> gint in the structure below, which should be
+ * valid everywhere we care about.
+ */
+G_STATIC_ASSERT (sizeof (int) == sizeof (gint32));
+
 /*
  * We just use one structure for all of the info object
  * types; in general, we should be reading data directly
@@ -43,7 +48,7 @@ struct _GIRealInfo
 {
   /* Keep this part in sync with GIUnresolvedInfo below */
   gint32 type;
-  gint32 ref_count;
+  volatile gint ref_count;
   GIRepository *repository;
   GIBaseInfo *container;
 
@@ -62,7 +67,7 @@ struct _GIUnresolvedInfo
 {
   /* Keep this part in sync with GIBaseInfo above */
   gint32 type;
-  gint32 ref_count;
+  volatile gint ref_count;
   GIRepository *repository;
   GIBaseInfo *container;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]