summaryrefslogtreecommitdiff
path: root/glib/gatomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'glib/gatomic.h')
-rw-r--r--glib/gatomic.h125
1 files changed, 120 insertions, 5 deletions
diff --git a/glib/gatomic.h b/glib/gatomic.h
index 086aae368..148424dc3 100644
--- a/glib/gatomic.h
+++ b/glib/gatomic.h
@@ -44,6 +44,14 @@ GLIB_AVAILABLE_IN_ALL
gboolean g_atomic_int_compare_and_exchange (volatile gint *atomic,
gint oldval,
gint newval);
+GLIB_AVAILABLE_IN_2_74
+gboolean g_atomic_int_compare_and_exchange_full (gint *atomic,
+ gint oldval,
+ gint newval,
+ gint *preval);
+GLIB_AVAILABLE_IN_2_74
+gint g_atomic_int_exchange (gint *atomic,
+ gint newval);
GLIB_AVAILABLE_IN_ALL
gint g_atomic_int_add (volatile gint *atomic,
gint val);
@@ -66,6 +74,14 @@ GLIB_AVAILABLE_IN_ALL
gboolean g_atomic_pointer_compare_and_exchange (volatile void *atomic,
gpointer oldval,
gpointer newval);
+GLIB_AVAILABLE_IN_2_74
+gboolean g_atomic_pointer_compare_and_exchange_full (void *atomic,
+ gpointer oldval,
+ gpointer newval,
+ void *preval);
+GLIB_AVAILABLE_IN_2_74
+gpointer g_atomic_pointer_exchange (void *atomic,
+ gpointer newval);
GLIB_AVAILABLE_IN_ALL
gssize g_atomic_pointer_add (volatile void *atomic,
gssize val);
@@ -154,7 +170,7 @@ 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
+#if defined(glib_typeof) && defined(G_CXX_STD_VERSION)
/* 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) \
@@ -164,7 +180,7 @@ G_END_DECLS
(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) */
+#else /* if !(defined(glib_typeof) && defined(G_CXX_STD_VERSION)) */
#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
(G_GNUC_EXTENSION ({ \
gint gaicae_oldval = (oldval); \
@@ -173,6 +189,22 @@ G_END_DECLS
__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_compare_and_exchange_full(atomic, oldval, newval, preval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ G_STATIC_ASSERT (sizeof *(preval) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (newval) ^ (oldval) ^ *(preval) : 1); \
+ *(preval) = (oldval); \
+ __atomic_compare_exchange_n ((atomic), (preval), (newval), FALSE, \
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) \
+ ? TRUE : FALSE; \
+ }))
+#define g_atomic_int_exchange(atomic, newval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (newval) : 1); \
+ (gint) __atomic_exchange_n ((atomic), (newval), __ATOMIC_SEQ_CST); \
+ }))
#define g_atomic_int_add(atomic, val) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
@@ -198,7 +230,7 @@ G_END_DECLS
(guint) __atomic_fetch_xor ((atomic), (val), __ATOMIC_SEQ_CST); \
}))
-#if defined(glib_typeof) && defined(__cplusplus) && __cplusplus >= 201103L
+#if defined(glib_typeof) && defined(G_CXX_STD_VERSION)
/* This is typesafe because we check we can assign oldval to the type of
* (*atomic). Unfortunately it can only be done in C++ because gcc/clang warn
* when atomic is volatile and not oldval, or when atomic is gsize* and oldval
@@ -209,13 +241,14 @@ G_END_DECLS
* https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1715#note_1024120. */
#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
(G_GNUC_EXTENSION ({ \
- G_STATIC_ASSERT (sizeof (oldval) == sizeof (gpointer)); \
+ G_STATIC_ASSERT (sizeof (static_cast<glib_typeof (*(atomic))>((oldval))) \
+ == sizeof (gpointer)); \
glib_typeof (*(atomic)) gapcae_oldval = (oldval); \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
(void) (0 ? (gpointer) *(atomic) : NULL); \
__atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
}))
-#else /* if !(defined(glib_typeof) && defined(__cplusplus) && __cplusplus >= 201103L) */
+#else /* if !(defined(glib_typeof) && defined(G_CXX_STD_VERSION) */
#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof (oldval) == sizeof (gpointer)); \
@@ -225,6 +258,23 @@ G_END_DECLS
__atomic_compare_exchange_n ((atomic), (void *) (&(gapcae_oldval)), (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
}))
#endif /* defined(glib_typeof) */
+#define g_atomic_pointer_compare_and_exchange_full(atomic, oldval, newval, preval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ G_STATIC_ASSERT (sizeof *(preval) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ (void) (0 ? (gpointer) *(preval) : NULL); \
+ *(preval) = (oldval); \
+ __atomic_compare_exchange_n ((atomic), (preval), (newval), FALSE, \
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? \
+ TRUE : FALSE; \
+ }))
+#define g_atomic_pointer_exchange(atomic, newval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ (gpointer) __atomic_exchange_n ((atomic), (newval), __ATOMIC_SEQ_CST); \
+ }))
#define g_atomic_pointer_add(atomic, val) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
@@ -355,6 +405,34 @@ G_END_DECLS
(void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 1); \
__sync_bool_compare_and_swap ((atomic), (oldval), (newval)) ? TRUE : FALSE; \
}))
+#define g_atomic_int_compare_and_exchange_full(atomic, oldval, newval, preval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ G_STATIC_ASSERT (sizeof *(preval) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (newval) ^ (oldval) ^ *(preval) : 1); \
+ *(preval) = __sync_val_compare_and_swap ((atomic), (oldval), (newval)); \
+ (*(preval) == (oldval)) ? TRUE : FALSE; \
+ }))
+#if defined(_GLIB_GCC_HAVE_SYNC_SWAP)
+#define g_atomic_int_exchange(atomic, newval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (newval) : 1); \
+ (gint) __sync_swap ((atomic), (newval)); \
+ }))
+#else /* defined(_GLIB_GCC_HAVE_SYNC_SWAP) */
+ #define g_atomic_int_exchange(atomic, newval) \
+ (G_GNUC_EXTENSION ({ \
+ gint oldval; \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (newval) : 1); \
+ do \
+ { \
+ oldval = *atomic; \
+ } while (!__sync_bool_compare_and_swap (atomic, oldval, newval)); \
+ oldval; \
+ }))
+#endif /* defined(_GLIB_GCC_HAVE_SYNC_SWAP) */
#define g_atomic_int_add(atomic, val) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
@@ -386,6 +464,35 @@ G_END_DECLS
(void) (0 ? (gpointer) *(atomic) : NULL); \
__sync_bool_compare_and_swap ((atomic), (oldval), (newval)) ? TRUE : FALSE; \
}))
+#define g_atomic_pointer_compare_and_exchange_full(atomic, oldval, newval, preval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ G_STATIC_ASSERT (sizeof *(preval) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ (void) (0 ? (gpointer) *(preval) : NULL); \
+ *(preval) = __sync_val_compare_and_swap ((atomic), (oldval), (newval)); \
+ (*(preval) == (oldval)) ? TRUE : FALSE; \
+ }))
+#if defined(_GLIB_GCC_HAVE_SYNC_SWAP)
+#define g_atomic_pointer_exchange(atomic, newval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ (gpointer) __sync_swap ((atomic), (newval)); \
+ }))
+#else
+#define g_atomic_pointer_exchange(atomic, newval) \
+ (G_GNUC_EXTENSION ({ \
+ gpointer oldval; \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ do \
+ { \
+ oldval = (gpointer) *atomic; \
+ } while (!__sync_bool_compare_and_swap (atomic, oldval, newval)); \
+ oldval; \
+ }))
+#endif /* defined(_GLIB_GCC_HAVE_SYNC_SWAP) */
#define g_atomic_pointer_add(atomic, val) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
@@ -425,6 +532,10 @@ G_END_DECLS
(g_atomic_int_set ((gint *) (atomic), (gint) (newval)))
#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
(g_atomic_int_compare_and_exchange ((gint *) (atomic), (oldval), (newval)))
+#define g_atomic_int_compare_and_exchange_full(atomic, oldval, newval, preval) \
+ (g_atomic_int_compare_and_exchange_full ((gint *) (atomic), (oldval), (newval), (gint *) (preval)))
+#define g_atomic_int_exchange(atomic, newval) \
+ (g_atomic_int_exchange ((gint *) (atomic), (newval)))
#define g_atomic_int_add(atomic, val) \
(g_atomic_int_add ((gint *) (atomic), (val)))
#define g_atomic_int_and(atomic, val) \
@@ -458,6 +569,10 @@ G_END_DECLS
#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
(g_atomic_pointer_compare_and_exchange ((atomic), (gpointer) (oldval), (gpointer) (newval)))
+#define g_atomic_pointer_compare_and_exchange_full(atomic, oldval, newval, prevval) \
+ (g_atomic_pointer_compare_and_exchange_full ((atomic), (gpointer) (oldval), (gpointer) (newval), (prevval)))
+#define g_atomic_pointer_exchange(atomic, newval) \
+ (g_atomic_pointer_exchange ((atomic), (gpointer) (newval)))
#define g_atomic_pointer_add(atomic, val) \
(g_atomic_pointer_add ((atomic), (gssize) (val)))
#define g_atomic_pointer_and(atomic, val) \