gsignal: let g_clear_signal_handler() evaluate argument only once

Preferably macros behave function-like to minimize surprises. That
means for example that they evaluate all arguments exactly once.

Rework g_clear_signal_handler() to assign the macro parameters
to auto variables so they are accessed exactly once.

Also, drop the static assert for the size of (*handler_id_ptr).
As we now assign to a "gulong *" pointer, the compiler already
checks the types. In fact, the check is now stricter than before.
Previously it would have allowed a pointer to a "signed long".
This is a change in behavior of the macro and the stricter compile
check could cause a build failure with broken code.

Also, clear the handler id first, before calling
g_signal_handler_disconnect(). Disconnecting a signal invokes the
destroy notify, which can have side effects. It just feels cleaner
to first reset the *_handler_id_ptr, before those side effects
can happen. Of course, in practice it makes little difference.
This commit is contained in:
Thomas Haller 2021-01-26 14:09:02 +01:00
parent cc4ffe4742
commit 7777f3bdbe

View File

@ -451,13 +451,14 @@ void g_clear_signal_handler (gulong *handler_id_ptr,
#define g_clear_signal_handler(handler_id_ptr, instance) \ #define g_clear_signal_handler(handler_id_ptr, instance) \
G_STMT_START { \ G_STMT_START { \
G_STATIC_ASSERT (sizeof *(handler_id_ptr) == sizeof (gulong)); \ gpointer const _instance = (instance); \
gulong _handler_id = *(handler_id_ptr); \ gulong *const _handler_id_ptr = (handler_id_ptr); \
const gulong _handler_id = *_handler_id_ptr; \
\ \
if (_handler_id > 0) \ if (_handler_id > 0) \
{ \ { \
g_signal_handler_disconnect ((instance), _handler_id); \ *_handler_id_ptr = 0; \
*(handler_id_ptr) = 0; \ g_signal_handler_disconnect (_instance, _handler_id); \
} \ } \
} G_STMT_END \ } G_STMT_END \
GLIB_AVAILABLE_MACRO_IN_2_62 GLIB_AVAILABLE_MACRO_IN_2_62