aboutsummaryrefslogtreecommitdiffstats
path: root/common/atomic.h
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2018-10-29 20:50:57 -0700
committerChris Robinson <[email protected]>2018-10-29 20:50:57 -0700
commit3deb7c6ed5105a54c6cea01318099494ba1ee9b6 (patch)
treea6103b3dbb85fe0cb2e7b843d4491a86167a1832 /common/atomic.h
parent5fea511ccec500f575898df33e9934dec075527c (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.h54
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