diff --git a/gio/gdbusconnection.h b/gio/gdbusconnection.h index fe31ea0f4..40f5f657f 100644 --- a/gio/gdbusconnection.h +++ b/gio/gdbusconnection.h @@ -603,6 +603,46 @@ GIO_AVAILABLE_IN_ALL void g_dbus_connection_signal_unsubscribe (GDBusConnection *connection, guint subscription_id); +/** + * g_clear_dbus_signal_subscription: (skip) + * @subscription_id_pointer: (not optional) (inout): A pointer to either a + * subscription id obtained from g_dbus_connection_signal_subscribe(), + * or zero. + * @connection: The connection from which the subscription ID was obtained. + * This pointer may be %NULL or invalid, if the subscription ID is zero. + * + * If @subscription_id_pointer points to a nonzero subscription ID, + * unsubscribe from that D-Bus signal subscription as if via + * g_dbus_connection_signal_unsubscribe(). + * Also set the value pointed to by @subscription_id_pointer to zero, + * which is not a valid subscription ID. + * + * This convenience function for C code helps to ensure that each signal + * subscription is unsubscribed exactly once, similar to g_clear_object() + * and g_clear_signal_handler(). + * + * Since: 2.84 + */ +GLIB_AVAILABLE_STATIC_INLINE_IN_2_84 +static inline void g_clear_dbus_signal_subscription (guint *subscription_id_pointer, + GDBusConnection *connection); + +GLIB_AVAILABLE_STATIC_INLINE_IN_2_84 +static inline void +g_clear_dbus_signal_subscription (guint *subscription_id_pointer, + GDBusConnection *connection) +{ + guint subscription_id; + + /* Suppress "Not available before" warning */ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + subscription_id = g_steal_handle_id (subscription_id_pointer); + G_GNUC_END_IGNORE_DEPRECATIONS + + if (subscription_id > 0) + g_dbus_connection_signal_unsubscribe (connection, subscription_id); +} + /* ---------------------------------------------------------------------------------------------------- */ /** diff --git a/gio/tests/gdbus-connection.c b/gio/tests/gdbus-connection.c index 8d37af83b..9b8178d4d 100644 --- a/gio/tests/gdbus-connection.c +++ b/gio/tests/gdbus-connection.c @@ -793,12 +793,18 @@ test_connection_signals (void) g_assert_cmpint (count_s4, ==, 2); g_assert_cmpint (count_s5, ==, 1); - g_dbus_connection_signal_unsubscribe (c1, g_steal_handle_id (&s1)); - g_dbus_connection_signal_unsubscribe (c1, g_steal_handle_id (&s2)); - g_dbus_connection_signal_unsubscribe (c1, g_steal_handle_id (&s3)); - g_dbus_connection_signal_unsubscribe (c1, g_steal_handle_id (&s1b)); - g_dbus_connection_signal_unsubscribe (c1, g_steal_handle_id (&s4)); - g_dbus_connection_signal_unsubscribe (c1, g_steal_handle_id (&s5)); + g_assert_cmpint (s1, !=, 0); + g_clear_dbus_signal_subscription (&s1, c1); + g_assert_cmpint (s1, ==, 0); + /* g_clear_dbus_signal_subscription() is idempotent, with no warnings */ + g_clear_dbus_signal_subscription (&s1, c1); + g_assert_cmpint (s1, ==, 0); + + g_clear_dbus_signal_subscription (&s2, c1); + g_clear_dbus_signal_subscription (&s3, c1); + g_clear_dbus_signal_subscription (&s1b, c1); + g_clear_dbus_signal_subscription (&s4, c1); + g_clear_dbus_signal_subscription (&s5, c1); g_object_unref (c1); g_object_unref (c2); @@ -852,8 +858,8 @@ test_match_rule (GDBusConnection *connection, g_assert_cmpint (emissions, ==, 1); g_assert_cmpint (matches, ==, should_match ? 1 : 0); - g_dbus_connection_signal_unsubscribe (connection, g_steal_handle_id (&subscription_ids[0])); - g_dbus_connection_signal_unsubscribe (connection, g_steal_handle_id (&subscription_ids[1])); + g_clear_dbus_signal_subscription (&subscription_ids[0], connection); + g_clear_dbus_signal_subscription (&subscription_ids[1], connection); } static void @@ -1132,7 +1138,7 @@ test_connection_filter (void) timeout_mainloop_id = g_timeout_add (30000, test_connection_filter_on_timeout, NULL); g_main_loop_run (loop); g_source_remove (timeout_mainloop_id); - g_dbus_connection_signal_unsubscribe (c, g_steal_handle_id (&signal_handler_id)); + g_clear_dbus_signal_subscription (&signal_handler_id, c); /* now test some combinations... */ filter_id = g_dbus_connection_add_filter (c,