plibsys
Functions
patomic.h File Reference

Atomic operations. More...

#include <ptypes.h>
#include <pmacros.h>
Include dependency graph for patomic.h:

Go to the source code of this file.

Functions

P_BEGIN_DECLS P_LIB_API pint p_atomic_int_get (const volatile pint *atomic)
 Gets pint value from atomic. More...
 
P_LIB_API void p_atomic_int_set (volatile pint *atomic, pint val)
 Sets pint value to atomic. More...
 
P_LIB_API void p_atomic_int_inc (volatile pint *atomic)
 Increments pint value from atomic by 1. More...
 
P_LIB_API pboolean p_atomic_int_dec_and_test (volatile pint *atomic)
 Decrements pint value from atomic by 1 and tests the result for zero. More...
 
P_LIB_API pboolean p_atomic_int_compare_and_exchange (volatile pint *atomic, pint oldval, pint newval)
 Compares oldval with the value pointed to by atomic and if they are equal, atomically exchanges the value of atomic with newval. More...
 
P_LIB_API pint p_atomic_int_add (volatile pint *atomic, pint val)
 Atomically adds pint value to atomic value. More...
 
P_LIB_API puint p_atomic_int_and (volatile puint *atomic, puint val)
 Atomically performs the bitwise 'and' operation of atomic value and val storing the result back in atomic. More...
 
P_LIB_API puint p_atomic_int_or (volatile puint *atomic, puint val)
 Atomically performs the bitwise 'or' operation of atomic value and val storing the result back in atomic. More...
 
P_LIB_API puint p_atomic_int_xor (volatile puint *atomic, puint val)
 Atomically performs the bitwise 'xor' operation of atomic value and val storing the result back in atomic. More...
 
P_LIB_API ppointer p_atomic_pointer_get (const volatile void *atomic)
 Gets ppointer-sized value from atomic. More...
 
P_LIB_API void p_atomic_pointer_set (volatile void *atomic, ppointer val)
 Sets val to ppointer-sized atomic. More...
 
P_LIB_API pboolean p_atomic_pointer_compare_and_exchange (volatile void *atomic, ppointer oldval, ppointer newval)
 Compares oldval with the value pointed to by atomic and if they are equal, atomically exchanges the value of atomic with newval. More...
 
P_LIB_API pssize p_atomic_pointer_add (volatile void *atomic, pssize val)
 Atomically adds ppointer-sized value to atomic value. More...
 
P_LIB_API psize p_atomic_pointer_and (volatile void *atomic, psize val)
 Atomically performs the bitwise 'and' operation of ppointer-sized atomic value and val storing the result back in atomic. More...
 
P_LIB_API psize p_atomic_pointer_or (volatile void *atomic, psize val)
 Atomically performs the bitwise 'or' operation of ppointer-sized atomic value and val storing the result back in atomic. More...
 
P_LIB_API psize p_atomic_pointer_xor (volatile void *atomic, psize val)
 Atomically performs the bitwise 'xor' operation of ppointer-sized atomic value and val storing the result back in atomic. More...
 
P_LIB_API pboolean p_atomic_is_lock_free (void)
 Checks whether atomic operations are lock-free. More...
 

Detailed Description

Atomic operations.

Author
Alexander Saprykin

Atomic operations can be used to avoid heavy thread synchronization primitives such as mutexes, semaphores and so on. These operations are performed atomically and can't be preempted by another thread.

Lock-free atomic operations require software and hardware support. Usually lock-free atomic operations are implemented with low-level using assembly inlines. Some of the compilers provide built-in routines to perform atomic operations. You can use the p_atomic_is_lock_free() call to check whether such a support is provided or not.

If there is no hardware or software support for lock-free atomic operations then they can be simulated (though in rather slower manner) using a thread global synchronization primitive (i.e. mutex), but it could block threads while performing atomic operations on distinct variables from distinct threads.

The Windows platform provides all the required lock-free operations in most cases, so it always has lock-free support.

Function Documentation

◆ p_atomic_int_add()

P_LIB_API pint p_atomic_int_add ( volatile pint atomic,
pint  val 
)

Atomically adds pint value to atomic value.

Parameters
[in,out]atomicPointer to pint.
valInteger to add to atomic value.
Returns
Old value before the addition.
Since
0.0.1

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.

◆ p_atomic_int_and()

P_LIB_API puint p_atomic_int_and ( volatile puint atomic,
puint  val 
)

Atomically performs the bitwise 'and' operation of atomic value and val storing the result back in atomic.

Parameters
[in,out]atomicPointer to puint.
valpuint to perform bitwise 'and' with atomic value.
Returns
Old atomic value before the operation.
Since
0.0.1

This call acts as a full compiler and hardware memory barrier.

Think of this operation as an atomic version of { tmp = *atomic; *atomic &= val; return tmp; }.

◆ p_atomic_int_compare_and_exchange()

P_LIB_API pboolean p_atomic_int_compare_and_exchange ( volatile pint atomic,
pint  oldval,
pint  newval 
)

Compares oldval with the value pointed to by atomic and if they are equal, atomically exchanges the value of atomic with newval.

Parameters
[in,out]atomicPointer to pint.
oldvalOld pint value.
newvalNew pint value.
Returns
TRUE if atomic value was equal oldval, FALSE otherwise.
Since
0.0.1

This compare and exchange is done atomically.

Think of this operation as an atomic version of { if (*atomic == oldval) { *atomic = newval; return TRUE; } else return FALSE; }.

This call acts as a full compiler and hardware memory barrier.

◆ p_atomic_int_dec_and_test()

P_LIB_API pboolean p_atomic_int_dec_and_test ( volatile pint atomic)

