119 lines
3.0 KiB
C++
119 lines
3.0 KiB
C++
#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 <typename T> 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;
|
|
};
|