diff --git a/luna/include/luna/Atomic.h b/luna/include/luna/Atomic.h new file mode 100644 index 00000000..d6be5f93 --- /dev/null +++ b/luna/include/luna/Atomic.h @@ -0,0 +1,108 @@ +#pragma once + +enum class MemoryOrder +{ + Relaxed = __ATOMIC_RELAXED, + Consume = __ATOMIC_CONSUME, + Acquire = __ATOMIC_ACQUIRE, + Release = __ATOMIC_RELEASE, + AcqRel = __ATOMIC_ACQ_REL, + SeqCst = __ATOMIC_SEQ_CST, +}; + +template class Atomic +{ + public: + Atomic() : m_value() + { + } + + Atomic(T value) : m_value(value) + { + } + + T operator=(T other) + { + store(other); + return other; + } + + T load(MemoryOrder order = MemoryOrder::SeqCst) const + { + return __atomic_load_n(&m_value, (int)order); + } + + operator T() const + { + return load(); + } + + void store(T value, MemoryOrder order = MemoryOrder::SeqCst) + { + return __atomic_store_n(&m_value, value, (int)order); + } + + T exchange(T value, MemoryOrder order = MemoryOrder::SeqCst) + { + return __atomic_exchange_n(&m_value, value, (int)order); + } + + bool compare_exchange_strong(T& expected, T desired, MemoryOrder success, MemoryOrder failure) + { + return __atomic_compare_exchange_n(&m_value, &expected, desired, false, (int)success, (int)failure); + } + + bool compare_exchange_strong(T& expected, T desired, MemoryOrder order = MemoryOrder::SeqCst) + { + MemoryOrder failure = (order == MemoryOrder::AcqRel) ? MemoryOrder::Acquire + : (order == MemoryOrder::Release) ? MemoryOrder::Relaxed + : order; + return __atomic_compare_exchange_n(&m_value, &expected, desired, false, (int)order, (int)failure); + } + + bool compare_exchange_weak(T& expected, T desired, MemoryOrder success, MemoryOrder failure) + { + return __atomic_compare_exchange_n(&m_value, &expected, desired, true, (int)success, (int)failure); + } + + bool compare_exchange_weak(T& expected, T desired, MemoryOrder order = MemoryOrder::SeqCst) + { + MemoryOrder failure = (order == MemoryOrder::AcqRel) ? MemoryOrder::Acquire + : (order == MemoryOrder::Release) ? MemoryOrder::Relaxed + : order; + return __atomic_compare_exchange_n(&m_value, &expected, desired, true, (int)order, (int)failure); + } + + T fetch_add(T other, MemoryOrder order = MemoryOrder::SeqCst) + { + return __atomic_fetch_add(&m_value, other, (int)order); + } + + T fetch_sub(T other, MemoryOrder order = MemoryOrder::SeqCst) + { + return __atomic_fetch_sub(&m_value, other, (int)order); + } + + T operator++() + { + return fetch_add(1) + 1; + } + + T operator++(int) + { + return fetch_add(1); + } + + T operator--() + { + return fetch_sub(1) - 1; + } + + T operator--(int) + { + return fetch_sub(1); + } + + private: + T m_value; +}; \ No newline at end of file