Program Listing for File counters.h
↰ Return to documentation for file (include/embers/primitives/counters.h
)
/* Copyright © 2020 Advanced Micro Devices, Inc. All rights reserved */
#ifndef _EMBERS_COUNTERS_H_
#define _EMBERS_COUNTERS_H_
#include <thread>
#include <type_traits>
#include "embers/atomic.h"
#include "embers/primitives/backoff.h"
namespace embers
{
template <MemoryScope scope_ = MemoryScope::SYSTEM,
std::memory_order order_ = std::memory_order_seq_cst, typename SIntType_ = int,
typename enable_ = std::enable_if_t<std::is_integral<SIntType_>::value &&
std::is_signed<SIntType_>::value> >
class MonotonicCounter
{
private:
atomic<SIntType_, scope_> value_;
public:
typedef SIntType_ counter_int_type;
__host__ MonotonicCounter();
__host__ ~MonotonicCounter() = default;
__host__ MonotonicCounter(MonotonicCounter &) = delete;
__host__ MonotonicCounter &operator=(const MonotonicCounter &) = delete;
__host__ MonotonicCounter(MonotonicCounter &&) = default;
__host__ __device__ SIntType_ Value() const noexcept;
__host__ __device__ void Increment(SIntType_ amount) noexcept;
__host__ __device__ void Check(SIntType_ val) const noexcept;
__host__ __device__ bool Appoint(SIntType_ *val, SIntType_ num) noexcept;
__host__ __device__ void Reset() noexcept;
};
template <MemoryScope scope_, std::memory_order order_, typename SIntType_, typename enable_>
MonotonicCounter<scope_, order_, SIntType_, enable_>::MonotonicCounter()
: value_(atomic<SIntType_>(static_cast<SIntType_>(0)))
{
Reset();
}
template <MemoryScope scope_, std::memory_order order_, typename SIntType_, typename enable_>
__host__ __device__ void MonotonicCounter<scope_, order_, SIntType_, enable_>::Reset() noexcept
{
value_.store(static_cast<SIntType_>(0), std::memory_order_release);
}
template <MemoryScope scope_, std::memory_order order_, typename SIntType_, typename enable_>
__host__ __device__ void MonotonicCounter<scope_, order_, SIntType_, enable_>::Increment(
SIntType_ amount) noexcept
{
value_.fetch_add(amount, order_);
}
template <MemoryScope scope_, std::memory_order order_, typename SIntType_, typename enable_>
__host__ __device__ SIntType_
MonotonicCounter<scope_, order_, SIntType_, enable_>::Value() const noexcept
{
return value_.load(order_);
}
template <MemoryScope scope_, std::memory_order order_, typename SIntType_, typename enable_>
__host__ __device__ void MonotonicCounter<scope_, order_, SIntType_, enable_>::Check(
SIntType_ level) const noexcept
{
while (Value() < level) backoff();
}
template <MemoryScope scope_, std::memory_order order_, typename SIntType_, typename enable_>
__host__ __device__ bool MonotonicCounter<scope_, order_, SIntType_, enable_>::Appoint(
SIntType_ *val, SIntType_ num) noexcept
{
auto expected = value_.load(order_);
bool success = value_.compare_exchange_strong(expected, value_.load(order_) + num, order_,
order_);
if (success) {
*val = expected;
}
return success;
}
} // namespace embers
#endif // _EMBERS_COUNTERS_H_