mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
Merge branch 'gatomic-exchange' into 'main'
gatomic: Add APIs to perform atomic int / pointer exchanges See merge request GNOME/glib!2726
This commit is contained in:
commit
d7c3b0fbf2
@ -1273,6 +1273,7 @@ g_atomic_int_set
|
|||||||
g_atomic_int_inc
|
g_atomic_int_inc
|
||||||
g_atomic_int_dec_and_test
|
g_atomic_int_dec_and_test
|
||||||
g_atomic_int_compare_and_exchange
|
g_atomic_int_compare_and_exchange
|
||||||
|
g_atomic_int_exchange
|
||||||
g_atomic_int_add
|
g_atomic_int_add
|
||||||
g_atomic_int_and
|
g_atomic_int_and
|
||||||
g_atomic_int_or
|
g_atomic_int_or
|
||||||
@ -1282,6 +1283,7 @@ g_atomic_int_xor
|
|||||||
g_atomic_pointer_get
|
g_atomic_pointer_get
|
||||||
g_atomic_pointer_set
|
g_atomic_pointer_set
|
||||||
g_atomic_pointer_compare_and_exchange
|
g_atomic_pointer_compare_and_exchange
|
||||||
|
g_atomic_pointer_exchange
|
||||||
g_atomic_pointer_add
|
g_atomic_pointer_add
|
||||||
g_atomic_pointer_and
|
g_atomic_pointer_and
|
||||||
g_atomic_pointer_or
|
g_atomic_pointer_or
|
||||||
|
@ -218,6 +218,31 @@ gboolean
|
|||||||
return g_atomic_int_compare_and_exchange (atomic, oldval, newval);
|
return g_atomic_int_compare_and_exchange (atomic, oldval, newval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_atomic_int_exchange:
|
||||||
|
* @atomic: a pointer to a #gint or #guint
|
||||||
|
* @newval: the value to replace with
|
||||||
|
*
|
||||||
|
* Sets the @atomic to @newval and returns the old value from @atomic.
|
||||||
|
*
|
||||||
|
* This exchange is done atomically.
|
||||||
|
*
|
||||||
|
* Think of this operation as an atomic version of
|
||||||
|
* `{ tmp = *atomic; *atomic = val; return tmp; }`.
|
||||||
|
*
|
||||||
|
* This call acts as a full compiler and hardware memory barrier.
|
||||||
|
*
|
||||||
|
* Returns: the value of @atomic before the exchange, signed
|
||||||
|
*
|
||||||
|
* Since: 2.74
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
(g_atomic_int_exchange) (gint *atomic,
|
||||||
|
gint newval)
|
||||||
|
{
|
||||||
|
return g_atomic_int_exchange (atomic, newval);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_atomic_int_add:
|
* g_atomic_int_add:
|
||||||
* @atomic: a pointer to a #gint or #guint
|
* @atomic: a pointer to a #gint or #guint
|
||||||
@ -405,6 +430,31 @@ gboolean
|
|||||||
oldval, newval);
|
oldval, newval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_atomic_pointer_exchange:
|
||||||
|
* @atomic: a pointer to a #gint or #guint
|
||||||
|
* @newval: the value to replace with
|
||||||
|
*
|
||||||
|
* Sets the @atomic to @newval and returns the old value from @atomic.
|
||||||
|
*
|
||||||
|
* This exchange is done atomically.
|
||||||
|
*
|
||||||
|
* Think of this operation as an atomic version of
|
||||||
|
* `{ tmp = *atomic; *atomic = val; return tmp; }`.
|
||||||
|
*
|
||||||
|
* This call acts as a full compiler and hardware memory barrier.
|
||||||
|
*
|
||||||
|
* Returns: the value of @atomic before the exchange, signed
|
||||||
|
*
|
||||||
|
* Since: 2.74
|
||||||
|
**/
|
||||||
|
gpointer
|
||||||
|
(g_atomic_pointer_exchange) (void *atomic,
|
||||||
|
gpointer newval)
|
||||||
|
{
|
||||||
|
return g_atomic_pointer_exchange ((gpointer *) atomic, newval);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_atomic_pointer_add:
|
* g_atomic_pointer_add:
|
||||||
* @atomic: (not nullable): a pointer to a #gpointer-sized value
|
* @atomic: (not nullable): a pointer to a #gpointer-sized value
|
||||||
@ -609,6 +659,13 @@ gboolean
|
|||||||
return InterlockedCompareExchange (atomic, newval, oldval) == oldval;
|
return InterlockedCompareExchange (atomic, newval, oldval) == oldval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
(g_atomic_int_exchange) (gint *atomic,
|
||||||
|
gint newval)
|
||||||
|
{
|
||||||
|
return InterlockedExchange (atomic, newval);
|
||||||
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
(g_atomic_int_add) (volatile gint *atomic,
|
(g_atomic_int_add) (volatile gint *atomic,
|
||||||
gint val)
|
gint val)
|
||||||
@ -665,6 +722,13 @@ gboolean
|
|||||||
return InterlockedCompareExchangePointer (atomic, newval, oldval) == oldval;
|
return InterlockedCompareExchangePointer (atomic, newval, oldval) == oldval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
(g_atomic_pointer_exchange) (void *atomic,
|
||||||
|
gpointer newval)
|
||||||
|
{
|
||||||
|
return InterlockedExchangePointer (atomic, newval);
|
||||||
|
}
|
||||||
|
|
||||||
gssize
|
gssize
|
||||||
(g_atomic_pointer_add) (volatile void *atomic,
|
(g_atomic_pointer_add) (volatile void *atomic,
|
||||||
gssize val)
|
gssize val)
|
||||||
@ -787,6 +851,21 @@ gboolean
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
(g_atomic_int_exchange) (gint *atomic,
|
||||||
|
gint newval)
|
||||||
|
{
|
||||||
|
gint *ptr = atomic;
|
||||||
|
gint oldval;
|
||||||
|
|
||||||
|
pthread_mutex_lock (&g_atomic_lock);
|
||||||
|
oldval = *ptr;
|
||||||
|
*ptr = newval;
|
||||||
|
pthread_mutex_unlock (&g_atomic_lock);
|
||||||
|
|
||||||
|
return oldval;
|
||||||
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
(g_atomic_int_add) (volatile gint *atomic,
|
(g_atomic_int_add) (volatile gint *atomic,
|
||||||
gint val)
|
gint val)
|
||||||
@ -886,6 +965,21 @@ gboolean
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
(g_atomic_pointer_exchange) (void *atomic,
|
||||||
|
gpointer newval)
|
||||||
|
{
|
||||||
|
gpointer *ptr = atomic;
|
||||||
|
gpointer oldval;
|
||||||
|
|
||||||
|
pthread_mutex_lock (&g_atomic_lock);
|
||||||
|
oldval = *ptr;
|
||||||
|
*ptr = newval;
|
||||||
|
pthread_mutex_unlock (&g_atomic_lock);
|
||||||
|
|
||||||
|
return oldval;
|
||||||
|
}
|
||||||
|
|
||||||
gssize
|
gssize
|
||||||
(g_atomic_pointer_add) (volatile void *atomic,
|
(g_atomic_pointer_add) (volatile void *atomic,
|
||||||
gssize val)
|
gssize val)
|
||||||
|
@ -44,6 +44,9 @@ GLIB_AVAILABLE_IN_ALL
|
|||||||
gboolean g_atomic_int_compare_and_exchange (volatile gint *atomic,
|
gboolean g_atomic_int_compare_and_exchange (volatile gint *atomic,
|
||||||
gint oldval,
|
gint oldval,
|
||||||
gint newval);
|
gint newval);
|
||||||
|
GLIB_AVAILABLE_IN_2_74
|
||||||
|
gint g_atomic_int_exchange (gint *atomic,
|
||||||
|
gint newval);
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
gint g_atomic_int_add (volatile gint *atomic,
|
gint g_atomic_int_add (volatile gint *atomic,
|
||||||
gint val);
|
gint val);
|
||||||
@ -66,6 +69,9 @@ GLIB_AVAILABLE_IN_ALL
|
|||||||
gboolean g_atomic_pointer_compare_and_exchange (volatile void *atomic,
|
gboolean g_atomic_pointer_compare_and_exchange (volatile void *atomic,
|
||||||
gpointer oldval,
|
gpointer oldval,
|
||||||
gpointer newval);
|
gpointer newval);
|
||||||
|
GLIB_AVAILABLE_IN_2_74
|
||||||
|
gpointer g_atomic_pointer_exchange (void *atomic,
|
||||||
|
gpointer newval);
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
gssize g_atomic_pointer_add (volatile void *atomic,
|
gssize g_atomic_pointer_add (volatile void *atomic,
|
||||||
gssize val);
|
gssize val);
|
||||||
@ -173,6 +179,12 @@ G_END_DECLS
|
|||||||
__atomic_compare_exchange_n ((atomic), (void *) (&(gaicae_oldval)), (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
|
__atomic_compare_exchange_n ((atomic), (void *) (&(gaicae_oldval)), (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
|
||||||
}))
|
}))
|
||||||
#endif /* defined(glib_typeof) */
|
#endif /* defined(glib_typeof) */
|
||||||
|
#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) \
|
#define g_atomic_int_add(atomic, val) \
|
||||||
(G_GNUC_EXTENSION ({ \
|
(G_GNUC_EXTENSION ({ \
|
||||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||||
@ -225,6 +237,12 @@ G_END_DECLS
|
|||||||
__atomic_compare_exchange_n ((atomic), (void *) (&(gapcae_oldval)), (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
|
__atomic_compare_exchange_n ((atomic), (void *) (&(gapcae_oldval)), (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
|
||||||
}))
|
}))
|
||||||
#endif /* defined(glib_typeof) */
|
#endif /* defined(glib_typeof) */
|
||||||
|
#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) \
|
#define g_atomic_pointer_add(atomic, val) \
|
||||||
(G_GNUC_EXTENSION ({ \
|
(G_GNUC_EXTENSION ({ \
|
||||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||||
@ -355,6 +373,26 @@ G_END_DECLS
|
|||||||
(void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 1); \
|
(void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 1); \
|
||||||
__sync_bool_compare_and_swap ((atomic), (oldval), (newval)) ? TRUE : FALSE; \
|
__sync_bool_compare_and_swap ((atomic), (oldval), (newval)) ? TRUE : FALSE; \
|
||||||
}))
|
}))
|
||||||
|
#if defined(__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(__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(__GCC_HAVE_SYNC_SWAP) */
|
||||||
#define g_atomic_int_add(atomic, val) \
|
#define g_atomic_int_add(atomic, val) \
|
||||||
(G_GNUC_EXTENSION ({ \
|
(G_GNUC_EXTENSION ({ \
|
||||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||||
@ -386,6 +424,26 @@ G_END_DECLS
|
|||||||
(void) (0 ? (gpointer) *(atomic) : NULL); \
|
(void) (0 ? (gpointer) *(atomic) : NULL); \
|
||||||
__sync_bool_compare_and_swap ((atomic), (oldval), (newval)) ? TRUE : FALSE; \
|
__sync_bool_compare_and_swap ((atomic), (oldval), (newval)) ? TRUE : FALSE; \
|
||||||
}))
|
}))
|
||||||
|
#if defined(__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(__GCC_HAVE_SYNC_SWAP) */
|
||||||
#define g_atomic_pointer_add(atomic, val) \
|
#define g_atomic_pointer_add(atomic, val) \
|
||||||
(G_GNUC_EXTENSION ({ \
|
(G_GNUC_EXTENSION ({ \
|
||||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||||
@ -425,6 +483,8 @@ G_END_DECLS
|
|||||||
(g_atomic_int_set ((gint *) (atomic), (gint) (newval)))
|
(g_atomic_int_set ((gint *) (atomic), (gint) (newval)))
|
||||||
#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
|
#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
|
||||||
(g_atomic_int_compare_and_exchange ((gint *) (atomic), (oldval), (newval)))
|
(g_atomic_int_compare_and_exchange ((gint *) (atomic), (oldval), (newval)))
|
||||||
|
#define g_atomic_int_exchange(atomic, newval) \
|
||||||
|
(g_atomic_int_exchange ((gint *) (atomic), (newval)))
|
||||||
#define g_atomic_int_add(atomic, val) \
|
#define g_atomic_int_add(atomic, val) \
|
||||||
(g_atomic_int_add ((gint *) (atomic), (val)))
|
(g_atomic_int_add ((gint *) (atomic), (val)))
|
||||||
#define g_atomic_int_and(atomic, val) \
|
#define g_atomic_int_and(atomic, val) \
|
||||||
@ -458,6 +518,8 @@ G_END_DECLS
|
|||||||
|
|
||||||
#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
|
#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
|
||||||
(g_atomic_pointer_compare_and_exchange ((atomic), (gpointer) (oldval), (gpointer) (newval)))
|
(g_atomic_pointer_compare_and_exchange ((atomic), (gpointer) (oldval), (gpointer) (newval)))
|
||||||
|
#define g_atomic_pointer_exchange(atomic, newval) \
|
||||||
|
(g_atomic_pointer_exchange ((atomic), (gpointer) (newval)))
|
||||||
#define g_atomic_pointer_add(atomic, val) \
|
#define g_atomic_pointer_add(atomic, val) \
|
||||||
(g_atomic_pointer_add ((atomic), (gssize) (val)))
|
(g_atomic_pointer_add ((atomic), (gssize) (val)))
|
||||||
#define g_atomic_pointer_and(atomic, val) \
|
#define g_atomic_pointer_and(atomic, val) \
|
||||||
|
@ -56,6 +56,9 @@ test_types (void)
|
|||||||
u2 = g_atomic_int_xor (&u, 4);
|
u2 = g_atomic_int_xor (&u, 4);
|
||||||
g_assert_cmpint (u2, ==, 12);
|
g_assert_cmpint (u2, ==, 12);
|
||||||
g_assert_cmpint (u, ==, 8);
|
g_assert_cmpint (u, ==, 8);
|
||||||
|
u2 = g_atomic_int_exchange (&u, 55);
|
||||||
|
g_assert_cmpint (u2, ==, 8);
|
||||||
|
g_assert_cmpint (u, ==, 55);
|
||||||
|
|
||||||
g_atomic_int_set (&s, 5);
|
g_atomic_int_set (&s, 5);
|
||||||
s2 = g_atomic_int_get (&s);
|
s2 = g_atomic_int_get (&s);
|
||||||
@ -79,6 +82,9 @@ test_types (void)
|
|||||||
s2 = (gint) g_atomic_int_xor (&s, 4);
|
s2 = (gint) g_atomic_int_xor (&s, 4);
|
||||||
g_assert_cmpint (s2, ==, 12);
|
g_assert_cmpint (s2, ==, 12);
|
||||||
g_assert_cmpint (s, ==, 8);
|
g_assert_cmpint (s, ==, 8);
|
||||||
|
s2 = g_atomic_int_exchange (&s, 55);
|
||||||
|
g_assert_cmpint (s2, ==, 8);
|
||||||
|
g_assert_cmpint (s, ==, 55);
|
||||||
|
|
||||||
g_atomic_pointer_set (&vp, 0);
|
g_atomic_pointer_set (&vp, 0);
|
||||||
vp2 = g_atomic_pointer_get (&vp);
|
vp2 = g_atomic_pointer_get (&vp);
|
||||||
@ -89,10 +95,14 @@ test_types (void)
|
|||||||
res = g_atomic_pointer_compare_and_exchange (&vp, NULL, NULL);
|
res = g_atomic_pointer_compare_and_exchange (&vp, NULL, NULL);
|
||||||
g_assert_true (res);
|
g_assert_true (res);
|
||||||
g_assert_true (vp == 0);
|
g_assert_true (vp == 0);
|
||||||
|
g_assert_null (g_atomic_pointer_exchange (&vp, &s));
|
||||||
|
g_assert_true (vp == &s);
|
||||||
|
|
||||||
g_atomic_pointer_set (&vp_str, NULL);
|
g_atomic_pointer_set (&vp_str, NULL);
|
||||||
res = g_atomic_pointer_compare_and_exchange (&vp_str, NULL, str);
|
res = g_atomic_pointer_compare_and_exchange (&vp_str, NULL, str);
|
||||||
g_assert_true (res);
|
g_assert_true (res);
|
||||||
|
g_assert_cmpstr (g_atomic_pointer_exchange (&vp_str, NULL), ==, str);
|
||||||
|
g_assert_null (vp_str);
|
||||||
|
|
||||||
/* Note that atomic variables should almost certainly not be marked as
|
/* Note that atomic variables should almost certainly not be marked as
|
||||||
* `volatile` — see http://isvolatileusefulwiththreads.in/c/. This test exists
|
* `volatile` — see http://isvolatileusefulwiththreads.in/c/. This test exists
|
||||||
@ -130,6 +140,10 @@ test_types (void)
|
|||||||
gs2 = g_atomic_pointer_xor (&gs, 4);
|
gs2 = g_atomic_pointer_xor (&gs, 4);
|
||||||
g_assert_cmpuint (gs2, ==, 12);
|
g_assert_cmpuint (gs2, ==, 12);
|
||||||
g_assert_cmpuint (gs, ==, 8);
|
g_assert_cmpuint (gs, ==, 8);
|
||||||
|
vp2 = g_atomic_pointer_exchange ((gpointer*) &gs, NULL);
|
||||||
|
gs2 = (gsize) vp2;
|
||||||
|
g_assert_cmpuint (gs2, ==, 8);
|
||||||
|
g_assert_null ((gpointer) gs);
|
||||||
|
|
||||||
g_assert_cmpint (g_atomic_int_get (csp), ==, s);
|
g_assert_cmpint (g_atomic_int_get (csp), ==, s);
|
||||||
g_assert_true (g_atomic_pointer_get ((const gint **) cspp) == csp);
|
g_assert_true (g_atomic_pointer_get ((const gint **) cspp) == csp);
|
||||||
@ -138,6 +152,7 @@ test_types (void)
|
|||||||
#undef g_atomic_int_set
|
#undef g_atomic_int_set
|
||||||
#undef g_atomic_int_get
|
#undef g_atomic_int_get
|
||||||
#undef g_atomic_int_compare_and_exchange
|
#undef g_atomic_int_compare_and_exchange
|
||||||
|
#undef g_atomic_int_exchange
|
||||||
#undef g_atomic_int_add
|
#undef g_atomic_int_add
|
||||||
#undef g_atomic_int_inc
|
#undef g_atomic_int_inc
|
||||||
#undef g_atomic_int_and
|
#undef g_atomic_int_and
|
||||||
@ -147,6 +162,7 @@ test_types (void)
|
|||||||
#undef g_atomic_pointer_set
|
#undef g_atomic_pointer_set
|
||||||
#undef g_atomic_pointer_get
|
#undef g_atomic_pointer_get
|
||||||
#undef g_atomic_pointer_compare_and_exchange
|
#undef g_atomic_pointer_compare_and_exchange
|
||||||
|
#undef g_atomic_pointer_exchange
|
||||||
#undef g_atomic_pointer_add
|
#undef g_atomic_pointer_add
|
||||||
#undef g_atomic_pointer_and
|
#undef g_atomic_pointer_and
|
||||||
#undef g_atomic_pointer_or
|
#undef g_atomic_pointer_or
|
||||||
@ -173,6 +189,9 @@ test_types (void)
|
|||||||
g_assert_cmpint (u, ==, 12);
|
g_assert_cmpint (u, ==, 12);
|
||||||
u2 = g_atomic_int_xor (&u, 4);
|
u2 = g_atomic_int_xor (&u, 4);
|
||||||
g_assert_cmpint (u2, ==, 12);
|
g_assert_cmpint (u2, ==, 12);
|
||||||
|
u2 = g_atomic_int_exchange (&u, 55);
|
||||||
|
g_assert_cmpint (u2, ==, 8);
|
||||||
|
g_assert_cmpint (u, ==, 55);
|
||||||
|
|
||||||
g_atomic_int_set (&s, 5);
|
g_atomic_int_set (&s, 5);
|
||||||
s2 = g_atomic_int_get (&s);
|
s2 = g_atomic_int_get (&s);
|
||||||
@ -201,6 +220,9 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
|||||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||||
g_assert_cmpint (s2, ==, 8);
|
g_assert_cmpint (s2, ==, 8);
|
||||||
g_assert_cmpint (s, ==, 9);
|
g_assert_cmpint (s, ==, 9);
|
||||||
|
s2 = g_atomic_int_exchange (&s, 55);
|
||||||
|
g_assert_cmpint (s2, ==, 9);
|
||||||
|
g_assert_cmpint (s, ==, 55);
|
||||||
|
|
||||||
g_atomic_pointer_set (&vp, 0);
|
g_atomic_pointer_set (&vp, 0);
|
||||||
vp2 = g_atomic_pointer_get (&vp);
|
vp2 = g_atomic_pointer_get (&vp);
|
||||||
@ -211,6 +233,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
|||||||
res = g_atomic_pointer_compare_and_exchange (&vp, NULL, NULL);
|
res = g_atomic_pointer_compare_and_exchange (&vp, NULL, NULL);
|
||||||
g_assert_true (res);
|
g_assert_true (res);
|
||||||
g_assert_true (vp == 0);
|
g_assert_true (vp == 0);
|
||||||
|
g_assert_null (g_atomic_pointer_exchange (&vp, &s));
|
||||||
|
g_assert_true (vp == &s);
|
||||||
|
|
||||||
g_atomic_pointer_set (&vp_str, NULL);
|
g_atomic_pointer_set (&vp_str, NULL);
|
||||||
res = g_atomic_pointer_compare_and_exchange (&vp_str, NULL, (char *) str);
|
res = g_atomic_pointer_compare_and_exchange (&vp_str, NULL, (char *) str);
|
||||||
@ -222,6 +246,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
|||||||
g_atomic_pointer_set (&vp_str_vol, NULL);
|
g_atomic_pointer_set (&vp_str_vol, NULL);
|
||||||
res = g_atomic_pointer_compare_and_exchange (&vp_str_vol, NULL, (char *) str);
|
res = g_atomic_pointer_compare_and_exchange (&vp_str_vol, NULL, (char *) str);
|
||||||
g_assert_true (res);
|
g_assert_true (res);
|
||||||
|
g_assert_cmpstr (g_atomic_pointer_exchange (&vp_str, NULL), ==, str);
|
||||||
|
g_assert_null (vp_str);
|
||||||
|
|
||||||
g_atomic_pointer_set (&ip, 0);
|
g_atomic_pointer_set (&ip, 0);
|
||||||
ip2 = g_atomic_pointer_get (&ip);
|
ip2 = g_atomic_pointer_get (&ip);
|
||||||
@ -249,6 +275,10 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
|||||||
gs2 = g_atomic_pointer_xor (&gs, 4);
|
gs2 = g_atomic_pointer_xor (&gs, 4);
|
||||||
g_assert_cmpuint (gs2, ==, 12);
|
g_assert_cmpuint (gs2, ==, 12);
|
||||||
g_assert_cmpuint (gs, ==, 8);
|
g_assert_cmpuint (gs, ==, 8);
|
||||||
|
vp2 = g_atomic_pointer_exchange ((gpointer*) &gs, NULL);
|
||||||
|
gs2 = (gsize) vp2;
|
||||||
|
g_assert_cmpuint (gs2, ==, 8);
|
||||||
|
g_assert_null ((gpointer) gs);
|
||||||
|
|
||||||
g_assert_cmpint (g_atomic_int_get (csp), ==, s);
|
g_assert_cmpint (g_atomic_int_get (csp), ==, s);
|
||||||
g_assert_true (g_atomic_pointer_get (cspp) == csp);
|
g_assert_true (g_atomic_pointer_get (cspp) == csp);
|
||||||
|
@ -87,6 +87,39 @@ test_atomic_int_compare_and_exchange (void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_atomic_pointer_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_exchange() with a "
|
||||||
|
"non-void* pointer doesn’t have any compiler warnings in C++ mode");
|
||||||
|
|
||||||
|
g_assert_true (g_atomic_pointer_exchange (&atomic_string, str2) == str1);
|
||||||
|
g_assert_true (atomic_string == str2);
|
||||||
|
#else
|
||||||
|
g_test_skip ("This test requires a C++11 compiler");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_atomic_int_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_cmpint (g_atomic_int_exchange (&atomic_int, 50), ==, 5);
|
||||||
|
#else
|
||||||
|
g_test_skip ("This test requires a C++11 compiler");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -99,6 +132,8 @@ main (int argc, char *argv[])
|
|||||||
g_test_add_func ("/C++/typeof", test_typeof);
|
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-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);
|
g_test_add_func ("/C++/atomic-int-compare-and-exchange", test_atomic_int_compare_and_exchange);
|
||||||
|
g_test_add_func ("/C++/atomic-pointer-exchange", test_atomic_pointer_exchange);
|
||||||
|
g_test_add_func ("/C++/atomic-int-exchange", test_atomic_int_exchange);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
12
meson.build
12
meson.build
@ -1840,6 +1840,18 @@ if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl' or cc.links(atomictest, na
|
|||||||
# __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
|
# __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
|
||||||
glib_conf.set('__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4', true)
|
glib_conf.set('__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4', true)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if cc.get_id() == 'gcc' or cc.get_id() == 'clang'
|
||||||
|
sync_swap_test = '''
|
||||||
|
int main() {
|
||||||
|
int atomic = 2;
|
||||||
|
__sync_swap (&atomic, 2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
glib_conf.set('__GCC_HAVE_SYNC_SWAP', cc.links(sync_swap_test, name : 'sync swap'))
|
||||||
|
endif
|
||||||
else
|
else
|
||||||
have_atomic_lock_free = false
|
have_atomic_lock_free = false
|
||||||
if host_machine.cpu_family() == 'x86' and cc.links(atomictest, args : '-march=i486')
|
if host_machine.cpu_family() == 'x86' and cc.links(atomictest, args : '-march=i486')
|
||||||
|
Loading…
Reference in New Issue
Block a user