21#if !defined(__RLIB_H_INCLUDE_GUARD__) && !defined(RLIB_COMPILATION)
22#error "#include <rlib.h> only please."
60#if defined(__clang__) && __has_extension(c_atomic)
61#define USE_CLANG_ATOMICS 1
62#elif R_GNUC_PREREQ(4, 9) && !defined(__STDC_NO_ATOMICS__)
63#define USE_GNUC_ATOMICS 1
64#elif defined(__GNUC__)
65#define USE_SYNC_ATOMICS 1
66#elif defined(_MSC_VER)
68#define USE_MSC_ATOMICS 1
74#if defined(USE_CLANG_ATOMICS) || defined(USE_GNUC_ATOMICS)
76typedef _Atomic(
int) raint;
78typedef _Atomic(
ruint) rauint;
81#elif defined(USE_MSC_ATOMICS)
82typedef int volatile raint;
83typedef ruint volatile rauint;
135#define r_atomic_bool_load(a) ((rboolean) r_atomic_int_load (a))
137#define r_atomic_bool_store(a, v) r_atomic_int_store (a, (int) (v))
139#define r_atomic_bool_exchange(a, v) ((rboolean) r_atomic_int_exchange (a, (int) (v)))
141#define r_atomic_bool_set(a) r_atomic_bool_store (a, TRUE)
143#define r_atomic_bool_unset(a) r_atomic_bool_store (a, FALSE)
204#if defined(USE_CLANG_ATOMICS)
205#define r_atomic_int_load(a) __c11_atomic_load (a, __ATOMIC_SEQ_CST)
206#define r_atomic_int_store(a, v) __c11_atomic_store (a, v, __ATOMIC_SEQ_CST)
207#define r_atomic_int_exchange(a, v) __c11_atomic_exchange (a, v, __ATOMIC_SEQ_CST)
208#define r_atomic_int_cmp_xchg_weak(a, o, v) __c11_atomic_compare_exchange_weak (a, o, v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
209#define r_atomic_int_cmp_xchg_strong(a, o, v) __c11_atomic_compare_exchange_strong (a, o, v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
210#define r_atomic_int_fetch_add(a, v) __c11_atomic_fetch_add (a, v, __ATOMIC_SEQ_CST)
211#define r_atomic_int_fetch_sub(a, v) __c11_atomic_fetch_sub (a, v, __ATOMIC_SEQ_CST)
212#define r_atomic_int_fetch_and(a, v) __c11_atomic_fetch_and (a, v, __ATOMIC_SEQ_CST)
213#define r_atomic_int_fetch_or(a, v) __c11_atomic_fetch_or (a, v, __ATOMIC_SEQ_CST)
214#define r_atomic_int_fetch_xor(a, v) __c11_atomic_fetch_xor (a, v, __ATOMIC_SEQ_CST)
216#define r_atomic_uint_load(a) __c11_atomic_load (a, __ATOMIC_SEQ_CST)
217#define r_atomic_uint_store(a, v) __c11_atomic_store (a, v, __ATOMIC_SEQ_CST)
218#define r_atomic_uint_exchange(a, v) __c11_atomic_exchange (a, v, __ATOMIC_SEQ_CST)
219#define r_atomic_uint_cmp_xchg_weak(a, o, v) __c11_atomic_compare_exchange_weak (a, o, v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
220#define r_atomic_uint_cmp_xchg_strong(a, o, v) __c11_atomic_compare_exchange_strong (a, o, v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
221#define r_atomic_uint_fetch_add(a, v) __c11_atomic_fetch_add (a, v, __ATOMIC_SEQ_CST)
222#define r_atomic_uint_fetch_sub(a, v) __c11_atomic_fetch_sub (a, v, __ATOMIC_SEQ_CST)
223#define r_atomic_uint_fetch_and(a, v) __c11_atomic_fetch_and (a, v, __ATOMIC_SEQ_CST)
224#define r_atomic_uint_fetch_or(a, v) __c11_atomic_fetch_or (a, v, __ATOMIC_SEQ_CST)
225#define r_atomic_uint_fetch_xor(a, v) __c11_atomic_fetch_xor (a, v, __ATOMIC_SEQ_CST)
227#define r_atomic_ptr_load(a) (rpointer)__c11_atomic_load (a, __ATOMIC_SEQ_CST)
228#define r_atomic_ptr_store(a, v) __c11_atomic_store (a, (ruintptr)v, __ATOMIC_SEQ_CST)
229#define r_atomic_ptr_exchange(a, v) (rpointer)__c11_atomic_exchange (a, (ruintptr)v, __ATOMIC_SEQ_CST)
230#define r_atomic_ptr_cmp_xchg_weak(a, o, v) __c11_atomic_compare_exchange_weak (a, (ruintptr*)o, (ruintptr)v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
231#define r_atomic_ptr_cmp_xchg_strong(a, o, v) __c11_atomic_compare_exchange_strong (a, (ruintptr*)o, (ruintptr)v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
232#define r_atomic_ptr_fetch_add(a, v) (rpointer)__c11_atomic_fetch_add (a, (ruintptr)v, __ATOMIC_SEQ_CST)
233#define r_atomic_ptr_fetch_sub(a, v) (rpointer)__c11_atomic_fetch_sub (a, (ruintptr)v, __ATOMIC_SEQ_CST)
234#define r_atomic_ptr_fetch_and(a, v) (rpointer)__c11_atomic_fetch_and (a, (ruintptr)v, __ATOMIC_SEQ_CST)
235#define r_atomic_ptr_fetch_or(a, v) (rpointer)__c11_atomic_fetch_or (a, (ruintptr)v, __ATOMIC_SEQ_CST)
236#define r_atomic_ptr_fetch_xor(a, v) (rpointer)__c11_atomic_fetch_xor (a, (ruintptr)v, __ATOMIC_SEQ_CST)
237#elif defined(USE_GNUC_ATOMICS)
238#define r_atomic_int_load(a) __atomic_load_n (a, __ATOMIC_SEQ_CST)
239#define r_atomic_int_store(a, v) __atomic_store_n (a, v, __ATOMIC_SEQ_CST)
240#define r_atomic_int_exchange(a, v) __atomic_exchange_n (a, v, __ATOMIC_SEQ_CST)
241#define r_atomic_int_cmp_xchg_weak(a, o, v) __atomic_compare_exchange_n (a, o, v, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
242#define r_atomic_int_cmp_xchg_strong(a, o, v) __atomic_compare_exchange_n (a, o, v, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
243#define r_atomic_int_fetch_add(a, v) __atomic_fetch_add (a, v, __ATOMIC_SEQ_CST)
244#define r_atomic_int_fetch_sub(a, v) __atomic_fetch_sub (a, v, __ATOMIC_SEQ_CST)
245#define r_atomic_int_fetch_and(a, v) __atomic_fetch_and (a, v, __ATOMIC_SEQ_CST)
246#define r_atomic_int_fetch_or(a, v) __atomic_fetch_or (a, v, __ATOMIC_SEQ_CST)
247#define r_atomic_int_fetch_xor(a, v) __atomic_fetch_xor (a, v, __ATOMIC_SEQ_CST)
249#define r_atomic_uint_load(a) __atomic_load_n (a, __ATOMIC_SEQ_CST)
250#define r_atomic_uint_store(a, v) __atomic_store_n (a, v, __ATOMIC_SEQ_CST)
251#define r_atomic_uint_exchange(a, v) __atomic_exchange_n (a, v, __ATOMIC_SEQ_CST)
252#define r_atomic_uint_cmp_xchg_weak(a, o, v) __atomic_compare_exchange_n (a, o, v, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
253#define r_atomic_uint_cmp_xchg_strong(a, o, v) __atomic_compare_exchange_n (a, o, v, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
254#define r_atomic_uint_fetch_add(a, v) __atomic_fetch_add (a, v, __ATOMIC_SEQ_CST)
255#define r_atomic_uint_fetch_sub(a, v) __atomic_fetch_sub (a, v, __ATOMIC_SEQ_CST)
256#define r_atomic_uint_fetch_and(a, v) __atomic_fetch_and (a, v, __ATOMIC_SEQ_CST)
257#define r_atomic_uint_fetch_or(a, v) __atomic_fetch_or (a, v, __ATOMIC_SEQ_CST)
258#define r_atomic_uint_fetch_xor(a, v) __atomic_fetch_xor (a, v, __ATOMIC_SEQ_CST)
260#define r_atomic_ptr_load(a) (rpointer)__atomic_load_n (a, __ATOMIC_SEQ_CST)
261#define r_atomic_ptr_store(a, v) __atomic_store_n (a, (ruintptr)v, __ATOMIC_SEQ_CST)
262#define r_atomic_ptr_exchange(a, v) (rpointer)__atomic_exchange_n (a, (ruintptr)v, __ATOMIC_SEQ_CST)
263#define r_atomic_ptr_cmp_xchg_weak(a, o, v) __atomic_compare_exchange_n (a, (ruintptr*)o, (ruintptr)v, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
264#define r_atomic_ptr_cmp_xchg_strong(a, o, v) __atomic_compare_exchange_n (a, (ruintptr*)o, (ruintptr)v, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
265#define r_atomic_ptr_fetch_add(a, v) (rpointer)__atomic_fetch_add (a, (ruintptr)v, __ATOMIC_SEQ_CST)
266#define r_atomic_ptr_fetch_sub(a, v) (rpointer)__atomic_fetch_sub (a, (ruintptr)v, __ATOMIC_SEQ_CST)
267#define r_atomic_ptr_fetch_and(a, v) (rpointer)__atomic_fetch_and (a, (ruintptr)v, __ATOMIC_SEQ_CST)
268#define r_atomic_ptr_fetch_or(a, v) (rpointer)__atomic_fetch_or (a, (ruintptr)v, __ATOMIC_SEQ_CST)
269#define r_atomic_ptr_fetch_xor(a, v) (rpointer)__atomic_fetch_xor (a, (ruintptr)v, __ATOMIC_SEQ_CST)
270#elif defined(USE_SYNC_ATOMICS)
271#if __has_builtin(__sync_swap)
272#define r_atomic_exchange(a, v) __sync_swap(a, v)
274#define r_atomic_exchange(a, v) \
276 __typeof__(a) __a = (a); \
277 __typeof__(v) __v = (v); \
278 __sync_synchronize(); \
279 __sync_lock_test_and_set(__a, __v); \
282#define r_atomic_cmp_xchg(a, o, v) \
284 __typeof__(o) __op = (o); \
285 __typeof__(*o) __o = *__op; \
286 (rboolean)((*__op = __sync_val_compare_and_swap(a, __o, v)) == __o); \
289#define r_atomic_int_load(a) __sync_fetch_and_add(a, 0)
290#define r_atomic_int_store(a, v) r_atomic_exchange (a, v)
291#define r_atomic_int_exchange(a, v) r_atomic_exchange (a, v)
292#define r_atomic_int_cmp_xchg_weak(a, o, v) r_atomic_cmp_xchg (a, o, v)
293#define r_atomic_int_cmp_xchg_strong(a, o, v) r_atomic_cmp_xchg (a, o, v)
294#define r_atomic_int_fetch_add(a, v) __sync_fetch_and_add (a, v)
295#define r_atomic_int_fetch_sub(a, v) __sync_fetch_and_sub (a, v)
296#define r_atomic_int_fetch_and(a, v) __sync_fetch_and_and (a, v)
297#define r_atomic_int_fetch_or(a, v) __sync_fetch_and_or (a, v)
298#define r_atomic_int_fetch_xor(a, v) __sync_fetch_and_xor (a, v)
300#define r_atomic_uint_load(a) __sync_fetch_and_add(a, 0)
301#define r_atomic_uint_store(a, v) r_atomic_exchange (a, v)
302#define r_atomic_uint_exchange(a, v) r_atomic_exchange (a, v)
303#define r_atomic_uint_cmp_xchg_weak(a, o, v) r_atomic_cmp_xchg (a, o, v)
304#define r_atomic_uint_cmp_xchg_strong(a, o, v) r_atomic_cmp_xchg (a, o, v)
305#define r_atomic_uint_fetch_add(a, v) __sync_fetch_and_add (a, v)
306#define r_atomic_uint_fetch_sub(a, v) __sync_fetch_and_sub (a, v)
307#define r_atomic_uint_fetch_and(a, v) __sync_fetch_and_and (a, v)
308#define r_atomic_uint_fetch_or(a, v) __sync_fetch_and_or (a, v)
309#define r_atomic_uint_fetch_xor(a, v) __sync_fetch_and_xor (a, v)
311#define r_atomic_ptr_load(a) (rpointer)__sync_fetch_and_add(a, 0)
312#define r_atomic_ptr_store(a, v) r_atomic_exchange (a, v)
313#define r_atomic_ptr_exchange(a, v) (rpointer)r_atomic_exchange (a, v)
314#define r_atomic_ptr_cmp_xchg_weak(a, o, v) r_atomic_cmp_xchg (a, o, v)
315#define r_atomic_ptr_cmp_xchg_strong(a, o, v) r_atomic_cmp_xchg (a, o, v)
316#define r_atomic_ptr_fetch_add(a, v) (rpointer)__sync_fetch_and_add (a, v)
317#define r_atomic_ptr_fetch_sub(a, v) (rpointer)__sync_fetch_and_sub (a, v)
318#define r_atomic_ptr_fetch_and(a, v) (rpointer)__sync_fetch_and_and (a, v)
319#define r_atomic_ptr_fetch_or(a, v) (rpointer)__sync_fetch_and_or (a, v)
320#define r_atomic_ptr_fetch_xor(a, v) (rpointer)__sync_fetch_and_xor (a, v)
324#define r_atomic_int_load(a) (MemoryBarrier(), *a)
325#define r_atomic_int_store(a, v) _InterlockedExchange ((long volatile *)a, (long)v)
326#define r_atomic_int_exchange(a, v) _InterlockedExchange ((long volatile *)a, (long)v)
339static inline rboolean _r_atomic_int_cmp_xchg_weak_impl (raint * a,
int * o,
int v) {
340 long prev = _InterlockedCompareExchange ((
long volatile *)a, (
long)v, (
long)*o);
341 if (prev == (
long)*o)
return TRUE;
345#define r_atomic_int_cmp_xchg_weak(a, o, v) _r_atomic_int_cmp_xchg_weak_impl ((a), (o), (v))
346#define r_atomic_int_cmp_xchg_strong(a, o, v) r_atomic_int_cmp_xchg_weak (a, o, v)
347#define r_atomic_int_fetch_add(a, v) _InterlockedExchangeAdd ((long volatile *)a, (long)v)
348#define r_atomic_int_fetch_sub(a, v) _InterlockedExchangeAdd ((long volatile *)a, -((long)v))
349#define r_atomic_int_fetch_and(a, v) _InterlockedAnd ((long volatile *)a, (long)v)
350#define r_atomic_int_fetch_or(a, v) _InterlockedOr ((long volatile *)a, (long)v)
351#define r_atomic_int_fetch_xor(a, v) _InterlockedXor ((long volatile *)a, (long)v)
353#define r_atomic_uint_load(a) (MemoryBarrier(), *a)
354#define r_atomic_uint_store(a, v) _InterlockedExchange ((long volatile *)a, (long)v)
355#define r_atomic_uint_exchange(a, v) _InterlockedExchange ((long volatile *)a, (long)v)
356static inline rboolean _r_atomic_uint_cmp_xchg_weak_impl (rauint * a,
ruint * o,
ruint v) {
357 long prev = _InterlockedCompareExchange ((
long volatile *)a, (
long)v, (
long)*o);
362#define r_atomic_uint_cmp_xchg_weak(a, o, v) _r_atomic_uint_cmp_xchg_weak_impl ((a), (o), (v))
363#define r_atomic_uint_cmp_xchg_strong(a, o, v) r_atomic_uint_cmp_xchg_weak (a, o, v)
364#define r_atomic_uint_fetch_add(a, v) _InterlockedExchangeAdd ((long volatile *)a, (long)v)
365#define r_atomic_uint_fetch_sub(a, v) _InterlockedExchangeAdd ((long volatile *)a, -((long)v))
366#define r_atomic_uint_fetch_and(a, v) _InterlockedAnd ((long volatile *)a, (long)v)
367#define r_atomic_uint_fetch_or(a, v) _InterlockedOr ((long volatile *)a, (long)v)
368#define r_atomic_uint_fetch_xor(a, v) _InterlockedXor ((long volatile *)a, (long)v)
370#define r_atomic_ptr_load(a) (rpointer)(MemoryBarrier(), *a)
371#define r_atomic_ptr_store(a, v) _InterlockedExchangePointer ((rpointer volatile)a, (rpointer)v)
372#define r_atomic_ptr_exchange(a, v) (rpointer)_InterlockedExchangePointer ((rpointer volatile)a, (rpointer)v)
374 rpointer prev = _InterlockedCompareExchangePointer ((
rpointer volatile)a, v, *o);
375 if (prev == *o)
return TRUE;
379#define r_atomic_ptr_cmp_xchg_weak(a, o, v) _r_atomic_ptr_cmp_xchg_weak_impl ((a), (o), (rpointer)(v))
380#define r_atomic_ptr_cmp_xchg_strong(a, o, v) r_atomic_ptr_cmp_xchg_weak (a, o, v)
381#if RLIB_SIZEOF_VOID_P == 4
382#define r_atomic_ptr_fetch_add(a, v) (rpointer)_InterlockedExchangeAdd ((long volatile *)a, (long)v)
383#define r_atomic_ptr_fetch_sub(a, v) (rpointer)_InterlockedExchangeAdd ((long volatile *)a, -((long)v))
384#define r_atomic_ptr_fetch_and(a, v) (rpointer)_InterlockedAnd ((long volatile *)a, (long)v)
385#define r_atomic_ptr_fetch_or(a, v) (rpointer)_InterlockedOr ((long volatile *)a, (long)v)
386#define r_atomic_ptr_fetch_xor(a, v) (rpointer)_InterlockedXor ((long volatile *)a, (long)v)
387#elif RLIB_SIZEOF_VOID_P == 8
388#define r_atomic_ptr_fetch_add(a, v) (rpointer)_InterlockedExchangeAdd64 ((_int64 volatile *)a, (_int64)v)
389#define r_atomic_ptr_fetch_sub(a, v) (rpointer)_InterlockedExchangeAdd64 ((_int64 volatile *)a, -((_int64)v))
390#define r_atomic_ptr_fetch_and(a, v) (rpointer)_InterlockedAnd64 ((_int64 volatile *)a, (_int64)v)
391#define r_atomic_ptr_fetch_or(a, v) (rpointer)_InterlockedOr64 ((_int64 volatile *)a, (_int64)v)
392#define r_atomic_ptr_fetch_xor(a, v) (rpointer)_InterlockedXor64 ((_int64 volatile *)a, (_int64)v)
394#error only x86 and x86_64 with MSC supported
void r_atomic_int_store(raint *a, int val)
Atomically store val into a.
rpointer r_atomic_ptr_fetch_sub(raptr *a, rpointer val)
Pointer-arithmetic fetch-sub; semantics mirror r_atomic_ptr_fetch_add.
int r_atomic_int_load(raint *a)
Atomically read a's value.
int r_atomic_int_fetch_sub(raint *a, int val)
Atomically compute *a -= val and return the previous *a.
void r_atomic_uint_store(rauint *a, ruint val)
Atomically store val into a.
rboolean r_atomic_uint_cmp_xchg_weak(rauint *a, ruint *old, ruint val)
Weak CAS; see r_atomic_int_cmp_xchg_weak for semantics.
ruint r_atomic_uint_exchange(rauint *a, ruint val)
Atomically write val and return the previous value.
rpointer r_atomic_ptr_fetch_and(raptr *a, rpointer val)
Bitwise &= over pointer storage (treat as integer width).
int r_atomic_int_fetch_xor(raint *a, int val)
Atomically compute *a ^= val and return the previous *a.
ruint r_atomic_uint_fetch_sub(rauint *a, ruint val)
Atomically compute *a -= val and return the previous *a.
rpointer r_atomic_ptr_load(raptr *a)
Atomically read a's pointer value.
ruint r_atomic_uint_fetch_and(rauint *a, ruint val)
Atomically compute *a &= val and return the previous *a.
rboolean r_atomic_ptr_cmp_xchg_strong(raptr *a, rpointer *old, rpointer val)
Strong CAS on pointer storage; no spurious failures.
int r_atomic_int_fetch_and(raint *a, int val)
Atomically compute *a &= val and return the previous *a.
rpointer r_atomic_ptr_fetch_xor(raptr *a, rpointer val)
Bitwise ^= over pointer storage.
ruint r_atomic_uint_fetch_or(rauint *a, ruint val)
Atomically compute *a |= val and return the previous *a.
int r_atomic_int_exchange(raint *a, int val)
Atomically write val and return the previous value.
raint raboolean
Atomic-friendly boolean; thin alias over raint so the boolean accessors funnel through r_atomic_int_*...
Definition ratomic.h:96
ruint r_atomic_uint_fetch_add(rauint *a, ruint val)
Atomically compute *a += val and return the previous *a.
rboolean r_atomic_int_cmp_xchg_weak(raint *a, int *old, int val)
Weak compare-and-swap: if *a equals *old, store val and return TRUE; otherwise write the current *a b...
rpointer r_atomic_ptr_fetch_add(raptr *a, rpointer val)
Pointer-arithmetic fetch-add: atomically *a += val and return the previous pointer.
rboolean r_atomic_int_cmp_xchg_strong(raint *a, int *old, int val)
Strong compare-and-swap: as r_atomic_int_cmp_xchg_weak but no spurious failure.
void r_atomic_ptr_store(raptr *a, rpointer val)
Atomically store val into a.
rpointer r_atomic_ptr_fetch_or(raptr *a, rpointer val)
Bitwise |= over pointer storage.
rboolean r_atomic_uint_cmp_xchg_strong(rauint *a, ruint *old, ruint val)
Strong CAS; no spurious failures.
rpointer r_atomic_ptr_exchange(raptr *a, rpointer val)
Atomically write val and return the previous value.
int r_atomic_int_fetch_or(raint *a, int val)
Atomically compute *a |= val and return the previous *a.
ruint r_atomic_uint_load(rauint *a)
Atomically read a's value.
int r_atomic_int_fetch_add(raint *a, int val)
Atomically compute *a += val and return the previous *a.
ruint r_atomic_uint_fetch_xor(rauint *a, ruint val)
Atomically compute *a ^= val and return the previous *a.
rboolean r_atomic_ptr_cmp_xchg_weak(raptr *a, rpointer *old, rpointer val)
Weak CAS on pointer storage; see r_atomic_int_cmp_xchg_weak for semantics.
#define R_API
Public-API decoration: resolves to R_API_EXPORT while building rlib and R_API_IMPORT for consumers.
Definition rmacros.h:115
#define TRUE
Boolean true (!FALSE).
Definition rmacros.h:136
#define FALSE
Boolean false (0).
Definition rmacros.h:132
#define R_BEGIN_DECLS
Open an extern "C" block under C++ (no-op in C).
Definition rmacros.h:196
int rboolean
Boolean type (typedef'd to int).
Definition rtypes.h:59
unsigned int ruint
Unsigned int.
Definition rtypes.h:157
unsigned long ruintptr
Unsigned integer wide enough to hold a pointer (like uintptr_t).
Definition rtypes.h:324
void * rpointer
Generic pointer (alias for void *).
Definition rtypes.h:327
Foundational type aliases used by every rlib header.