Decrements pint value from atomic by 1 and tests the result for zero.

Parameters
[in,out]atomicPointer to pint to decrement the value.
Returns
TRUE if the new value is equal to zero, FALSE otherwise.
Since
0.0.1

Think of this operation as an atomic version of { *atomic -= 1; return (*atomic == 0); }.

This call acts as a full compiler and hardware memory barrier.

◆ p_atomic_int_get()

P_BEGIN_DECLS P_LIB_API pint p_atomic_int_get ( const volatile pint atomic)

Gets pint value from atomic.

Parameters
atomicPointer to pint to get the value from.
Returns
Integer value.
Since
0.0.1

This call acts as a full compiler and hardware memory barrier (before the get).

◆ p_atomic_int_inc()

P_LIB_API void p_atomic_int_inc ( volatile pint atomic)

Increments pint value from atomic by 1.

Parameters
[in,out]atomicPointer to pint to increment the value.
Since
0.0.1

Think of this operation as an atomic version of { *atomic += 1; }.

This call acts as a full compiler and hardware memory barrier.

◆ p_atomic_int_or()

P_LIB_API puint p_atomic_int_or ( volatile puint atomic,
puint  val 
)

Atomically performs the bitwise 'or' operation of atomic value and val storing the result back in atomic.

Parameters
[in,out]atomicPointer to puint.
valpuint to perform bitwise 'or' with atomic value.
Returns
Old atomic value before the operation.
Since
0.0.1

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.

◆ p_atomic_int_set()

P_LIB_API void p_atomic_int_set ( volatile pint atomic,
pint  val 
)

Sets pint value to atomic.

Parameters
[out]atomicPointer to pint to set the value for.
valNew pint value.
Since
0.0.1

This call acts as a full compiler and hardware memory barrier (after the set).

◆ p_atomic_int_xor()

P_LIB_API puint p_atomic_int_xor ( volatile puint atomic,
puint  val 
)

Atomically performs the bitwise 'xor' operation of atomic value and val storing the result back in atomic.

Parameters
[in,out]atomicPointer to puint.
valpuint to perform bitwise 'xor' with atomic value.
Returns
Old atomic value before the operation.
Since
0.0.1

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.

◆ p_atomic_is_lock_free()

P_LIB_API pboolean p_atomic_is_lock_free ( void  )

Checks whether atomic operations are lock-free.

Returns
TRUE in case of success, FALSE otherwise.
Since
0.0.1

Some underlying atomic model implementations may not support lock-free operations depending on hardware or software.

◆ p_atomic_pointer_add()

P_LIB_API pssize p_atomic_pointer_add ( volatile void *  atomic,
pssize  val 
)

Atomically adds ppointer-sized value to atomic value.

Parameters
[in,out]atomicPointer to ppointer-sized value.
valValue to add to atomic value.
Returns
Old value before the addition.
Since
0.0.1

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.

◆ p_atomic_pointer_and()

P_LIB_API psize p_atomic_pointer_and ( volatile void *  atomic,
psize  val 
)

Atomically performs the bitwise 'and' operation of ppointer-sized atomic value and val storing the result back in atomic.

Parameters
[in,out]atomicPointer to ppointer-size value.
valpsize to perform bitwise 'and' with atomic value.
Returns
Old atomic value before the operation.
Since
0.0.1

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.

◆ p_atomic_pointer_compare_and_exchange()

P_LIB_API pboolean p_atomic_pointer_compare_and_exchange ( volatile void *  atomic,
ppointer  oldval,
ppointer  newval 
)

Compares oldval with the value pointed to by atomic and if they are equal, atomically exchanges the value of atomic with newval.

Parameters
[in,out]atomicPointer to ppointer-sized value.
oldvalOld ppointer-sized value.
newvalNew ppointer-sized value.
Returns
TRUE if atomic value was equal oldval, FALSE otherwise.
Since
0.0.1

This compare and exchange is done atomically.

Think of this operation as an atomic version of { if (*atomic == oldval) { *atomic = newval; return TRUE; } else return FALSE; }.

This call acts as a full compiler and hardware memory barrier.

◆ p_atomic_pointer_get()

P_LIB_API ppointer p_atomic_pointer_get ( const volatile void *  atomic)

Gets ppointer-sized value from atomic.

Parameters
atomicPointer to get the value from.
Returns
Value from the pointer.
Since
0.0.1

This call acts as a full compiler and hardware memory barrier (before the get).

◆ p_atomic_pointer_or()

P_LIB_API psize p_atomic_pointer_or ( volatile void *  atomic,
psize  val 
)

Atomically performs the bitwise 'or' operation of ppointer-sized atomic value and val storing the result back in atomic.

Parameters
[in,out]atomicPointer to ppointer-size value.
valpsize to perform bitwise 'or' with atomic value.
Returns
Old atomic value before the operation.
Since
0.0.1

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.

◆ p_atomic_pointer_set()

P_LIB_API void p_atomic_pointer_set ( volatile void *  atomic,
ppointer  val 
)

Sets val to ppointer-sized atomic.

Parameters
[out]atomicPointer to set the value for.
valNew value for atomic.
Since
0.0.1

This call acts as a full compiler and hardware memory barrier (after the set).

◆ p_atomic_pointer_xor()

P_LIB_API psize p_atomic_pointer_xor ( volatile void *  atomic,
psize  val 
)

Atomically performs the bitwise 'xor' operation of ppointer-sized atomic value and val storing the result back in atomic.

Parameters
[in,out]atomicPointer to ppointer-size value.
valpsize to perform bitwise 'xor' with atomic value.
Returns
Old atomic value before the operation.
Since
0.0.1

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.