#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); } T operator+=(const T& other) { return fetch_add(other) + other; } T operator-=(const T& other) { return fetch_sub(other) - other; } private: T m_value; };