mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 11:26:16 +01:00
Move docs for atomic operations inline
This commit is contained in:
parent
e8503fddee
commit
e57291efdc
@ -2,64 +2,16 @@
|
||||
Atomic Operations
|
||||
|
||||
<!-- ##### SECTION Short_Description ##### -->
|
||||
basic atomic integer and pointer operations
|
||||
|
||||
|
||||
<!-- ##### SECTION Long_Description ##### -->
|
||||
<para>
|
||||
The following functions can be used to atomically access integers and
|
||||
pointers. They are implemented as inline assembler function on most
|
||||
platforms and use slower fall-backs otherwise. Using them can sometimes
|
||||
save you from using a performance-expensive #GMutex to protect the
|
||||
integer or pointer.
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The most important usage is reference counting. Using
|
||||
g_atomic_int_inc() and g_atomic_int_dec_and_test() makes reference
|
||||
counting a very fast operation.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
You must not directly read integers or pointers concurrently accessed
|
||||
by multiple threads, but use the atomic accessor functions instead.
|
||||
That is, always use g_atomic_int_get() and g_atomic_pointer_get() for
|
||||
read outs.
|
||||
They provide the neccessary synchonization mechanisms like memory
|
||||
barriers to access memory locations concurrently.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
If you are using those functions for anything apart from simple
|
||||
reference counting, you should really be aware of the implications of
|
||||
doing that. There are literally thousands of ways to shoot yourself in
|
||||
the foot. So if in doubt, use a #GMutex. If you don't know, what
|
||||
memory barriers are, do not use anything but g_atomic_int_inc() and
|
||||
g_atomic_int_dec_and_test().
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
It is not safe to set an integer or pointer just by assigning to it,
|
||||
when it is concurrently accessed by other threads with the following
|
||||
functions. Use g_atomic_int_compare_and_exchange() or
|
||||
g_atomic_pointer_compare_and_exchange() respectively.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<!-- ##### SECTION See_Also ##### -->
|
||||
<para>
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term>#GMutex</term>
|
||||
<listitem><para>GLib mutual exclusions.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### SECTION Stability_Level ##### -->
|
||||
@ -70,117 +22,89 @@ g_atomic_pointer_compare_and_exchange() respectively.
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_int_get ##### -->
|
||||
<para>
|
||||
Reads the value of the integer pointed to by @atomic. Also acts as
|
||||
a memory barrier.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to an integer
|
||||
@Returns: the value of *@atomic
|
||||
@Since: 2.4
|
||||
@atomic:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_int_set ##### -->
|
||||
<para>
|
||||
Sets the value of the integer pointed to by @atomic.
|
||||
Also acts as a memory barrier.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to an integer
|
||||
@newval: the new value
|
||||
@Since: 2.10
|
||||
@atomic:
|
||||
@newval:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_int_add ##### -->
|
||||
<para>
|
||||
Atomically adds @val to the integer pointed to by @atomic.
|
||||
Also acts as a memory barrier.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to an integer.
|
||||
@val: the value to add to *@atomic.
|
||||
@Since: 2.4
|
||||
@atomic:
|
||||
@val:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_int_exchange_and_add ##### -->
|
||||
<para>
|
||||
Atomically adds @val to the integer pointed to by @atomic. It returns
|
||||
the value of *@atomic just before the addition took place.
|
||||
Also acts as a memory barrier.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to an integer.
|
||||
@val: the value to add to *@atomic.
|
||||
@Returns: the value of *@atomic before the addition.
|
||||
@Since: 2.4
|
||||
@atomic:
|
||||
@val:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_int_compare_and_exchange ##### -->
|
||||
<para>
|
||||
Compares @oldval with the integer pointed to by @atomic and
|
||||
if they are equal, atomically exchanges *@atomic with @newval.
|
||||
Also acts as a memory barrier.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to an integer.
|
||||
@oldval: the assumed old value of *@atomic.
|
||||
@newval: the new value of *@atomic.
|
||||
@Returns: %TRUE, if *@atomic was equal @oldval. %FALSE otherwise.
|
||||
@Since: 2.4
|
||||
@atomic:
|
||||
@oldval:
|
||||
@newval:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_pointer_get ##### -->
|
||||
<para>
|
||||
Reads the value of the pointer pointed to by @atomic. Also acts as
|
||||
a memory barrier.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to a #gpointer.
|
||||
@Returns: the value to add to *@atomic.
|
||||
@Since: 2.4
|
||||
@atomic:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_pointer_set ##### -->
|
||||
<para>
|
||||
Sets the value of the pointer pointed to by @atomic.
|
||||
Also acts as a memory barrier.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to a #gpointer
|
||||
@newval: the new value
|
||||
@Since: 2.10
|
||||
@atomic:
|
||||
@newval:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_pointer_compare_and_exchange ##### -->
|
||||
<para>
|
||||
Compares @oldval with the pointer pointed to by @atomic and
|
||||
if they are equal, atomically exchanges *@atomic with @newval.
|
||||
Also acts as a memory barrier.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to a #gpointer.
|
||||
@oldval: the assumed old value of *@atomic.
|
||||
@newval: the new value of *@atomic.
|
||||
@Returns: %TRUE, if *@atomic was equal @oldval. %FALSE otherwise.
|
||||
@Since: 2.4
|
||||
@atomic:
|
||||
@oldval:
|
||||
@newval:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_int_inc ##### -->
|
||||
<para>
|
||||
Atomically increments the integer pointed to by @atomic by 1.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to an integer.
|
||||
@Since: 2.4
|
||||
@atomic:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_atomic_int_dec_and_test ##### -->
|
||||
<para>
|
||||
Atomically decrements the integer pointed to by @atomic by 1.
|
||||
|
||||
</para>
|
||||
|
||||
@atomic: a pointer to an integer.
|
||||
@Returns: %TRUE, if the integer pointed to by @atomic is 0 after
|
||||
decrementing it.
|
||||
@Since: 2.4
|
||||
@atomic:
|
||||
|
||||
|
||||
|
133
glib/gatomic.c
133
glib/gatomic.c
@ -30,6 +30,44 @@
|
||||
#include "glib.h"
|
||||
#include "gthreadprivate.h"
|
||||
|
||||
/**
|
||||
* SECTION:atomic_operations
|
||||
* @title: Atomic Operations
|
||||
* @shot_description: basic atomic integer and pointer operations
|
||||
* @see_also: #GMutex
|
||||
*
|
||||
* The following functions can be used to atomically access integers and
|
||||
* pointers. They are implemented as inline assembler function on most
|
||||
* platforms and use slower fall-backs otherwise. Using them can sometimes
|
||||
* save you from using a performance-expensive #GMutex to protect the
|
||||
* integer or pointer.
|
||||
*
|
||||
* The most important usage is reference counting. Using
|
||||
* g_atomic_int_inc() and g_atomic_int_dec_and_test() makes reference
|
||||
* counting a very fast operation.
|
||||
*
|
||||
* <note><para>You must not directly read integers or pointers concurrently
|
||||
* accessed by multiple threads, but use the atomic accessor functions
|
||||
* instead. That is, always use g_atomic_int_get() and g_atomic_pointer_get()
|
||||
* for read outs. They provide the neccessary synchonization mechanisms
|
||||
* like memory barriers to access memory locations concurrently.
|
||||
* </para></note>
|
||||
*
|
||||
* <note><para>If you are using those functions for anything apart from
|
||||
* simple reference counting, you should really be aware of the implications
|
||||
* of doing that. There are literally thousands of ways to shoot yourself
|
||||
* in the foot. So if in doubt, use a #GMutex. If you don't know, what
|
||||
* memory barriers are, do not use anything but g_atomic_int_inc() and
|
||||
* g_atomic_int_dec_and_test().
|
||||
* </para></note>
|
||||
*
|
||||
* <note><para>It is not safe to set an integer or pointer just by assigning
|
||||
* to it, when it is concurrently accessed by other threads with the following
|
||||
* functions. Use g_atomic_int_compare_and_exchange() or
|
||||
* g_atomic_pointer_compare_and_exchange() respectively.
|
||||
* </para></note>
|
||||
*/
|
||||
|
||||
#if defined (__GNUC__)
|
||||
# if defined (G_ATOMIC_I486)
|
||||
/* Adapted from CVS version 1.10 of glibc's sysdeps/i386/i486/bits/atomic.h
|
||||
@ -846,6 +884,19 @@ g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomi
|
||||
/* We have to use the slow, but safe locking method */
|
||||
static GMutex *g_atomic_mutex;
|
||||
|
||||
/**
|
||||
* g_atomic_int_exchange_and_add:
|
||||
* @atomic: a pointer to an integer
|
||||
* @val: the value to add to *@atomic
|
||||
*
|
||||
* Atomically adds @val to the integer pointed to by @atomic.
|
||||
* It returns the value of *@atomic just before the addition
|
||||
* took place. Also acts as a memory barrier.
|
||||
*
|
||||
* Returns: the value of *@atomic before the addition.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
gint
|
||||
g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
|
||||
gint val)
|
||||
@ -860,7 +911,16 @@ g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* g_atomic_int_add:
|
||||
* @atomic: a pointer to an integer
|
||||
* @val: the value to add to *@atomic
|
||||
*
|
||||
* Atomically adds @val to the integer pointed to by @atomic.
|
||||
* Also acts as a memory barrier.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
void
|
||||
g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
|
||||
gint val)
|
||||
@ -870,6 +930,20 @@ g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
|
||||
g_mutex_unlock (g_atomic_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_compare_and_exchange:
|
||||
* @atomic: a pointer to an integer
|
||||
* @oldval: the assumed old value of *@atomic
|
||||
* @newval: the new value of *@atomic
|
||||
*
|
||||
* Compares @oldval with the integer pointed to by @atomic and
|
||||
* if they are equal, atomically exchanges *@atomic with @newval.
|
||||
* Also acts as a memory barrier.
|
||||
*
|
||||
* Returns: %TRUE, if *@atomic was equal @oldval. %FALSE otherwise.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
gboolean
|
||||
g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic,
|
||||
gint oldval,
|
||||
@ -890,6 +964,20 @@ g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic,
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_compare_and_exchange:
|
||||
* @atomic: a pointer to a #gpointer
|
||||
* @oldval: the assumed old value of *@atomic
|
||||
* @newval: the new value of *@atomic
|
||||
*
|
||||
* Compares @oldval with the pointer pointed to by @atomic and
|
||||
* if they are equal, atomically exchanges *@atomic with @newval.
|
||||
* Also acts as a memory barrier.
|
||||
*
|
||||
* Returns: %TRUE, if *@atomic was equal @oldval. %FALSE otherwise.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
gboolean
|
||||
g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
|
||||
gpointer oldval,
|
||||
@ -911,6 +999,18 @@ g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomi
|
||||
}
|
||||
|
||||
#ifdef G_ATOMIC_OP_MEMORY_BARRIER_NEEDED
|
||||
|
||||
/**
|
||||
* g_atomic_int_get:
|
||||
* @atomic: a pointer to an integer
|
||||
*
|
||||
* Reads the value of the integer pointed to by @atomic.
|
||||
* Also acts as a memory barrier.
|
||||
*
|
||||
* Returns: the value of *@atomic
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
gint
|
||||
(g_atomic_int_get) (volatile gint G_GNUC_MAY_ALIAS *atomic)
|
||||
{
|
||||
@ -923,6 +1023,16 @@ gint
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_set:
|
||||
* @atomic: a pointer to an integer
|
||||
* @newval: the new value
|
||||
*
|
||||
* Sets the value of the integer pointed to by @atomic.
|
||||
* Also acts as a memory barrier.
|
||||
*
|
||||
* Since: 2.10
|
||||
*/
|
||||
void
|
||||
(g_atomic_int_set) (volatile gint G_GNUC_MAY_ALIAS *atomic,
|
||||
gint newval)
|
||||
@ -932,6 +1042,17 @@ void
|
||||
g_mutex_unlock (g_atomic_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_get:
|
||||
* @atomic: a pointer to a #gpointer.
|
||||
*
|
||||
* Reads the value of the pointer pointed to by @atomic.
|
||||
* Also acts as a memory barrier.
|
||||
*
|
||||
* Returns: the value to add to *@atomic.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
gpointer
|
||||
(g_atomic_pointer_get) (volatile gpointer G_GNUC_MAY_ALIAS *atomic)
|
||||
{
|
||||
@ -944,6 +1065,16 @@ gpointer
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_set:
|
||||
* @atomic: a pointer to a #gpointer
|
||||
* @newval: the new value
|
||||
*
|
||||
* Sets the value of the pointer pointed to by @atomic.
|
||||
* Also acts as a memory barrier.
|
||||
*
|
||||
* Since: 2.10
|
||||
*/
|
||||
void
|
||||
(g_atomic_pointer_set) (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
|
||||
gpointer newval)
|
||||
|
@ -76,8 +76,28 @@ void g_atomic_pointer_set (volatile gpointer G_GNUC_MAY_ALI
|
||||
(g_atomic_pointer_set) ((volatile gpointer G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval)))
|
||||
#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
|
||||
|
||||
/**
|
||||
* g_atomic_int_inc:
|
||||
* @atomic: a pointer to an integer.
|
||||
*
|
||||
* Atomically increments the integer pointed to by @atomic by 1.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
#define g_atomic_int_inc(atomic) (g_atomic_int_add ((atomic), 1))
|
||||
#define g_atomic_int_dec_and_test(atomic) \
|
||||
|
||||
/**
|
||||
* g_atomic_int_dec_and_test:
|
||||
* @atomic: a pointer to an integer
|
||||
*
|
||||
* Atomically decrements the integer pointed to by @atomic by 1.
|
||||
*
|
||||
* Returns: %TRUE if the integer pointed to by @atomic is 0
|
||||
* after decrementing it
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
#define g_atomic_int_dec_and_test(atomic) \
|
||||
(g_atomic_int_exchange_and_add ((atomic), -1) == 1)
|
||||
|
||||
G_END_DECLS
|
||||
|
Loading…
Reference in New Issue
Block a user