@@ -40,6 +40,28 @@ enum class MemoryScope : int {
4040#endif
4141};
4242
43+ namespace impl {
44+ LIBC_INLINE constexpr int order (MemoryOrder mem_ord) {
45+ return static_cast <int >(mem_ord);
46+ }
47+
48+ LIBC_INLINE constexpr int scope (MemoryScope mem_scope) {
49+ return static_cast <int >(mem_scope);
50+ }
51+
52+ template <class T > LIBC_INLINE T *addressof (T &ref) {
53+ return __builtin_addressof (ref);
54+ }
55+
56+ LIBC_INLINE constexpr int infer_failure_order (MemoryOrder mem_ord) {
57+ if (mem_ord == MemoryOrder::RELEASE)
58+ return order (MemoryOrder::RELAXED);
59+ if (mem_ord == MemoryOrder::ACQ_REL)
60+ return order (MemoryOrder::ACQUIRE);
61+ return order (mem_ord);
62+ }
63+ } // namespace impl
64+
4365template <typename T> struct Atomic {
4466 static_assert (is_trivially_copyable_v<T> && is_copy_constructible_v<T> &&
4567 is_move_constructible_v<T> && is_copy_assignable_v<T> &&
@@ -54,15 +76,6 @@ template <typename T> struct Atomic {
5476
5577private:
5678 // type conversion helper to avoid long c++ style casts
57- LIBC_INLINE static int order (MemoryOrder mem_ord) {
58- return static_cast <int >(mem_ord);
59- }
60-
61- LIBC_INLINE static int scope (MemoryScope mem_scope) {
62- return static_cast <int >(mem_scope);
63- }
64-
65- LIBC_INLINE static T *addressof (T &ref) { return __builtin_addressof (ref); }
6679
6780 // Require types that are 1, 2, 4, 8, or 16 bytes in length to be aligned to
6881 // at least their size to be potentially used lock-free.
@@ -98,10 +111,11 @@ template <typename T> struct Atomic {
98111 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
99112 T res;
100113#if __has_builtin(__scoped_atomic_load)
101- __scoped_atomic_load (addressof (val), addressof (res), order (mem_ord ),
102- scope (mem_scope));
114+ __scoped_atomic_load (impl:: addressof (val), impl:: addressof (res),
115+ impl::order (mem_ord), impl:: scope (mem_scope));
103116#else
104- __atomic_load (addressof (val), addressof (res), order (mem_ord));
117+ __atomic_load (impl::addressof (val), impl::addressof (res),
118+ impl::order (mem_ord));
105119#endif
106120 return res;
107121 }
@@ -116,20 +130,22 @@ template <typename T> struct Atomic {
116130 store (T rhs, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
117131 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
118132#if __has_builtin(__scoped_atomic_store)
119- __scoped_atomic_store (addressof (val), addressof (rhs), order (mem_ord ),
120- scope (mem_scope));
133+ __scoped_atomic_store (impl:: addressof (val), impl:: addressof (rhs),
134+ impl::order (mem_ord), impl:: scope (mem_scope));
121135#else
122- __atomic_store (addressof (val), addressof (rhs), order (mem_ord));
136+ __atomic_store (impl::addressof (val), impl::addressof (rhs),
137+ impl::order (mem_ord));
123138#endif
124139 }
125140
126141 // Atomic compare exchange
127142 LIBC_INLINE bool compare_exchange_strong (
128143 T &expected, T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
129144 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
130- return __atomic_compare_exchange (addressof (val), addressof (expected),
131- addressof (desired), false , order (mem_ord),
132- order (mem_ord));
145+ return __atomic_compare_exchange (
146+ impl::addressof (val), impl::addressof (expected),
147+ impl::addressof (desired), false , impl::order (mem_ord),
148+ impl::infer_failure_order (mem_ord));
133149 }
134150
135151 // Atomic compare exchange (separate success and failure memory orders)
@@ -138,17 +154,19 @@ template <typename T> struct Atomic {
138154 MemoryOrder failure_order,
139155 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
140156 return __atomic_compare_exchange (
141- addressof (val), addressof (expected), addressof (desired), false ,
142- order (success_order), order (failure_order));
157+ impl::addressof (val), impl::addressof (expected),
158+ impl::addressof (desired), false , impl::order (success_order),
159+ impl::order (failure_order));
143160 }
144161
145162 // Atomic compare exchange (weak version)
146163 LIBC_INLINE bool compare_exchange_weak (
147164 T &expected, T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
148165 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
149- return __atomic_compare_exchange (addressof (val), addressof (expected),
150- addressof (desired), true , order (mem_ord),
151- order (mem_ord));
166+ return __atomic_compare_exchange (
167+ impl::addressof (val), impl::addressof (expected),
168+ impl::addressof (desired), true , impl::order (mem_ord),
169+ impl::infer_failure_order (mem_ord));
152170 }
153171
154172 // Atomic compare exchange (weak version with separate success and failure
@@ -158,20 +176,22 @@ template <typename T> struct Atomic {
158176 MemoryOrder failure_order,
159177 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
160178 return __atomic_compare_exchange (
161- addressof (val), addressof (expected), addressof (desired), true ,
162- order (success_order), order (failure_order));
179+ impl::addressof (val), impl::addressof (expected),
180+ impl::addressof (desired), true , impl::order (success_order),
181+ impl::order (failure_order));
163182 }
164183
165184 LIBC_INLINE T
166185 exchange (T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
167186 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
168187 T ret;
169188#if __has_builtin(__scoped_atomic_exchange)
170- __scoped_atomic_exchange (addressof (val), addressof (desired), addressof (ret),
171- order (mem_ord), scope (mem_scope));
189+ __scoped_atomic_exchange (impl::addressof (val), impl::addressof (desired),
190+ impl::addressof (ret), impl::order (mem_ord),
191+ impl::scope (mem_scope));
172192#else
173- __atomic_exchange (addressof (val), addressof (desired), addressof (ret ),
174- order (mem_ord));
193+ __atomic_exchange (impl:: addressof (val), impl:: addressof (desired),
194+ impl::addressof (ret), impl:: order (mem_ord));
175195#endif
176196 return ret;
177197 }
@@ -181,10 +201,12 @@ template <typename T> struct Atomic {
181201 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
182202 static_assert (cpp::is_integral_v<T>, " T must be an integral type." );
183203#if __has_builtin(__scoped_atomic_fetch_add)
184- return __scoped_atomic_fetch_add (addressof (val), increment, order (mem_ord),
185- scope (mem_scope));
204+ return __scoped_atomic_fetch_add (impl::addressof (val), increment,
205+ impl::order (mem_ord),
206+ impl::scope (mem_scope));
186207#else
187- return __atomic_fetch_add (addressof (val), increment, order (mem_ord));
208+ return __atomic_fetch_add (impl::addressof (val), increment,
209+ impl::order (mem_ord));
188210#endif
189211 }
190212
@@ -193,10 +215,11 @@ template <typename T> struct Atomic {
193215 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
194216 static_assert (cpp::is_integral_v<T>, " T must be an integral type." );
195217#if __has_builtin(__scoped_atomic_fetch_or)
196- return __scoped_atomic_fetch_or (addressof (val), mask, order (mem_ord),
197- scope (mem_scope));
218+ return __scoped_atomic_fetch_or (impl::addressof (val), mask,
219+ impl::order (mem_ord),
220+ impl::scope (mem_scope));
198221#else
199- return __atomic_fetch_or (addressof (val), mask, order (mem_ord));
222+ return __atomic_fetch_or (impl:: addressof (val), mask, impl:: order (mem_ord));
200223#endif
201224 }
202225
@@ -205,10 +228,11 @@ template <typename T> struct Atomic {
205228 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
206229 static_assert (cpp::is_integral_v<T>, " T must be an integral type." );
207230#if __has_builtin(__scoped_atomic_fetch_and)
208- return __scoped_atomic_fetch_and (addressof (val), mask, order (mem_ord),
209- scope (mem_scope));
231+ return __scoped_atomic_fetch_and (impl::addressof (val), mask,
232+ impl::order (mem_ord),
233+ impl::scope (mem_scope));
210234#else
211- return __atomic_fetch_and (addressof (val), mask, order (mem_ord));
235+ return __atomic_fetch_and (impl:: addressof (val), mask, impl:: order (mem_ord));
212236#endif
213237 }
214238
@@ -217,10 +241,12 @@ template <typename T> struct Atomic {
217241 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
218242 static_assert (cpp::is_integral_v<T>, " T must be an integral type." );
219243#if __has_builtin(__scoped_atomic_fetch_sub)
220- return __scoped_atomic_fetch_sub (addressof (val), decrement, order (mem_ord),
221- scope (mem_scope));
244+ return __scoped_atomic_fetch_sub (impl::addressof (val), decrement,
245+ impl::order (mem_ord),
246+ impl::scope (mem_scope));
222247#else
223- return __atomic_fetch_sub (addressof (val), decrement, order (mem_ord));
248+ return __atomic_fetch_sub (impl::addressof (val), decrement,
249+ impl::order (mem_ord));
224250#endif
225251 }
226252
@@ -244,14 +270,6 @@ template <typename T> struct AtomicRef {
244270private:
245271 T *ptr;
246272
247- LIBC_INLINE static int order (MemoryOrder mem_ord) {
248- return static_cast <int >(mem_ord);
249- }
250-
251- LIBC_INLINE static int scope (MemoryScope mem_scope) {
252- return static_cast <int >(mem_scope);
253- }
254-
255273public:
256274 // Constructor from T reference
257275 LIBC_INLINE explicit constexpr AtomicRef (T &obj) : ptr(&obj) {}
@@ -270,9 +288,10 @@ template <typename T> struct AtomicRef {
270288 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
271289 T res;
272290#if __has_builtin(__scoped_atomic_load)
273- __scoped_atomic_load (ptr, &res, order (mem_ord), scope (mem_scope));
291+ __scoped_atomic_load (ptr, &res, impl::order (mem_ord),
292+ impl::scope (mem_scope));
274293#else
275- __atomic_load (ptr, &res, order (mem_ord));
294+ __atomic_load (ptr, &res, impl:: order (mem_ord));
276295#endif
277296 return res;
278297 }
@@ -287,9 +306,10 @@ template <typename T> struct AtomicRef {
287306 store (T rhs, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
288307 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
289308#if __has_builtin(__scoped_atomic_store)
290- __scoped_atomic_store (ptr, &rhs, order (mem_ord), scope (mem_scope));
309+ __scoped_atomic_store (ptr, &rhs, impl::order (mem_ord),
310+ impl::scope (mem_scope));
291311#else
292- __atomic_store (ptr, &rhs, order (mem_ord));
312+ __atomic_store (ptr, &rhs, impl:: order (mem_ord));
293313#endif
294314 }
295315
@@ -298,7 +318,8 @@ template <typename T> struct AtomicRef {
298318 T &expected, T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
299319 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
300320 return __atomic_compare_exchange (ptr, &expected, &desired, false ,
301- order (mem_ord), order (mem_ord));
321+ impl::order (mem_ord),
322+ impl::infer_failure_order (mem_ord));
302323 }
303324
304325 // Atomic compare exchange (strong, separate success/failure memory orders)
@@ -307,8 +328,8 @@ template <typename T> struct AtomicRef {
307328 MemoryOrder failure_order,
308329 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
309330 return __atomic_compare_exchange (ptr, &expected, &desired, false ,
310- order (success_order),
311- order (failure_order));
331+ impl:: order (success_order),
332+ impl:: order (failure_order));
312333 }
313334
314335 // Atomic exchange
@@ -317,10 +338,10 @@ template <typename T> struct AtomicRef {
317338 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
318339 T ret;
319340#if __has_builtin(__scoped_atomic_exchange)
320- __scoped_atomic_exchange (ptr, &desired, &ret, order (mem_ord),
321- scope (mem_scope));
341+ __scoped_atomic_exchange (ptr, &desired, &ret, impl:: order (mem_ord),
342+ impl:: scope (mem_scope));
322343#else
323- __atomic_exchange (ptr, &desired, &ret, order (mem_ord));
344+ __atomic_exchange (ptr, &desired, &ret, impl:: order (mem_ord));
324345#endif
325346 return ret;
326347 }
@@ -330,10 +351,10 @@ template <typename T> struct AtomicRef {
330351 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
331352 static_assert (cpp::is_integral_v<T>, " T must be an integral type." );
332353#if __has_builtin(__scoped_atomic_fetch_add)
333- return __scoped_atomic_fetch_add (ptr, increment, order (mem_ord),
334- scope (mem_scope));
354+ return __scoped_atomic_fetch_add (ptr, increment, impl:: order (mem_ord),
355+ impl:: scope (mem_scope));
335356#else
336- return __atomic_fetch_add (ptr, increment, order (mem_ord));
357+ return __atomic_fetch_add (ptr, increment, impl:: order (mem_ord));
337358#endif
338359 }
339360
@@ -342,10 +363,10 @@ template <typename T> struct AtomicRef {
342363 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
343364 static_assert (cpp::is_integral_v<T>, " T must be an integral type." );
344365#if __has_builtin(__scoped_atomic_fetch_or)
345- return __scoped_atomic_fetch_or (ptr, mask, order (mem_ord),
346- scope (mem_scope));
366+ return __scoped_atomic_fetch_or (ptr, mask, impl:: order (mem_ord),
367+ impl:: scope (mem_scope));
347368#else
348- return __atomic_fetch_or (ptr, mask, order (mem_ord));
369+ return __atomic_fetch_or (ptr, mask, impl:: order (mem_ord));
349370#endif
350371 }
351372
@@ -354,10 +375,10 @@ template <typename T> struct AtomicRef {
354375 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
355376 static_assert (cpp::is_integral_v<T>, " T must be an integral type." );
356377#if __has_builtin(__scoped_atomic_fetch_and)
357- return __scoped_atomic_fetch_and (ptr, mask, order (mem_ord),
358- scope (mem_scope));
378+ return __scoped_atomic_fetch_and (ptr, mask, impl:: order (mem_ord),
379+ impl:: scope (mem_scope));
359380#else
360- return __atomic_fetch_and (ptr, mask, order (mem_ord));
381+ return __atomic_fetch_and (ptr, mask, impl:: order (mem_ord));
361382#endif
362383 }
363384
@@ -366,10 +387,10 @@ template <typename T> struct AtomicRef {
366387 [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
367388 static_assert (cpp::is_integral_v<T>, " T must be an integral type." );
368389#if __has_builtin(__scoped_atomic_fetch_sub)
369- return __scoped_atomic_fetch_sub (ptr, decrement, order (mem_ord),
370- scope (mem_scope));
390+ return __scoped_atomic_fetch_sub (ptr, decrement, impl:: order (mem_ord),
391+ impl:: scope (mem_scope));
371392#else
372- return __atomic_fetch_sub (ptr, decrement, order (mem_ord));
393+ return __atomic_fetch_sub (ptr, decrement, impl:: order (mem_ord));
373394#endif
374395 }
375396};
@@ -402,7 +423,6 @@ LIBC_INLINE void atomic_signal_fence([[maybe_unused]] MemoryOrder mem_ord) {
402423 asm volatile (" " ::: " memory" );
403424#endif
404425}
405-
406426} // namespace cpp
407427} // namespace LIBC_NAMESPACE_DECL
408428
0 commit comments