diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2019-10-09 15:09:53 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2019-10-09 15:09:53 +0000 |
commit | d770e00d9c8fd5cfc6406323970d70af4364da16 (patch) | |
tree | 0c37c1d9465ec4136e6ee642c48f43d0c225d56d | |
parent | 35e26151a82466ef60620f13ed05eddb79bbd2ca (diff) | |
parent | 15e3b6f136245b4e9b4b9ed225610b2fb84423d1 (diff) | |
download | glib-d770e00d9c8fd5cfc6406323970d70af4364da16.tar.gz |
Merge branch 'wip/g-warning-once' into 'master'
gmessages: Add g_warning_once()
See merge request GNOME/glib!1028
-rw-r--r-- | docs/reference/glib/glib-sections.txt | 1 | ||||
-rw-r--r-- | glib/gmessages.h | 38 | ||||
-rw-r--r-- | tests/testglib.c | 21 |
3 files changed, 60 insertions, 0 deletions
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index f6073c21d..eea025c92 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -1411,6 +1411,7 @@ g_log g_logv g_message g_warning +g_warning_once g_critical g_error g_info diff --git a/glib/gmessages.h b/glib/gmessages.h index 95d60c5be..e910f7b73 100644 --- a/glib/gmessages.h +++ b/glib/gmessages.h @@ -30,6 +30,7 @@ #endif #include <stdarg.h> +#include <glib/gatomic.h> #include <glib/gtypes.h> #include <glib/gmacros.h> #include <glib/gvariant.h> @@ -454,6 +455,43 @@ g_debug (const gchar *format, #endif /* !__GNUC__ */ /** + * g_warning_once: + * @...: format string, followed by parameters to insert + * into the format string (as with printf()) + * + * Logs a warning only once. + * + * g_warning_once() calls g_warning() with the passed message the first time + * the statement is executed; subsequent times it is a no-op. + * + * Note! On platforms where the compiler doesn't support variadic macros, the + * warning is printed each time instead of only once. + * + * Since: 2.64 + */ +#if defined(G_HAVE_ISO_VARARGS) && !G_ANALYZER_ANALYZING +#define g_warning_once(...) \ + G_STMT_START { \ + static volatile int G_PASTE (_GWarningOnceBoolean, __LINE__) = 0; \ + if (g_atomic_int_compare_and_exchange (&G_PASTE (_GWarningOnceBoolean, __LINE__), \ + 0, 1)) \ + g_warning (__VA_ARGS__); \ + } G_STMT_END \ + GLIB_AVAILABLE_MACRO_IN_2_64 +#elif defined(G_HAVE_GNUC_VARARGS) && !G_ANALYZER_ANALYZING +#define g_warning_once(format...) \ + G_STMT_START { \ + static volatile int G_PASTE (_GWarningOnceBoolean, __LINE__) = 0; \ + if (g_atomic_int_compare_and_exchange (&G_PASTE (_GWarningOnceBoolean, __LINE__), \ + 0, 1)) \ + g_warning (format); \ + } G_STMT_END \ + GLIB_AVAILABLE_MACRO_IN_2_64 +#else +#define g_warning_once g_warning +#endif + +/** * GPrintFunc: * @string: the message to output * diff --git a/tests/testglib.c b/tests/testglib.c index 372ddae2c..f49a6d99d 100644 --- a/tests/testglib.c +++ b/tests/testglib.c @@ -575,6 +575,26 @@ log_warning_error_tests (void) } static void +log_warning_rate_limited_tests (void) +{ +#if defined(G_HAVE_ISO_VARARGS) || defined(G_HAVE_GNUC_VARARGS) + int i; + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, + "*harmless single warning 1*"); + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, + "*harmless single warning 2*"); + for (i = 0; i < 10; i++) + g_warning_once ("harmless single warning 1"); + for (i = 0; i < 10; i++) + g_warning_once ("harmless single warning 2"); + g_test_assert_expected_messages (); +#else + g_test_skip ("Variadic macro support not available"); +#endif +} + +static void timer_tests (void) { GTimer *timer, *timer2; @@ -1684,6 +1704,7 @@ main (int argc, g_test_add_func ("/testglib/Parse Debug Strings", test_g_parse_debug_string); g_test_add_func ("/testglib/GMemChunk (deprecated)", test_mem_chunks); g_test_add_func ("/testglib/Warnings & Errors", log_warning_error_tests); + g_test_add_func ("/testglib/Warnings (rate limited)", log_warning_rate_limited_tests); g_test_add_func ("/testglib/Timers (slow)", timer_tests); return g_test_run(); |