diff options
author | Philip Withnall <withnall@endlessm.com> | 2019-11-12 19:40:12 +0000 |
---|---|---|
committer | Philip Withnall <withnall@endlessm.com> | 2019-11-15 11:06:14 +0000 |
commit | 875e2afa55f98bf602b73bd5dff6da02a7ec692f (patch) | |
tree | 1f83b431a37f8b4ad90595e11d0d8a407d0a9f7f | |
parent | 90b51805b7f200b0b8de34c0e9794e869ae5bb69 (diff) | |
download | glib-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.c | 40 |
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; } |