#pragma once #include #include #include #include template 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 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; // Use this one if you do want to share the pointer between threads, omit thread checks and do the synchronization yourself using TExplicitSimpleCounter = TSimpleCounterTemplate; template struct TCommonLockOps> { static inline void Acquire(TSimpleCounterTemplate* t) noexcept { t->Inc(); } static inline void Release(TSimpleCounterTemplate* 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 { static inline void Acquire(TAtomicCounter* t) noexcept { t->Inc(); } static inline void Release(TAtomicCounter* t) noexcept { t->Dec(); } };