blob: 966e853b77fba3ed320e7326f09a1d03ee3b4686 (
plain) (
tree)
|
|
#pragma once
#include <util/system/guard.h>
#include <util/system/atomic.h>
#include <util/system/defaults.h>
#include <util/system/yassert.h>
template <class TCounterCheckPolicy>
class TSimpleCounterTemplate: public TCounterCheckPolicy {
using TCounterCheckPolicy::Check;
public:
inline TSimpleCounterTemplate(long initial = 0) noexcept
: Counter_(initial)
{
}
inline ~TSimpleCounterTemplate() {
Check();
}
inline TAtomicBase Add(TAtomicBase d) noexcept {
Check();
return Counter_ += d;
}
inline TAtomicBase Inc() noexcept {
return Add(1);
}
inline TAtomicBase Sub(TAtomicBase d) noexcept {
Check();
return Counter_ -= d;
}
inline TAtomicBase Dec() noexcept {
return Sub(1);
}
inline bool TryWeakInc() noexcept {
if (!Counter_) {
return false;
}
Inc();
Y_ASSERT(Counter_ != 0);
return true;
}
inline TAtomicBase Val() const noexcept {
return Counter_;
}
private:
TAtomicBase Counter_;
};
class TNoCheckPolicy {
protected:
inline void Check() const {
}
};
#if defined(SIMPLE_COUNTER_THREAD_CHECK)
#include <util/system/thread.i>
class TCheckPolicy {
public:
inline TCheckPolicy() {
ThreadId = SystemCurrentThreadId();
}
protected:
inline void Check() const {
Y_VERIFY(ThreadId == SystemCurrentThreadId(), "incorrect usage of TSimpleCounter");
}
private:
size_t ThreadId;
};
#else
using TCheckPolicy = TNoCheckPolicy;
#endif
// Use this one if access from multiple threads to your pointer is an error and you want to enforce thread checks
using TSimpleCounter = TSimpleCounterTemplate<TCheckPolicy>;
// Use this one if you do want to share the pointer between threads, omit thread checks and do the synchronization yourself
using TExplicitSimpleCounter = TSimpleCounterTemplate<TNoCheckPolicy>;
template <class TCounterCheckPolicy>
struct TCommonLockOps<TSimpleCounterTemplate<TCounterCheckPolicy>> {
static inline void Acquire(TSimpleCounterTemplate<TCounterCheckPolicy>* t) noexcept {
t->Inc();
}
static inline void Release(TSimpleCounterTemplate<TCounterCheckPolicy>* t) noexcept {
t->Dec();
}
};
class TAtomicCounter {
public:
inline TAtomicCounter(long initial = 0) noexcept
: Counter_(initial)
{
}
inline ~TAtomicCounter() = default;
inline TAtomicBase Add(TAtomicBase d) noexcept {
return AtomicAdd(Counter_, d);
}
inline TAtomicBase Inc() noexcept {
return Add(1);
}
inline TAtomicBase Sub(TAtomicBase d) noexcept {
return AtomicSub(Counter_, d);
}
inline TAtomicBase Dec() noexcept {
return Sub(1);
}
inline TAtomicBase Val() const noexcept {
return AtomicGet(Counter_);
}
inline bool TryWeakInc() noexcept {
while (true) {
intptr_t curValue = Counter_;
if (!curValue) {
return false;
}
intptr_t newValue = curValue + 1;
Y_ASSERT(newValue != 0);
if (AtomicCas(&Counter_, newValue, curValue)) {
return true;
}
}
}
private:
TAtomic Counter_;
};
template <>
struct TCommonLockOps<TAtomicCounter> {
static inline void Acquire(TAtomicCounter* t) noexcept {
t->Inc();
}
static inline void Release(TAtomicCounter* t) noexcept {
t->Dec();
}
};
|