diff options
author | Chris Robinson <[email protected]> | 2018-10-29 20:50:57 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2018-10-29 20:50:57 -0700 |
commit | 3deb7c6ed5105a54c6cea01318099494ba1ee9b6 (patch) | |
tree | a6103b3dbb85fe0cb2e7b843d4491a86167a1832 /common/atomic.h | |
parent | 5fea511ccec500f575898df33e9934dec075527c (diff) |
Workaround C++ compatiility issues for atomic.h
This isn't wholly correct since neither C11 or C++11 guarantee compatibility
between atomic implementations. It's desired behavior and mostly works, see:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0943r1.html
Alignment issues can be fixed with manual alignas() specifications, should the
need arise.
Diffstat (limited to 'common/atomic.h')
-rw-r--r-- | common/atomic.h | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/common/atomic.h b/common/atomic.h index 39daa1dc..d28298f2 100644 --- a/common/atomic.h +++ b/common/atomic.h @@ -17,6 +17,52 @@ #define CONST_CAST(T, V) ((T)(V)) #endif +#ifdef HAVE_C11_ATOMIC +#ifdef __cplusplus +/* C++11 doesn't support compatibility with C11 atomics. So instead, make C++11 + * atomic declarations global to emulate C11. There's no standard guarantee of + * ABI compatibility, but it's desired behavior that mostly works. See: + * + * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0943r1.html + * + * Any alignment issues arising from this can be fixed with explicit alignas() + * specifiers on affected variables. + * + * Only do this when C11 atomics are supported in C, since MSVC and pre-C11 + * compilers may use something else that is significantly different in C + * despite supporting C++11 atomics. + */ +#include <atomic> + +#define _Atomic(T) std::atomic<T> +using std::memory_order; +using std::memory_order_relaxed; +using std::memory_order_consume; +using std::memory_order_acquire; +using std::memory_order_release; +using std::memory_order_acq_rel; +using std::memory_order_seq_cst; + +using std::atomic_flag; + +using std::atomic_init; +using std::atomic_load_explicit; +using std::atomic_store_explicit; +using std::atomic_fetch_add_explicit; +using std::atomic_fetch_sub_explicit; +using std::atomic_exchange_explicit; +using std::atomic_compare_exchange_strong_explicit; +using std::atomic_compare_exchange_weak_explicit; +using std::atomic_flag_test_and_set_explicit; +using std::atomic_flag_clear_explicit; +using std::atomic_thread_fence; + +#else + +#include <stdatomic.h> +#endif /* __cplusplus */ +#endif /* HAVE_C11_ATOMIC */ + #ifdef __cplusplus extern "C" { #endif @@ -24,8 +70,6 @@ extern "C" { /* Atomics using C11 */ #ifdef HAVE_C11_ATOMIC -#include <stdatomic.h> - #define almemory_order memory_order #define almemory_order_relaxed memory_order_relaxed #define almemory_order_consume memory_order_consume @@ -34,7 +78,7 @@ extern "C" { #define almemory_order_acq_rel memory_order_acq_rel #define almemory_order_seq_cst memory_order_seq_cst -#define ATOMIC(T) T _Atomic +#define ATOMIC(T) _Atomic(T) #define ATOMIC_FLAG atomic_flag #define ATOMIC_INIT atomic_init @@ -415,9 +459,9 @@ inline void InitRef(RefCount *ptr, uint value) inline uint ReadRef(RefCount *ptr) { return ATOMIC_LOAD(ptr, almemory_order_acquire); } inline uint IncrementRef(RefCount *ptr) -{ return ATOMIC_ADD(ptr, 1, almemory_order_acq_rel)+1; } +{ return ATOMIC_ADD(ptr, 1u, almemory_order_acq_rel)+1; } inline uint DecrementRef(RefCount *ptr) -{ return ATOMIC_SUB(ptr, 1, almemory_order_acq_rel)-1; } +{ return ATOMIC_SUB(ptr, 1u, almemory_order_acq_rel)-1; } /* WARNING: A livelock is theoretically possible if another thread keeps |