[glib/wip/ebassi/rc] Add atomically reference counted memory



commit 43ed42e4d52c14816b10ba83cedfb37e6ccc839a
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Tue Nov 15 12:40:41 2016 +0000

    Add atomically reference counted memory
    
    Similar to g_ref_*, we have g_atomic_ref_*, which will ensure that all
    reference counting operations are performed atomically.
    
    Not every data structure needs atomic reference counting; for instance,
    most of the GTK+ data structures operate under the assumption that only
    one thread can access windowing system data. Since atomic operations are
    not cheap, forcing them on every data structure can negatively affect
    performance.
    
    The underlying reference counting mechanism for g_atomic_ref_* is the
    same as for g_ref_*, but instead of adding a "make this atomic" boolean
    flag to the g_ref_* API we prefer being explicit, and add the "atomic"
    qualifier directly into the API, to avoid misunderstandings.

 glib/grefcount.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 glib/grefcount.h |   21 +++++++++++++++++++
 2 files changed, 78 insertions(+), 0 deletions(-)
---
diff --git a/glib/grefcount.c b/glib/grefcount.c
index 1772c11..830e5d7 100644
--- a/glib/grefcount.c
+++ b/glib/grefcount.c
@@ -326,3 +326,60 @@ g_ref_release (gpointer ref)
   if (g_ref_counter_release (&real_ref->ref_count))
     g_ref_free (ref);
 }
+
+gpointer
+g_atomic_ref_alloc (gsize          size,
+                    GDestroyNotify notify)
+{
+  g_return_val_if_fail (size > 0, NULL);
+
+  return g_ref_alloc_internal (size, FALSE, TRUE, notify);
+}
+
+gpointer
+g_atomic_ref_alloc0 (gsize          size,
+                     GDestroyNotify notify)
+{
+  g_return_val_if_fail (size > 0, NULL);
+
+  return g_ref_alloc_internal (size, TRUE, TRUE, notify);
+}
+
+gpointer
+g_atomic_ref_dup (gconstpointer  data,
+                  gsize          size,
+                  GDestroyNotify notify)
+{
+  gpointer res;
+
+  g_return_val_if_fail (size > 0, NULL);
+
+  res = g_ref_alloc_internal (size, FALSE, TRUE, notify);
+
+  memcpy (res, data, size);
+
+  return res;
+}
+
+gpointer
+g_atomic_ref_acquire (gpointer ref)
+{
+  GRef *real_ref = G_REF (ref);
+
+  g_return_val_if_fail (ref != NULL, NULL);
+
+  g_ref_counter_acquire (&real_ref->ref_count);
+
+  return ref;
+}
+
+void
+g_atomic_ref_release (gpointer ref)
+{
+  GRef *real_ref = G_REF (ref);
+
+  g_return_if_fail (ref != NULL);
+
+  if (g_ref_counter_release (&real_ref->ref_count))
+    g_ref_free (ref);
+}
diff --git a/glib/grefcount.h b/glib/grefcount.h
index 5e38028..8069499 100644
--- a/glib/grefcount.h
+++ b/glib/grefcount.h
@@ -59,6 +59,27 @@ gpointer        g_ref_acquire                   (gpointer       ref);
 GLIB_AVAILABLE_IN_2_52
 void            g_ref_release                   (gpointer       ref);
 
+#define g_atomic_ref_new(Type,Notify) \
+  (Type *) g_atomic_ref_alloc (sizeof (Type), Notify)
+
+#define g_atomic_ref_new0(Type,Notify) \
+  (Type *) g_atomic_ref_alloc0 (sizeof (Type), Notify)
+
+GLIB_AVAILABLE_IN_2_52
+gpointer        g_atomic_ref_alloc              (gsize          size,
+                                                 GDestroyNotify notify);
+GLIB_AVAILABLE_IN_2_52
+gpointer        g_atomic_ref_alloc0             (gsize          size,
+                                                 GDestroyNotify notify);
+GLIB_AVAILABLE_IN_2_52
+gpointer        g_atomic_ref_dup                (gconstpointer  data,
+                                                 gsize          size,
+                                                 GDestroyNotify notify);
+GLIB_AVAILABLE_IN_2_52
+gpointer        g_atomic_ref_acquire            (gpointer       ref);
+GLIB_AVAILABLE_IN_2_52
+void            g_atomic_ref_release            (gpointer       ref);
+
 G_END_DECLS
 
 #endif /* __G_REF_COUNT_H__ */


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