[glib/wip/ebassi/rc] Add atomically reference counted memory
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/ebassi/rc] Add atomically reference counted memory
- Date: Tue, 15 Nov 2016 13:36:24 +0000 (UTC)
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]