summaryrefslogtreecommitdiff
path: root/gtk/gtkcsslookup.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/gtkcsslookup.c')
-rw-r--r--gtk/gtkcsslookup.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c
index e7ae35c52c..95347665a1 100644
--- a/gtk/gtkcsslookup.c
+++ b/gtk/gtkcsslookup.c
@@ -66,6 +66,92 @@ gtk_css_lookup_value_unref (GtkCssLookupValue *value)
gtk_css_lookup_value_free (value);
}
+static GHashTable *lookups;
+
+static gboolean
+gtk_css_lookup_equal (gconstpointer p1,
+ gconstpointer p2)
+{
+ const GtkCssLookup *l1 = p1;
+ const GtkCssLookup *l2 = p2;
+ int i;
+
+ if (!_gtk_bitmask_equals (l1->set_values, l2->set_values))
+ return FALSE;
+
+ if (l1->values == NULL && l2->values == NULL)
+ return TRUE;
+
+ if (l1->values == NULL || l2->values == NULL)
+ return FALSE;
+
+ if (l1->values->len != l2->values->len)
+ return FALSE;
+
+ for (i = 0; i < l1->values->len; i++)
+ {
+ GtkCssLookupValue *v1 = g_ptr_array_index (l1->values, i);
+ GtkCssLookupValue *v2 = g_ptr_array_index (l2->values, i);
+
+ if (!_gtk_css_value_equal (v1->value, v2->value))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static guint
+gtk_css_lookup_hash (gconstpointer data)
+{
+ const GtkCssLookup *l = data;
+ int i;
+ guint h;
+
+ if (l->values == NULL)
+ return 0;
+
+ h = 0;
+ for (i = 0; i < l->values->len; i++)
+ {
+ GtkCssLookupValue *v = g_ptr_array_index (l->values, i);
+ char *s = _gtk_css_value_to_string (v->value);
+ h += g_str_hash (s);
+ g_free (s);
+ }
+
+ return h;
+}
+
+static gboolean
+dump_lookups (gpointer data)
+{
+ GHashTableIter iter;
+ GtkCssLookup *key;
+ gpointer value;
+ int total = 0;
+ int length = 0;
+
+ g_hash_table_iter_init (&iter, lookups);
+ while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
+ {
+ total += GPOINTER_TO_INT (value);
+ length += GPOINTER_TO_INT (value) * key->values->len;
+ }
+
+ g_print ("lookup stats:\n");
+ g_print ("\t%d different lookups, %d total, %g avg length\n",
+ g_hash_table_size (lookups),
+ total,
+ length / (1.0 * total));
+
+ g_hash_table_iter_init (&iter, lookups);
+ while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
+ g_print ("\t%d\t%d\n", GPOINTER_TO_INT (value), key->values->len);
+ g_print ("\n");
+
+ return G_SOURCE_CONTINUE;
+}
+
GtkCssLookup *
gtk_css_lookup_new (void)
{
@@ -74,12 +160,50 @@ gtk_css_lookup_new (void)
lookup->ref_count = 1;
lookup->set_values = _gtk_bitmask_new ();
+ if (!lookups)
+ {
+ lookups = g_hash_table_new (gtk_css_lookup_hash, gtk_css_lookup_equal);
+ g_timeout_add (1000, dump_lookups, NULL);
+ }
+
return lookup;
}
+void
+gtk_css_lookup_register (GtkCssLookup *lookup)
+{
+ gint count;
+
+ count = GPOINTER_TO_INT (g_hash_table_lookup (lookups, lookup));
+ count++;
+
+ if (count == 1)
+ gtk_css_lookup_ref (lookup);
+
+ g_hash_table_insert (lookups, lookup, GINT_TO_POINTER (count));
+}
+
+static void
+gtk_css_lookup_unregister (GtkCssLookup *lookup)
+{
+ gint count;
+
+ count = GPOINTER_TO_INT (g_hash_table_lookup (lookups, lookup));
+ g_assert (count > 0);
+ if (count == 1)
+ g_hash_table_remove (lookups, lookup);
+ else
+ {
+ count--;
+ g_hash_table_insert (lookups, lookup, GINT_TO_POINTER (count));
+ }
+}
+
static void
gtk_css_lookup_free (GtkCssLookup *lookup)
{
+ gtk_css_lookup_unregister (lookup);
+
_gtk_bitmask_free (lookup->set_values);
if (lookup->values)
g_ptr_array_unref (lookup->values);
@@ -105,6 +229,10 @@ gtk_css_lookup_unref (GtkCssLookup *lookup)
lookup->ref_count--;
+ if (lookup->ref_count == 1 &&
+ GPOINTER_TO_INT (g_hash_table_lookup (lookups, lookup)) == 1)
+ lookup->ref_count--;
+
if (lookup->ref_count == 0)
gtk_css_lookup_free (lookup);
}