summaryrefslogtreecommitdiff
path: root/glib/gatomic.c
diff options
context:
space:
mode:
Diffstat (limited to 'glib/gatomic.c')
-rw-r--r--glib/gatomic.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/glib/gatomic.c b/glib/gatomic.c
index b317601b5..6c1ea768e 100644
--- a/glib/gatomic.c
+++ b/glib/gatomic.c
@@ -219,6 +219,64 @@ gboolean
}
/**
+ * g_atomic_int_compare_and_exchange_full:
+ * @atomic: a pointer to a #gint or #guint
+ * @oldval: the value to compare with
+ * @newval: the value to conditionally replace with
+ * @preval: (out): the contents of @atomic before this operation
+ *
+ * Compares @atomic to @oldval and, if equal, sets it to @newval.
+ * If @atomic was not equal to @oldval then no change occurs.
+ * In any case the value of @atomic before this operation is stored in @preval.
+ *
+ * This compare and exchange is done atomically.
+ *
+ * Think of this operation as an atomic version of
+ * `{ *preval = *atomic; if (*atomic == oldval) { *atomic = newval; return TRUE; } else return FALSE; }`.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * See also g_atomic_int_compare_and_exchange()
+ *
+ * Returns: %TRUE if the exchange took place
+ *
+ * Since: 2.74
+ **/
+gboolean
+(g_atomic_int_compare_and_exchange_full) (gint *atomic,
+ gint oldval,
+ gint newval,
+ gint *preval)
+{
+ return g_atomic_int_compare_and_exchange_full (atomic, oldval, newval, preval);
+}
+
+/**
+ * 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:
* @atomic: a pointer to a #gint or #guint
* @val: the value to add
@@ -405,6 +463,66 @@ gboolean
oldval, newval);
}
+ /**
+ * g_atomic_pointer_compare_and_exchange_full:
+ * @atomic: (not nullable): a pointer to a #gpointer-sized value
+ * @oldval: the value to compare with
+ * @newval: the value to conditionally replace with
+ * @preval: (not nullable) (out): the contents of @atomic before this operation
+ *
+ * Compares @atomic to @oldval and, if equal, sets it to @newval.
+ * If @atomic was not equal to @oldval then no change occurs.
+ * In any case the value of @atomic before this operation is stored in @preval.
+ *
+ * This compare and exchange is done atomically.
+ *
+ * Think of this operation as an atomic version of
+ * `{ *preval = *atomic; if (*atomic == oldval) { *atomic = newval; return TRUE; } else return FALSE; }`.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * See also g_atomic_pointer_compare_and_exchange()
+ *
+ * Returns: %TRUE if the exchange took place
+ *
+ * Since: 2.74
+ **/
+gboolean
+(g_atomic_pointer_compare_and_exchange_full) (void *atomic,
+ gpointer oldval,
+ gpointer newval,
+ void *preval)
+{
+ return g_atomic_pointer_compare_and_exchange_full ((gpointer *) atomic,
+ oldval, newval,
+ (gpointer *) preval);
+}
+
+/**
+ * g_atomic_pointer_exchange:
+ * @atomic: a pointer to a #gpointer-sized value
+ * @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
+ *
+ * Since: 2.74
+ **/
+gpointer
+(g_atomic_pointer_exchange) (void *atomic,
+ gpointer newval)
+{
+ return g_atomic_pointer_exchange ((gpointer *) atomic, newval);
+}
+
/**
* g_atomic_pointer_add:
* @atomic: (not nullable): a pointer to a #gpointer-sized value
@@ -609,6 +727,23 @@ gboolean
return InterlockedCompareExchange (atomic, newval, oldval) == oldval;
}
+gboolean
+(g_atomic_int_compare_and_exchange_full) (gint *atomic,
+ gint oldval,
+ gint newval,
+ gint *preval)
+{
+ *preval = InterlockedCompareExchange (atomic, newval, oldval);
+ return *preval == oldval;
+}
+
+gint
+(g_atomic_int_exchange) (gint *atomic,
+ gint newval)
+{
+ return InterlockedExchange (atomic, newval);
+}
+
gint
(g_atomic_int_add) (volatile gint *atomic,
gint val)
@@ -665,6 +800,26 @@ gboolean
return InterlockedCompareExchangePointer (atomic, newval, oldval) == oldval;
}
+gboolean
+(g_atomic_pointer_compare_and_exchange_full) (void *atomic,
+ gpointer oldval,
+ gpointer newval,
+ void *preval)
+{
+ gpointer *pre = preval;
+
+ *pre = InterlockedCompareExchangePointer (atomic, newval, oldval);
+
+ return *pre == oldval;
+}
+
+gpointer
+(g_atomic_pointer_exchange) (void *atomic,
+ gpointer newval)
+{
+ return InterlockedExchangePointer (atomic, newval);
+}
+
gssize
(g_atomic_pointer_add) (volatile void *atomic,
gssize val)
@@ -787,6 +942,41 @@ gboolean
return success;
}
+gboolean
+(g_atomic_int_compare_and_exchange_full) (gint *atomic,
+ gint oldval,
+ gint newval,
+ gint *preval)
+{
+ gboolean success;
+
+ pthread_mutex_lock (&g_atomic_lock);
+
+ *preval = *atomic;
+
+ if ((success = (*atomic == oldval)))
+ *atomic = newval;
+
+ pthread_mutex_unlock (&g_atomic_lock);
+
+ 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
(g_atomic_int_add) (volatile gint *atomic,
gint val)
@@ -886,6 +1076,42 @@ gboolean
return success;
}
+gboolean
+(g_atomic_pointer_compare_and_exchange_full) (void *atomic,
+ gpointer oldval,
+ gpointer newval,
+ void *preval)
+{
+ gpointer *ptr = atomic;
+ gpointer *pre = preval;
+ gboolean success;
+
+ pthread_mutex_lock (&g_atomic_lock);
+
+ *pre = *ptr;
+ if ((success = (*ptr == oldval)))
+ *ptr = newval;
+
+ pthread_mutex_unlock (&g_atomic_lock);
+
+ 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
(g_atomic_pointer_add) (volatile void *atomic,
gssize val)