mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-11 11:44:03 +02:00
gsignal: Use static allocation if we've just few emission hooks
Normally we don't really have emission hooks around, so try to allocate only tiny array to contain a few of them and in case we exceed that limit, we go back to use allocated ones.
This commit is contained in:
committed by
Philip Withnall
parent
bfc599b8a2
commit
76ed55f3a7
@@ -3833,8 +3833,7 @@ signal_emit_unlocked_R (SignalNode *node,
|
|||||||
if (node->emission_hooks)
|
if (node->emission_hooks)
|
||||||
{
|
{
|
||||||
GHook *hook;
|
GHook *hook;
|
||||||
GHook **emission_hooks = NULL;
|
GHook *static_emission_hooks[3];
|
||||||
guint8 *hook_returns = NULL;
|
|
||||||
size_t n_emission_hooks = 0;
|
size_t n_emission_hooks = 0;
|
||||||
const gboolean may_recurse = TRUE;
|
const gboolean may_recurse = TRUE;
|
||||||
guint i;
|
guint i;
|
||||||
@@ -3843,6 +3842,8 @@ signal_emit_unlocked_R (SignalNode *node,
|
|||||||
|
|
||||||
/* Quick check to determine whether any hooks match this emission,
|
/* Quick check to determine whether any hooks match this emission,
|
||||||
* before committing to the more complex work of calling those hooks.
|
* before committing to the more complex work of calling those hooks.
|
||||||
|
* We save a few of them into a static array, to try to avoid further
|
||||||
|
* allocations.
|
||||||
*/
|
*/
|
||||||
hook = g_hook_first_valid (node->emission_hooks, may_recurse);
|
hook = g_hook_first_valid (node->emission_hooks, may_recurse);
|
||||||
while (hook)
|
while (hook)
|
||||||
@@ -3850,34 +3851,70 @@ signal_emit_unlocked_R (SignalNode *node,
|
|||||||
SignalHook *signal_hook = SIGNAL_HOOK (hook);
|
SignalHook *signal_hook = SIGNAL_HOOK (hook);
|
||||||
|
|
||||||
if (!signal_hook->detail || signal_hook->detail == detail)
|
if (!signal_hook->detail || signal_hook->detail == detail)
|
||||||
|
{
|
||||||
|
if (n_emission_hooks < G_N_ELEMENTS (static_emission_hooks))
|
||||||
|
{
|
||||||
|
static_emission_hooks[n_emission_hooks] =
|
||||||
|
g_hook_ref (node->emission_hooks, hook);
|
||||||
|
}
|
||||||
|
|
||||||
n_emission_hooks += 1;
|
n_emission_hooks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
|
hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
|
||||||
}
|
}
|
||||||
|
|
||||||
if G_UNLIKELY (n_emission_hooks > 0)
|
|
||||||
{
|
|
||||||
emission_hooks = g_newa (GHook *, n_emission_hooks);
|
|
||||||
hook_returns = g_newa (guint8, n_emission_hooks);
|
|
||||||
|
|
||||||
/* Re-iterate back through the matching hooks and copy them into
|
/* Re-iterate back through the matching hooks and copy them into
|
||||||
* an array which won’t change when we unlock to call the
|
* an array which won’t change when we unlock to call the
|
||||||
* user-provided hook functions.
|
* user-provided hook functions.
|
||||||
* These functions may change hook configuration for this signal,
|
* These functions may change hook configuration for this signal,
|
||||||
* add / remove signal handlers, etc.
|
* add / remove signal handlers, etc.
|
||||||
*/
|
*/
|
||||||
hook = g_hook_first_valid (node->emission_hooks, may_recurse);
|
if G_UNLIKELY (n_emission_hooks > 0)
|
||||||
for (i = 0; hook; )
|
{
|
||||||
|
guint8 static_hook_returns[G_N_ELEMENTS (static_emission_hooks)];
|
||||||
|
GHook **emission_hooks = NULL;
|
||||||
|
guint8 *hook_returns = NULL;
|
||||||
|
|
||||||
|
if G_LIKELY (n_emission_hooks <= G_N_ELEMENTS (static_emission_hooks))
|
||||||
|
{
|
||||||
|
emission_hooks = static_emission_hooks;
|
||||||
|
hook_returns = static_hook_returns;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emission_hooks = g_newa (GHook *, n_emission_hooks);
|
||||||
|
hook_returns = g_newa (guint8, n_emission_hooks);
|
||||||
|
|
||||||
|
/* We can't just memcpy the ones we have in the static array,
|
||||||
|
* to the alloca()'d one because otherwise we'd get an invalid
|
||||||
|
* ID assertion during unref
|
||||||
|
*/
|
||||||
|
i = 0;
|
||||||
|
for (hook = g_hook_first_valid (node->emission_hooks, may_recurse);
|
||||||
|
hook != NULL;
|
||||||
|
hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse))
|
||||||
{
|
{
|
||||||
SignalHook *signal_hook = SIGNAL_HOOK (hook);
|
SignalHook *signal_hook = SIGNAL_HOOK (hook);
|
||||||
|
|
||||||
if (!signal_hook->detail || signal_hook->detail == detail)
|
if (!signal_hook->detail || signal_hook->detail == detail)
|
||||||
emission_hooks[i++] = g_hook_ref (node->emission_hooks, hook);
|
{
|
||||||
|
if (i < G_N_ELEMENTS (static_emission_hooks))
|
||||||
|
{
|
||||||
|
emission_hooks[i] = g_steal_pointer (&static_emission_hooks[i]);
|
||||||
|
g_assert (emission_hooks[i] == hook);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emission_hooks[i] = g_hook_ref (node->emission_hooks, hook);
|
||||||
|
}
|
||||||
|
|
||||||
hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
|
i += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert (i == n_emission_hooks);
|
g_assert (i == n_emission_hooks);
|
||||||
|
}
|
||||||
|
|
||||||
SIGNAL_UNLOCK ();
|
SIGNAL_UNLOCK ();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user