diff --git a/glib/gatomic.h b/glib/gatomic.h index 5eba1dbc7..8b2b880c8 100644 --- a/glib/gatomic.h +++ b/glib/gatomic.h @@ -152,6 +152,17 @@ G_END_DECLS (void) (0 ? *(atomic) ^ *(atomic) : 1); \ __atomic_fetch_sub ((atomic), 1, __ATOMIC_SEQ_CST) == 1; \ })) +#if defined(glib_typeof) && defined(__cplusplus) && __cplusplus >= 201103L +/* See comments below about equivalent g_atomic_pointer_compare_and_exchange() + * shenanigans for type-safety when compiling in C++ mode. */ +#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \ + (G_GNUC_EXTENSION ({ \ + glib_typeof (*(atomic)) gaicae_oldval = (oldval); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + (void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 1); \ + __atomic_compare_exchange_n ((atomic), &gaicae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \ + })) +#else /* if !(defined(glib_typeof) && defined(__cplusplus) && __cplusplus >= 201103L) */ #define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \ (G_GNUC_EXTENSION ({ \ gint gaicae_oldval = (oldval); \ @@ -159,6 +170,7 @@ G_END_DECLS (void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 1); \ __atomic_compare_exchange_n ((atomic), (void *) (&(gaicae_oldval)), (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \ })) +#endif /* defined(glib_typeof) */ #define g_atomic_int_add(atomic, val) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ diff --git a/glib/tests/cxx.cpp b/glib/tests/cxx.cpp index be0a6bfa1..6426d43a7 100644 --- a/glib/tests/cxx.cpp +++ b/glib/tests/cxx.cpp @@ -49,7 +49,41 @@ test_typeof (void) g_clear_pointer (&obj6, g_rc_box_release); g_rc_box_release (obj); #else - g_test_skip ("This test requires C++11 compiler"); + g_test_skip ("This test requires a C++11 compiler"); +#endif +} + +static void +test_atomic_pointer_compare_and_exchange (void) +{ +#if __cplusplus >= 201103L + const gchar *str1 = "str1"; + const gchar *str2 = "str2"; + const gchar *atomic_string = str1; + + g_test_message ("Test that g_atomic_pointer_compare_and_exchange() with a " + "non-void* pointer doesn’t have any compiler warnings in C++ mode"); + + g_assert_true (g_atomic_pointer_compare_and_exchange (&atomic_string, str1, str2)); + g_assert_true (atomic_string == str2); +#else + g_test_skip ("This test requires a C++11 compiler"); +#endif +} + +static void +test_atomic_int_compare_and_exchange (void) +{ +#if __cplusplus >= 201103L + gint atomic_int = 5; + + g_test_message ("Test that g_atomic_int_compare_and_exchange() doesn’t have " + "any compiler warnings in C++ mode"); + + g_assert_true (g_atomic_int_compare_and_exchange (&atomic_int, 5, 50)); + g_assert_cmpint (atomic_int, ==, 50); +#else + g_test_skip ("This test requires a C++11 compiler"); #endif } @@ -63,6 +97,8 @@ main (int argc, char *argv[]) #endif g_test_add_func ("/C++/typeof", test_typeof); + g_test_add_func ("/C++/atomic-pointer-compare-and-exchange", test_atomic_pointer_compare_and_exchange); + g_test_add_func ("/C++/atomic-int-compare-and-exchange", test_atomic_int_compare_and_exchange); return g_test_run (); }