CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
clang_atomic.h
1#pragma once
2
3#include <stdatomic.h>
4
5#define atomicInit(...) (__VA_ARGS__)
6
7#define AtomicMemoryOrder memory_order
8#define ATOMIC_MO_Relaxed memory_order_relaxed
9#define ATOMIC_MO_Acquire memory_order_acquire
10#define ATOMIC_MO_Release memory_order_release
11#define ATOMIC_MO_AcqRel memory_order_acq_rel
12#define ATOMIC_MO_SeqCst memory_order_seq_cst
13
14#define atomicFence(order) atomic_thread_fence(ATOMIC_MO_##order)
15
16#define atomic(type) cx_atomic_##type
17#define atomicLoad(type, atomic_ptr, order) \
18 _atomicLoad_##type(atomic_ptr, ATOMIC_MO_##order)
19#define atomicStore(type, atomic_ptr, val, order) \
20 _atomicStore_##type(atomic_ptr, val, ATOMIC_MO_##order)
21#define atomicExchange(type, atomic_ptr, val, order) \
22 _atomicExchange_##type(atomic_ptr, val, ATOMIC_MO_##order)
23#define atomicCompareExchange(type, semantics, atomic_ptr, expected_ptr,\
24 desired, successorder, failorder) \
25 _atomicCompareExchange_##semantics##_##type(atomic_ptr, \
26 expected_ptr, desired, \
27 ATOMIC_MO_##successorder, ATOMIC_MO_##failorder)
28
29#define atomicFetchAdd(type, atomic_ptr, val, order) \
30 _atomicFetchAdd_##type(atomic_ptr, val, ATOMIC_MO_##order)
31#define atomicFetchSub(type, atomic_ptr, val, order) \
32 _atomicFetchSub_##type(atomic_ptr, val, ATOMIC_MO_##order)
33#define atomicFetchAnd(type, atomic_ptr, val, order) \
34 _atomicFetchAnd_##type(atomic_ptr, val, ATOMIC_MO_##order)
35#define atomicFetchOr(type, atomic_ptr, val, order) \
36 _atomicFetchOr_##type(atomic_ptr, val, ATOMIC_MO_##order)
37#define atomicFetchXor(type, atomic_ptr, val, order) \
38 _atomicFetchXor_##type(atomic_ptr, val, ATOMIC_MO_##order)
39
40#define CX_GENERATE_ATOMICS(type, short_type, \
41 /* unused */ lg_size) \
42typedef _Atomic(type) cx_atomic_##short_type; \
43 \
44_meta_inline type \
45_atomicLoad_##short_type(const cx_atomic_##short_type *a, \
46 AtomicMemoryOrder mo) { \
47 /* \
48 * A strict interpretation of the C standard prevents \
49 * atomic_load from taking a const argument, but it's \
50 * convenient for our purposes. This cast is a workaround. \
51 */ \
52 cx_atomic_##short_type* a_nonconst = \
53 (cx_atomic_##short_type*)a; \
54 return atomic_load_explicit(a_nonconst, mo); \
55} \
56 \
57_meta_inline void \
58_atomicStore_##short_type(cx_atomic_##short_type *a, \
59 type val, AtomicMemoryOrder mo) { \
60 atomic_store_explicit(a, val, mo); \
61} \
62 \
63_meta_inline type \
64_atomicExchange_##short_type(cx_atomic_##short_type *a, type val, \
65 AtomicMemoryOrder mo) { \
66 return atomic_exchange_explicit(a, val, mo); \
67} \
68 \
69_meta_inline bool \
70_atomicCompareExchange_weak_##short_type(cx_atomic_##short_type *a, \
71 type *expected, type desired, AtomicMemoryOrder success_mo, \
72 AtomicMemoryOrder failure_mo) { \
73 return atomic_compare_exchange_weak_explicit(a, expected, \
74 desired, success_mo, failure_mo); \
75} \
76 \
77_meta_inline bool \
78_atomicCompareExchange_strong_##short_type(cx_atomic_##short_type *a, \
79 type *expected, type desired, AtomicMemoryOrder success_mo, \
80 AtomicMemoryOrder failure_mo) { \
81 return atomic_compare_exchange_strong_explicit(a, expected, \
82 desired, success_mo, failure_mo); \
83}
84
85#define CX_EXTERN_ATOMICS(type, short_type) \
86extern inline type \
87_atomicLoad_##short_type(const cx_atomic_##short_type *a, \
88 AtomicMemoryOrder mo); \
89 \
90extern inline void \
91_atomicStore_##short_type(cx_atomic_##short_type *a, \
92 type val, AtomicMemoryOrder mo); \
93 \
94extern inline type \
95_atomicExchange_##short_type(cx_atomic_##short_type *a, type val, \
96 AtomicMemoryOrder mo); \
97 \
98extern inline bool \
99_atomicCompareExchange_weak_##short_type(cx_atomic_##short_type *a, \
100 type *expected, type desired, AtomicMemoryOrder success_mo, \
101 AtomicMemoryOrder failure_mo); \
102 \
103extern inline bool \
104_atomicCompareExchange_strong_##short_type(cx_atomic_##short_type *a, \
105 type *expected, type desired, AtomicMemoryOrder success_mo, \
106 AtomicMemoryOrder failure_mo);
107
108/*
109 * Integral types have some special operations available that non-integral ones
110 * lack.
111 */
112#define CX_GENERATE_INT_ATOMICS(type, short_type, \
113 /* unused */ lg_size) \
114CX_GENERATE_ATOMICS(type, short_type, /* unused */ lg_size) \
115 \
116_meta_inline type \
117_atomicFetchAdd_##short_type(cx_atomic_##short_type *a, \
118 type val, AtomicMemoryOrder mo) { \
119 return atomic_fetch_add_explicit(a, val, mo); \
120} \
121_meta_inline type \
122_atomicFetchSub_##short_type(cx_atomic_##short_type *a, \
123 type val, AtomicMemoryOrder mo) { \
124 return atomic_fetch_sub_explicit(a, val, mo); \
125} \
126_meta_inline type \
127_atomicFetchAnd_##short_type(cx_atomic_##short_type *a, \
128 type val, AtomicMemoryOrder mo) { \
129 return atomic_fetch_and_explicit(a, val, mo); \
130} \
131_meta_inline type \
132_atomicFetchOr_##short_type(cx_atomic_##short_type *a, \
133 type val, AtomicMemoryOrder mo) { \
134 return atomic_fetch_or_explicit(a, val, mo); \
135} \
136_meta_inline type \
137_atomicFetchXor_##short_type(cx_atomic_##short_type *a, \
138 type val, AtomicMemoryOrder mo) { \
139 return atomic_fetch_xor_explicit(a, val, mo); \
140}
141
142#define CX_EXTERN_INT_ATOMICS(type, short_type) \
143CX_EXTERN_ATOMICS(type, short_type) \
144 \
145extern inline type \
146_atomicFetchAdd_##short_type(cx_atomic_##short_type *a, \
147 type val, AtomicMemoryOrder mo); \
148extern inline type \
149_atomicFetchSub_##short_type(cx_atomic_##short_type *a, \
150 type val, AtomicMemoryOrder mo); \
151extern inline type \
152_atomicFetchAnd_##short_type(cx_atomic_##short_type *a, \
153 type val, AtomicMemoryOrder mo); \
154extern inline type \
155_atomicFetchOr_##short_type(cx_atomic_##short_type *a, \
156 type val, AtomicMemoryOrder mo); \
157extern inline type \
158_atomicFetchXor_##short_type(cx_atomic_##short_type *a, \
159 type val, AtomicMemoryOrder mo);