[glib: 9/19] gsignal: Canonicalise signal name when looking it up in an object



commit 875e2afa55f98bf602b73bd5dff6da02a7ec692f
Author: Philip Withnall <withnall endlessm com>
Date:   Tue Nov 12 19:40:12 2019 +0000

    gsignal: Canonicalise signal name when looking it up in an object
    
    Previously, we’d look up the signal name as passed to (for example)
    `g_signal_lookup()`, and rely on the fact that signals are inserted
    twice into `g_signal_key_bsa`; once in canonical form and once not.
    
    In preparation for only inserting signals into `g_signal_key_bsa` once,
    we now try looking up a signal with the given signal name and, if that
    fails, try canonicalising the name and trying again.
    
    This is a performance hit on lookups for non-canonical names, but
    shouldn’t affect the performance of lookups for canonical names. If
    people want performance, they should use canonical names.
    
    Signed-off-by: Philip Withnall <withnall endlessm com>
    
    Helps: #358

 gobject/gsignal.c | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)
---
diff --git a/gobject/gsignal.c b/gobject/gsignal.c
index 6b6966dbd..63d0d85a4 100644
--- a/gobject/gsignal.c
+++ b/gobject/gsignal.c
@@ -340,6 +340,29 @@ LOOKUP_SIGNAL_NODE (guint signal_id)
 
 
 /* --- functions --- */
+/* @key must have already been validated with is_valid()
+ * Modifies @key in place. */
+static void
+canonicalize_key (gchar *key)
+{
+  gchar *p;
+
+  for (p = key; *p != 0; p++)
+    {
+      gchar c = *p;
+
+      if (c == '_')
+        *p = '-';
+    }
+}
+
+/* @key must have already been validated with is_valid() */
+static gboolean
+is_canonical (const gchar *key)
+{
+  return (strchr (key, '_') == NULL);
+}
+
 static inline guint
 signal_id_lookup (const gchar *name,
                   GType  itype)
@@ -383,7 +406,22 @@ signal_id_lookup (const gchar *name,
        }
     }
   g_free (ifaces);
-  
+
+  /* If the @name is non-canonical, try again. This is the slow path — people
+   * should use canonical names in their queries if they want performance. */
+  if (!is_canonical (name))
+    {
+      guint signal_id;
+      gchar *name_copy = g_strdup (name);
+      canonicalize_key (name_copy);
+
+      signal_id = signal_id_lookup (name_copy, itype);
+
+      g_free (name_copy);
+
+      return signal_id;
+    }
+
   return 0;
 }
 


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