diff options
Diffstat (limited to 'gtk/gtkcsslookup.c')
-rw-r--r-- | gtk/gtkcsslookup.c | 128 |
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); } |