atomic.h: use strongly typed enum

master
Daniel Kolesa 2015-05-20 00:24:20 +01:00
parent 559a1afd26
commit 25fb30b524
1 changed files with 53 additions and 53 deletions

View File

@ -13,14 +13,14 @@
#include "octa/type_traits.h" #include "octa/type_traits.h"
namespace octa { namespace octa {
typedef enum MemoryOrder { enum class MemoryOrder {
memory_order_relaxed = 0, relaxed = 0,
memory_order_consume, consume,
memory_order_acquire, acquire,
memory_order_release, release,
memory_order_acq_rel, acq_rel,
memory_order_seq_cst seq_cst
} MemoryOrder; };
template<typename T> template<typename T>
struct __OctaAtomicBase { struct __OctaAtomicBase {
@ -90,9 +90,9 @@ namespace octa {
#define ATOMIC_POINTER_LOCK_FREE 2 #define ATOMIC_POINTER_LOCK_FREE 2
static inline void __octa_atomic_thread_fence(MemoryOrder ord) { static inline void __octa_atomic_thread_fence(MemoryOrder ord) {
if (ord > memory_order_consume) { if (ord > MemoryOrder::consume) {
_ReadWriteBarrier(); _ReadWriteBarrier();
if (ord == memory_order_seq_cst) { if (ord == MemoryOrder::seq_cst) {
MemoryBarrier(); MemoryBarrier();
_ReadWriteBarrier(); _ReadWriteBarrier();
} }
@ -100,7 +100,7 @@ namespace octa {
} }
static inline void __octa_atomic_signal_fence(MemoryOrder ord) { static inline void __octa_atomic_signal_fence(MemoryOrder ord) {
if (ord > memory_order_consume) _ReadWriteBarrier(); if (ord > MemoryOrder::consume) _ReadWriteBarrier();
} }
static inline bool __octa_atomic_is_lock_free(size_t size) { static inline bool __octa_atomic_is_lock_free(size_t size) {
@ -114,7 +114,7 @@ namespace octa {
struct __OctaMsvcAtomicStore<T, 1> { struct __OctaMsvcAtomicStore<T, 1> {
static inline void store(volatile T *dst, T src, MemoryOrder ord) static inline void store(volatile T *dst, T src, MemoryOrder ord)
noexcept { noexcept {
if (ord == memory_order_seq_cst) if (ord == MemoryOrder::seq_cst)
InterlockedExchange8((volatile int8_t *)dst, (int8_t)src); InterlockedExchange8((volatile int8_t *)dst, (int8_t)src);
else *dst = src; else *dst = src;
} }
@ -124,7 +124,7 @@ namespace octa {
struct __OctaMsvcAtomicStore<T, 2> { struct __OctaMsvcAtomicStore<T, 2> {
static inline void store(volatile T *dst, T src, MemoryOrder ord) static inline void store(volatile T *dst, T src, MemoryOrder ord)
noexcept { noexcept {
if (ord == memory_order_seq_cst) if (ord == MemoryOrder::seq_cst)
InterlockedExchange16((volatile int16_t *)dst, (int16_t)src); InterlockedExchange16((volatile int16_t *)dst, (int16_t)src);
else *dst = src; else *dst = src;
} }
@ -134,7 +134,7 @@ namespace octa {
struct __OctaMsvcAtomicStore<T, 4> { struct __OctaMsvcAtomicStore<T, 4> {
static inline void store(volatile T *dst, T src, MemoryOrder ord) static inline void store(volatile T *dst, T src, MemoryOrder ord)
noexcept { noexcept {
if (ord == memory_order_seq_cst) if (ord == MemoryOrder::seq_cst)
InterlockedExchange((volatile int32_t *)dst, (int32_t)src); InterlockedExchange((volatile int32_t *)dst, (int32_t)src);
else *dst = src; else *dst = src;
} }
@ -144,7 +144,7 @@ namespace octa {
struct __OctaMsvcAtomicStore<T, 8> { struct __OctaMsvcAtomicStore<T, 8> {
static inline void store(volatile T *dst, T src, MemoryOrder ord) static inline void store(volatile T *dst, T src, MemoryOrder ord)
noexcept { noexcept {
if (ord == memory_order_relaxed) if (ord == MemoryOrder::relaxed)
InterlockedExchangeNoFence64((volatile int64_t *)dst, (int64_t)src); InterlockedExchangeNoFence64((volatile int64_t *)dst, (int64_t)src);
else else
InterlockedExchange64((volatile int64_t *)dst, (int64_t)src); InterlockedExchange64((volatile int64_t *)dst, (int64_t)src);
@ -475,20 +475,20 @@ namespace octa {
#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE #define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
static inline constexpr int __octa_to_gcc_order(MemoryOrder ord) { static inline constexpr int __octa_to_gcc_order(MemoryOrder ord) {
return ((ord == memory_order_relaxed) ? __ATOMIC_RELAXED : return ((ord == MemoryOrder::relaxed) ? __ATOMIC_RELAXED :
((ord == memory_order_acquire) ? __ATOMIC_ACQUIRE : ((ord == MemoryOrder::acquire) ? __ATOMIC_ACQUIRE :
((ord == memory_order_release) ? __ATOMIC_RELEASE : ((ord == MemoryOrder::release) ? __ATOMIC_RELEASE :
((ord == memory_order_seq_cst) ? __ATOMIC_SEQ_CST : ((ord == MemoryOrder::seq_cst) ? __ATOMIC_SEQ_CST :
((ord == memory_order_acq_rel) ? __ATOMIC_ACQ_REL : ((ord == MemoryOrder::acq_rel) ? __ATOMIC_ACQ_REL :
__ATOMIC_CONSUME))))); __ATOMIC_CONSUME)))));
} }
static inline constexpr int __octa_to_gcc_failure_order(MemoryOrder ord) { static inline constexpr int __octa_to_gcc_failure_order(MemoryOrder ord) {
return ((ord == memory_order_relaxed) ? __ATOMIC_RELAXED : return ((ord == MemoryOrder::relaxed) ? __ATOMIC_RELAXED :
((ord == memory_order_acquire) ? __ATOMIC_ACQUIRE : ((ord == MemoryOrder::acquire) ? __ATOMIC_ACQUIRE :
((ord == memory_order_release) ? __ATOMIC_RELAXED : ((ord == MemoryOrder::release) ? __ATOMIC_RELAXED :
((ord == memory_order_seq_cst) ? __ATOMIC_SEQ_CST : ((ord == MemoryOrder::seq_cst) ? __ATOMIC_SEQ_CST :
((ord == memory_order_acq_rel) ? __ATOMIC_ACQUIRE : ((ord == MemoryOrder::acq_rel) ? __ATOMIC_ACQUIRE :
__ATOMIC_CONSUME))))); __ATOMIC_CONSUME)))));
} }
@ -693,32 +693,32 @@ namespace octa {
return __octa_atomic_is_lock_free(sizeof(T)); return __octa_atomic_is_lock_free(sizeof(T));
} }
void store(T v, MemoryOrder ord = memory_order_seq_cst) void store(T v, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
__octa_atomic_store(&p_a, v, ord); __octa_atomic_store(&p_a, v, ord);
} }
void store(T v, MemoryOrder ord = memory_order_seq_cst) noexcept { void store(T v, MemoryOrder ord = MemoryOrder::seq_cst) noexcept {
__octa_atomic_store(&p_a, v, ord); __octa_atomic_store(&p_a, v, ord);
} }
T load(MemoryOrder ord = memory_order_seq_cst) const volatile noexcept { T load(MemoryOrder ord = MemoryOrder::seq_cst) const volatile noexcept {
return __octa_atomic_load(&p_a, ord); return __octa_atomic_load(&p_a, ord);
} }
T load(MemoryOrder ord = memory_order_seq_cst) const noexcept { T load(MemoryOrder ord = MemoryOrder::seq_cst) const noexcept {
return __octa_atomic_load(&p_a, ord); return __octa_atomic_load(&p_a, ord);
} }
operator T() const volatile noexcept { return load(); } operator T() const volatile noexcept { return load(); }
operator T() const noexcept { return load(); } operator T() const noexcept { return load(); }
T exchange(T v, MemoryOrder ord = memory_order_seq_cst) T exchange(T v, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_exchange(&p_a, v, ord); return __octa_atomic_exchange(&p_a, v, ord);
} }
T exchange(T v, MemoryOrder ord = memory_order_seq_cst) noexcept { T exchange(T v, MemoryOrder ord = MemoryOrder::seq_cst) noexcept {
return __octa_atomic_exchange(&p_a, v, ord); return __octa_atomic_exchange(&p_a, v, ord);
} }
@ -743,25 +743,25 @@ namespace octa {
} }
bool compare_exchange_weak(T& e, T v, MemoryOrder ord bool compare_exchange_weak(T& e, T v, MemoryOrder ord
= memory_order_seq_cst) = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_compare_exchange_weak(&p_a, &e, v, ord, ord); return __octa_atomic_compare_exchange_weak(&p_a, &e, v, ord, ord);
} }
bool compare_exchange_weak(T& e, T v, MemoryOrder ord bool compare_exchange_weak(T& e, T v, MemoryOrder ord
= memory_order_seq_cst) = MemoryOrder::seq_cst)
noexcept { noexcept {
return __octa_atomic_compare_exchange_weak(&p_a, &e, v, ord, ord); return __octa_atomic_compare_exchange_weak(&p_a, &e, v, ord, ord);
} }
bool compare_exchange_strong(T& e, T v, MemoryOrder ord bool compare_exchange_strong(T& e, T v, MemoryOrder ord
= memory_order_seq_cst) = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_compare_exchange_strong(&p_a, &e, v, ord, ord); return __octa_atomic_compare_exchange_strong(&p_a, &e, v, ord, ord);
} }
bool compare_exchange_strong(T& e, T v, MemoryOrder ord bool compare_exchange_strong(T& e, T v, MemoryOrder ord
= memory_order_seq_cst) = MemoryOrder::seq_cst)
noexcept { noexcept {
return __octa_atomic_compare_exchange_strong(&p_a, &e, v, ord, ord); return __octa_atomic_compare_exchange_strong(&p_a, &e, v, ord, ord);
} }
@ -775,48 +775,48 @@ namespace octa {
constexpr __OctaAtomic(T v) noexcept: base_t(v) {} constexpr __OctaAtomic(T v) noexcept: base_t(v) {}
T fetch_add(T op, MemoryOrder ord = memory_order_seq_cst) T fetch_add(T op, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_fetch_add(&this->p_a, op, ord); return __octa_atomic_fetch_add(&this->p_a, op, ord);
} }
T fetch_add(T op, MemoryOrder ord = memory_order_seq_cst) noexcept { T fetch_add(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept {
return __octa_atomic_fetch_add(&this->p_a, op, ord); return __octa_atomic_fetch_add(&this->p_a, op, ord);
} }
T fetch_sub(T op, MemoryOrder ord = memory_order_seq_cst) T fetch_sub(T op, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_fetch_sub(&this->p_a, op, ord); return __octa_atomic_fetch_sub(&this->p_a, op, ord);
} }
T fetch_sub(T op, MemoryOrder ord = memory_order_seq_cst) noexcept { T fetch_sub(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept {
return __octa_atomic_fetch_sub(&this->p_a, op, ord); return __octa_atomic_fetch_sub(&this->p_a, op, ord);
} }
T fetch_and(T op, MemoryOrder ord = memory_order_seq_cst) T fetch_and(T op, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_fetch_and(&this->p_a, op, ord); return __octa_atomic_fetch_and(&this->p_a, op, ord);
} }
T fetch_and(T op, MemoryOrder ord = memory_order_seq_cst) noexcept { T fetch_and(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept {
return __octa_atomic_fetch_and(&this->p_a, op, ord); return __octa_atomic_fetch_and(&this->p_a, op, ord);
} }
T fetch_or(T op, MemoryOrder ord = memory_order_seq_cst) T fetch_or(T op, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_fetch_or(&this->p_a, op, ord); return __octa_atomic_fetch_or(&this->p_a, op, ord);
} }
T fetch_or(T op, MemoryOrder ord = memory_order_seq_cst) noexcept { T fetch_or(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept {
return __octa_atomic_fetch_or(&this->p_a, op, ord); return __octa_atomic_fetch_or(&this->p_a, op, ord);
} }
T fetch_xor(T op, MemoryOrder ord = memory_order_seq_cst) T fetch_xor(T op, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_fetch_xor(&this->p_a, op, ord); return __octa_atomic_fetch_xor(&this->p_a, op, ord);
} }
T fetch_xor(T op, MemoryOrder ord = memory_order_seq_cst) noexcept { T fetch_xor(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept {
return __octa_atomic_fetch_xor(&this->p_a, op, ord); return __octa_atomic_fetch_xor(&this->p_a, op, ord);
} }
@ -874,22 +874,22 @@ namespace octa {
base_t::store(v); return v; base_t::store(v); return v;
} }
T *fetch_add(ptrdiff_t op, MemoryOrder ord = memory_order_seq_cst) T *fetch_add(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_fetch_add(&this->p_a, op, ord); return __octa_atomic_fetch_add(&this->p_a, op, ord);
} }
T *fetch_add(ptrdiff_t op, MemoryOrder ord = memory_order_seq_cst) T *fetch_add(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst)
noexcept { noexcept {
return __octa_atomic_fetch_add(&this->p_a, op, ord); return __octa_atomic_fetch_add(&this->p_a, op, ord);
} }
T *fetch_sub(ptrdiff_t op, MemoryOrder ord = memory_order_seq_cst) T *fetch_sub(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_fetch_sub(&this->p_a, op, ord); return __octa_atomic_fetch_sub(&this->p_a, op, ord);
} }
T *fetch_sub(ptrdiff_t op, MemoryOrder ord = memory_order_seq_cst) T *fetch_sub(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst)
noexcept { noexcept {
return __octa_atomic_fetch_sub(&this->p_a, op, ord); return __octa_atomic_fetch_sub(&this->p_a, op, ord);
} }
@ -1241,20 +1241,20 @@ namespace octa {
AtomicFlag &operator=(const AtomicFlag &) = delete; AtomicFlag &operator=(const AtomicFlag &) = delete;
AtomicFlag &operator=(const AtomicFlag &) volatile = delete; AtomicFlag &operator=(const AtomicFlag &) volatile = delete;
bool test_and_set(MemoryOrder ord = memory_order_seq_cst) bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile noexcept {
return __octa_atomic_exchange(&p_a, true, ord); return __octa_atomic_exchange(&p_a, true, ord);
} }
bool test_and_set(MemoryOrder ord = memory_order_seq_cst) noexcept { bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst) noexcept {
return __octa_atomic_exchange(&p_a, true, ord); return __octa_atomic_exchange(&p_a, true, ord);
} }
void clear(MemoryOrder ord = memory_order_seq_cst) volatile noexcept { void clear(MemoryOrder ord = MemoryOrder::seq_cst) volatile noexcept {
__octa_atomic_store(&p_a, false, ord); __octa_atomic_store(&p_a, false, ord);
} }
void clear(MemoryOrder ord = memory_order_seq_cst) noexcept { void clear(MemoryOrder ord = MemoryOrder::seq_cst) noexcept {
__octa_atomic_store(&p_a, false, ord); __octa_atomic_store(&p_a, false, ord);
} }
}; };