diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/generic/refcount.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/generic/refcount.h')
-rw-r--r-- | util/generic/refcount.h | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/util/generic/refcount.h b/util/generic/refcount.h new file mode 100644 index 0000000000..966e853b77 --- /dev/null +++ b/util/generic/refcount.h @@ -0,0 +1,162 @@ +#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(); + } +}; |