89 lines
No EOL
2.1 KiB
C++
89 lines
No EOL
2.1 KiB
C++
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <type_traits>
|
|
|
|
namespace nano
|
|
{
|
|
/* Default memory order of normal std::atomic operations is std::memory_order_seq_cst which provides
|
|
a total global ordering of atomic operations as well as synchronization between threads. Weaker memory
|
|
ordering can provide benefits in some circumstances, like dumb counters where no other data is
|
|
dependent on the ordering of these operations. This assumes T is a type of integer, not bool or char. */
|
|
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
|
|
class relaxed_atomic_integral
|
|
{
|
|
public:
|
|
relaxed_atomic_integral () noexcept = default;
|
|
constexpr relaxed_atomic_integral (T desired) noexcept :
|
|
atomic (desired)
|
|
{
|
|
}
|
|
|
|
T operator= (T desired) noexcept
|
|
{
|
|
store (desired);
|
|
return atomic;
|
|
}
|
|
|
|
relaxed_atomic_integral (relaxed_atomic_integral const &) = delete;
|
|
relaxed_atomic_integral & operator= (relaxed_atomic_integral const &) = delete;
|
|
|
|
void store (T desired, std::memory_order order = std::memory_order_relaxed) noexcept
|
|
{
|
|
atomic.store (desired, order);
|
|
}
|
|
|
|
T load (std::memory_order order = std::memory_order_relaxed) const noexcept
|
|
{
|
|
return atomic.load (std::memory_order_relaxed);
|
|
}
|
|
|
|
operator T () const noexcept
|
|
{
|
|
return load ();
|
|
}
|
|
|
|
bool compare_exchange_weak (T & expected, T desired, std::memory_order order = std::memory_order_relaxed) noexcept
|
|
{
|
|
return atomic.compare_exchange_weak (expected, desired, order);
|
|
}
|
|
|
|
bool compare_exchange_strong (T & expected, T desired, std::memory_order order = std::memory_order_relaxed) noexcept
|
|
{
|
|
return atomic.compare_exchange_strong (expected, desired, order);
|
|
}
|
|
|
|
T fetch_add (T arg, std::memory_order order = std::memory_order_relaxed) noexcept
|
|
{
|
|
return atomic.fetch_add (arg, order);
|
|
}
|
|
|
|
T fetch_sub (T arg, std::memory_order order = std::memory_order_relaxed) noexcept
|
|
{
|
|
return atomic.fetch_sub (arg, order);
|
|
}
|
|
|
|
T operator++ () noexcept
|
|
{
|
|
return fetch_add (1) + 1;
|
|
}
|
|
|
|
T operator++ (int) noexcept
|
|
{
|
|
return fetch_add (1);
|
|
}
|
|
|
|
T operator-- () noexcept
|
|
{
|
|
return fetch_sub (1) - 1;
|
|
}
|
|
|
|
T operator-- (int) noexcept
|
|
{
|
|
return fetch_sub (1);
|
|
}
|
|
|
|
private:
|
|
std::atomic<T> atomic;
|
|
};
|
|
} |