68#ifndef PERFC_COUNTER_HPP_
69#define PERFC_COUNTER_HPP_
81enum class MemoryOrder : std::underlying_type_t<std::memory_order> {
85 Release =
static_cast<std::underlying_type_t<std::memory_order>
>(std::memory_order_release),
90 Acquire =
static_cast<std::underlying_type_t<std::memory_order>
>(std::memory_order_acquire),
97 Relaxed =
static_cast<std::underlying_type_t<std::memory_order>
>(std::memory_order_relaxed),
111template <
class T,
class TimePo
int>
117template <
class T,
class Clock = std::chrono::steady_clock,
class =
void>
140class Counter<T, void, typename std::enable_if<std::is_integral<T>::value>::type> {
163 explicit Counter(T value) noexcept : m_value(value) {
173 return m_value.is_lock_free();
183 return m_value.store(value,
static_cast<std::memory_order
>(order));
193 return m_value.load(
static_cast<std::memory_order
>(order));
204 return m_value.fetch_add(value,
static_cast<std::memory_order
>(order));
216 return m_value.fetch_sub(value,
static_cast<std::memory_order
>(order));
286class Counter<T, void, typename std::enable_if<!std::is_integral<T>::value>::type> {
308 explicit Counter(T value) noexcept : m_value(value) {
319 return m_value.is_lock_free();
329 return m_value.store(value,
static_cast<std::memory_order
>(order));
339 return m_value.load(
static_cast<std::memory_order
>(order));
363template <
class T,
class Clock>
364class Counter<T, Clock, typename std::enable_if<!std::is_void<Clock>::value>::type> {
387 explicit Counter(T value) noexcept : m_value({value, ClockType::now()}) {
406 return m_value.is_lock_free();
416 return m_value.store({value, ClockType::now()},
static_cast<std::memory_order
>(order));
426 return m_value.store(value,
static_cast<std::memory_order
>(order));
436 return m_value.load(
static_cast<std::memory_order
>(order));
459 std::atomic_thread_fence(std::memory_order_acquire);
472 std::atomic_thread_fence(std::memory_order_release);
void Store(ValueType value, MemoryOrder order=MemoryOrder::Release) noexcept
Store value with provided timestamp in counter.
ValueType Load(MemoryOrder order=MemoryOrder::Acquire) const noexcept
Load value and timestamp from counter.
bool IsLockFree() const noexcept
Query if operations are lock free.
void Store(T value, MemoryOrder order=MemoryOrder::Release) noexcept
Stores provided value and with current time by querying clock.
Counter() noexcept
Construct with value-initialized T (T())
Counter(ValueType value) noexcept
Initialze with value and time.
typename ClockType::time_point TimePointType
std::atomic< ValueType > CounterType
Counter(Counter const &)=delete
static constexpr bool IS_ALWAYS_LOCK_FREE
Is true if counter is always lock free.
Timestamped< T, TimePointType > ValueType
Counter(T value) noexcept
Initialze with a value using current time.
T operator++(int) noexcept
Post-increment operator using default memory order.
T operator-=(T value) noexcept
Performs subtraction (equivalent to FetchSub(value) - value
T operator+=(T value) noexcept
Performs addition (equivalent to FetchAdd(value) + value
void Store(T value, MemoryOrder order=MemoryOrder::Release) noexcept
Stores provided value in counter.
std::atomic< T > CounterType
T FetchAdd(T value, MemoryOrder order=MemoryOrder::Release) noexcept
Perform post-increment with current value and value.
Counter() noexcept
Construct with value-initialized T (T())
T FetchSub(T value, MemoryOrder order=MemoryOrder::Release) noexcept
Load value from counter.
static constexpr bool IS_ALWAYS_LOCK_FREE
Is true if counter is always lock free.
bool IsLockFree() const noexcept
Query if operations are lock free.
T operator--() noexcept
Pre-decrement operator using default memory order.
Counter(T value) noexcept
Construct with initial value value.
Counter(Counter const &)=delete
T Load(MemoryOrder order=MemoryOrder::Acquire) const noexcept
Load value from counter.
T operator--(int) noexcept
Post-decrement operator using default memory order.
T operator++() noexcept
Pre-increment operator using default memory order.
std::atomic< ValueType > CounterType
Counter(T value) noexcept
Initialze with provided value.
void Store(T value, MemoryOrder order=MemoryOrder::Release) noexcept
Store value in counter.
Counter(Counter const &)=delete
bool IsLockFree() const noexcept
Query if operations are lock free.
ValueType Load(MemoryOrder order=MemoryOrder::Acquire) const noexcept
Load value from counter.
Counter() noexcept
Construct with value-initialized T (T())
static constexpr bool IS_ALWAYS_LOCK_FREE
Is true if counter is always lock free.
void CounterRelease() noexcept
Synchronizes-with CounterAcquire() or counter load operations using MemoryOrder::Acquire.
MemoryOrder
Memory ordering constraints.
Counter< double, void > CounterDouble
Counter< std::uint64_t, std::chrono::steady_clock > CounterU64Ts
Counter< std::int64_t, void > CounterI64
Counter< std::uint64_t, void > CounterU64
Counter< double, std::chrono::steady_clock > CounterDoubleTs
void CounterAcquire() noexcept
Synchronizes-with CounterRelease() or Counter store operations using MemoryOrder::Release.
Counter< std::int64_t, std::chrono::steady_clock > CounterI64Ts
Trivial type describing a counter value and associated timestamp.