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.
This commit is contained in:
Chris Robinson
2018-10-29 20:50:57 -07:00
parent 5fea511cce
commit 3deb7c6ed5
+49 -5
View File
@@ -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