#Header
#include "co/atomic.h"
The API is in the co namespace.
#Memory Order
using memorder_t = std::memory_order;
constexpr memorder_t mo_relaxed = std::memory_order_relaxed;
constexpr memorder_t mo_consume = std::memory_order_consume;
constexpr memorder_t mo_acquire = std::memory_order_acquire;
constexpr memorder_t mo_release = std::memory_order_release;
constexpr memorder_t mo_acq_rel = std::memory_order_acq_rel;
constexpr memorder_t mo_seq_cst = std::memory_order_seq_cst;
#Load and Store
template<typename T>
T atomic_load(const T* p, memorder_t mo = mo_seq_cst);
template<typename T, typename V>
void atomic_store(T* p, V v, memorder_t mo = mo_seq_cst);
atomic_loadsupports:mo_relaxed,mo_consume,mo_acquire,mo_seq_cst.atomic_storesupports:mo_relaxed,mo_release,mo_seq_cst.
Example:
int i = 0;
co::atomic_store(&i, 3); // i -> 3
int x = co::atomic_load(&i); // x -> 3
#Exchange
template<typename T, typename V>
T atomic_swap(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T, typename O, typename V>
T atomic_compare_swap(
T* p, O o, V v,
memorder_t smo = mo_seq_cst, memorder_t fmo = mo_seq_cst
);
template<typename T, typename O, typename V>
T atomic_cas(
T* p, O o, V v,
memorder_t smo = mo_seq_cst, memorder_t fmo = mo_seq_cst
);
template<typename T, typename O, typename V>
bool atomic_bool_cas(
T* p, O o, V v,
memorder_t smo = mo_seq_cst, memorder_t fmo = mo_seq_cst
);
atomic_swapreturns the old value and supports all memory orders.atomic_casis equivalent toatomic_compare_swap; it performs the swap only when*p == o, and returns the old value.atomic_bool_casis similar toatomic_cas; it returns true on success and false on failure.- In CAS operations,
smois the memory order on success and supports all memory orders;fmois the memory order on failure, cannot bemo_releaseormo_acq_rel, and cannot be stronger thansmo.
Example:
bool b = false;
bool o = co::atomic_swap(&b, true); // b -> true, o -> false
int i = 0;
int r = co::atomic_cas(&i, 1, 2); // i unchanged, r -> 0
r = co::atomic_cas(&i, 0, 2); // i -> 2, r -> 0
void* p = 0;
bool x = co::atomic_bool_cas(&p, 0, (void*)8); // p -> 8, x -> true
#Add and Subtract
template<typename T, typename V>
T atomic_add(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T, typename V>
T atomic_sub(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T>
T atomic_inc(T* p, memorder_t mo = mo_seq_cst);
template<typename T>
T atomic_dec(T* p, memorder_t mo = mo_seq_cst);
template<typename T, typename V>
T atomic_fetch_add(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T, typename V>
T atomic_fetch_sub(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T>
T atomic_fetch_inc(T* p, memorder_t mo = mo_seq_cst);
template<typename T>
T atomic_fetch_dec(T* p, memorder_t mo = mo_seq_cst);
incadds 1,decsubtracts 1.- The fetch versions return the old value; the non-fetch versions return the new value.
- Supports all memory orders.
#Bitwise Operations
template<typename T, typename V>
T atomic_or(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T, typename V>
T atomic_and(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T, typename V>
T atomic_xor(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T, typename V>
T atomic_fetch_or(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T, typename V>
T atomic_fetch_and(T* p, V v, memorder_t mo = mo_seq_cst);
template<typename T, typename V>
T atomic_fetch_xor(T* p, V v, memorder_t mo = mo_seq_cst);
- The fetch versions return the old value; the non-fetch versions return the new value.
- Supports all memory orders.