[glib] Make quark to string lockless
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Make quark to string lockless
- Date: Sat, 4 Jun 2011 01:14:37 +0000 (UTC)
commit 7ae5e9c2487dc23d6b584d1508f38f5e89700181
Author: Alexander Larsson <alexl redhat com>
Date: Thu May 19 21:30:38 2011 +0200
Make quark to string lockless
We do this by assigning to g_quarks atomically and leaking it when
replacing it atomically. Then its safe to consume the array
on the reader side (atomically).
Also, since we're leaking quarks on growing, bump the block size
so that we're not leaking as much. gtk3-demo allocates > 1500 quarks,
and gnome apps > 3000. I'm setting the block to 2048 which means no
leaks for small gtk3 apps and just one leak for gnome apps.
https://bugzilla.gnome.org/show_bug.cgi?id=650458
glib/gdataset.c | 37 ++++++++++++++++++++++++++-----------
1 files changed, 26 insertions(+), 11 deletions(-)
---
diff --git a/glib/gdataset.c b/glib/gdataset.c
index a09699e..661c30f 100644
--- a/glib/gdataset.c
+++ b/glib/gdataset.c
@@ -136,7 +136,7 @@
**/
/* --- defines --- */
-#define G_QUARK_BLOCK_SIZE (512)
+#define G_QUARK_BLOCK_SIZE (2048)
#define G_DATALIST_FLAGS_MASK_INTERNAL 0x7
@@ -207,7 +207,7 @@ static GDataset *g_dataset_cached = NULL; /* should this be
G_LOCK_DEFINE_STATIC (g_quark_global);
static GHashTable *g_quark_ht = NULL;
static gchar **g_quarks = NULL;
-static GQuark g_quark_seq_id = 0;
+static int g_quark_seq_id = 0;
/* --- functions --- */
@@ -1217,11 +1217,14 @@ G_CONST_RETURN gchar*
g_quark_to_string (GQuark quark)
{
gchar* result = NULL;
+ gchar **quarks;
+ gint quark_seq_id;
- G_LOCK (g_quark_global);
- if (quark < g_quark_seq_id)
- result = g_quarks[quark];
- G_UNLOCK (g_quark_global);
+ quark_seq_id = g_atomic_int_get (&g_quark_seq_id);
+ quarks = g_atomic_pointer_get (&g_quarks);
+
+ if (quark < quark_seq_id)
+ result = quarks[quark];
return result;
}
@@ -1231,20 +1234,32 @@ static inline GQuark
g_quark_new (gchar *string)
{
GQuark quark;
+ gchar **g_quarks_new;
if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
- g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
+ {
+ g_quarks_new = g_new (gchar*, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
+ if (g_quark_seq_id != 0)
+ memcpy (g_quarks_new, g_quarks, sizeof (char *) * g_quark_seq_id);
+ memset (g_quarks_new + g_quark_seq_id, 0, sizeof (char *) * G_QUARK_BLOCK_SIZE);
+ /* This leaks the old quarks array. Its unfortunate, but it allows
+ us to do lockless lookup of the arrays, and there shouldn't be that
+ many quarks in an app */
+ g_atomic_pointer_set (&g_quarks, g_quarks_new);
+ }
if (!g_quark_ht)
{
g_assert (g_quark_seq_id == 0);
g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
- g_quarks[g_quark_seq_id++] = NULL;
+ g_quarks[g_quark_seq_id] = NULL;
+ g_atomic_int_inc (&g_quark_seq_id);
}
- quark = g_quark_seq_id++;
- g_quarks[quark] = string;
+ quark = g_quark_seq_id;
+ g_atomic_pointer_set (&g_quarks[quark], string);
g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
-
+ g_atomic_int_inc (&g_quark_seq_id);
+
return quark;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]