summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <withnall@endlessm.com>2019-11-12 19:40:12 +0000
committerPhilip Withnall <withnall@endlessm.com>2019-11-15 11:06:14 +0000
commit875e2afa55f98bf602b73bd5dff6da02a7ec692f (patch)
tree1f83b431a37f8b4ad90595e11d0d8a407d0a9f7f
parent90b51805b7f200b0b8de34c0e9794e869ae5bb69 (diff)
downloadglib-875e2afa55f98bf602b73bd5dff6da02a7ec692f.tar.gz
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
-rw-r--r--gobject/gsignal.c40
1 files changed, 39 insertions, 1 deletions
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;
}