mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-30 12:54:11 +02:00
gsignal: Reduce lock/unlock operations when calling signal_emit_unlocked_R
We used to call this function as unlocked, with a node value that could be invalid at the point of the call, so let's ensure that when we call such function it's defined, and then reduce the access to the signal node members when we're unlocked or after a lock/unlock operation that may have changed it. As per this, add more tests handling multiple signal hooks cases that we did not cover before.
This commit is contained in:
committed by
Philip Withnall
parent
e5ee6e141d
commit
bfc599b8a2
@@ -1130,12 +1130,35 @@ hook_func (GSignalInvocationHint *ihint,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
hook_func_removal (GSignalInvocationHint *ihint,
|
||||
guint n_params,
|
||||
const GValue *params,
|
||||
gpointer data)
|
||||
{
|
||||
gint *count = data;
|
||||
|
||||
(*count)++;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
simple_handler_remove_hook (GObject *sender,
|
||||
gpointer data)
|
||||
{
|
||||
gulong *hook = data;
|
||||
|
||||
g_signal_remove_emission_hook (simple_id, *hook);
|
||||
}
|
||||
|
||||
static void
|
||||
test_emission_hook (void)
|
||||
{
|
||||
GObject *test1, *test2;
|
||||
gint count = 0;
|
||||
gulong hook;
|
||||
gulong connection_id;
|
||||
|
||||
test1 = g_object_new (test_get_type (), NULL);
|
||||
test2 = g_object_new (test_get_type (), NULL);
|
||||
@@ -1150,6 +1173,73 @@ test_emission_hook (void)
|
||||
g_signal_emit_by_name (test1, "simple");
|
||||
g_assert_cmpint (count, ==, 2);
|
||||
|
||||
count = 0;
|
||||
hook = g_signal_add_emission_hook (simple_id, 0, hook_func_removal, &count, NULL);
|
||||
g_assert_cmpint (count, ==, 0);
|
||||
g_signal_emit_by_name (test1, "simple");
|
||||
g_assert_cmpint (count, ==, 1);
|
||||
g_signal_emit_by_name (test2, "simple");
|
||||
g_assert_cmpint (count, ==, 1);
|
||||
|
||||
g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_CRITICAL,
|
||||
"*simple* had no hook * to remove");
|
||||
g_signal_remove_emission_hook (simple_id, hook);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
count = 0;
|
||||
hook = g_signal_add_emission_hook (simple_id, 0, hook_func, &count, NULL);
|
||||
connection_id = g_signal_connect (test1, "simple",
|
||||
G_CALLBACK (simple_handler_remove_hook), &hook);
|
||||
g_assert_cmpint (count, ==, 0);
|
||||
g_signal_emit_by_name (test1, "simple");
|
||||
g_assert_cmpint (count, ==, 1);
|
||||
g_signal_emit_by_name (test2, "simple");
|
||||
g_assert_cmpint (count, ==, 1);
|
||||
|
||||
g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_CRITICAL,
|
||||
"*simple* had no hook * to remove");
|
||||
g_signal_remove_emission_hook (simple_id, hook);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
g_clear_signal_handler (&connection_id, test1);
|
||||
|
||||
gulong hooks[10];
|
||||
count = 0;
|
||||
|
||||
for (size_t i = 0; i < G_N_ELEMENTS (hooks); ++i)
|
||||
hooks[i] = g_signal_add_emission_hook (simple_id, 0, hook_func, &count, NULL);
|
||||
|
||||
g_assert_cmpint (count, ==, 0);
|
||||
g_signal_emit_by_name (test1, "simple");
|
||||
g_assert_cmpint (count, ==, 10);
|
||||
g_signal_emit_by_name (test2, "simple");
|
||||
g_assert_cmpint (count, ==, 20);
|
||||
|
||||
for (size_t i = 0; i < G_N_ELEMENTS (hooks); ++i)
|
||||
g_signal_remove_emission_hook (simple_id, hooks[i]);
|
||||
|
||||
g_signal_emit_by_name (test1, "simple");
|
||||
g_assert_cmpint (count, ==, 20);
|
||||
|
||||
count = 0;
|
||||
|
||||
for (size_t i = 0; i < G_N_ELEMENTS (hooks); ++i)
|
||||
hooks[i] = g_signal_add_emission_hook (simple_id, 0, hook_func_removal, &count, NULL);
|
||||
|
||||
g_assert_cmpint (count, ==, 0);
|
||||
g_signal_emit_by_name (test1, "simple");
|
||||
g_assert_cmpint (count, ==, 10);
|
||||
g_signal_emit_by_name (test2, "simple");
|
||||
g_assert_cmpint (count, ==, 10);
|
||||
|
||||
for (size_t i = 0; i < G_N_ELEMENTS (hooks); ++i)
|
||||
{
|
||||
g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_CRITICAL,
|
||||
"*simple* had no hook * to remove");
|
||||
g_signal_remove_emission_hook (simple_id, hooks[i]);
|
||||
g_test_assert_expected_messages ();
|
||||
}
|
||||
|
||||
g_object_unref (test1);
|
||||
g_object_unref (test2);
|
||||
}
|
||||
|
Reference in New Issue
Block a user