diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /library/cpp/neh/smart_ptr.h | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'library/cpp/neh/smart_ptr.h')
-rw-r--r-- | library/cpp/neh/smart_ptr.h | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/library/cpp/neh/smart_ptr.h b/library/cpp/neh/smart_ptr.h new file mode 100644 index 00000000000..1ec4653304b --- /dev/null +++ b/library/cpp/neh/smart_ptr.h @@ -0,0 +1,332 @@ +#pragma once + +#include <util/generic/ptr.h> +#include <library/cpp/deprecated/atomic/atomic.h> + +namespace NNeh { + //limited emulation shared_ptr/weak_ptr from boost lib. + //the main value means the weak_ptr functionality, else recommended use types from util/generic/ptr.h + + //smart pointer counter shared between shared and weak ptrs. + class TSPCounted: public TThrRefBase { + public: + inline TSPCounted() noexcept + : C_(0) + { + } + + inline void Inc() noexcept { + AtomicIncrement(C_); + } + + //return false if C_ already 0, else increment and return true + inline bool TryInc() noexcept { + for (;;) { + intptr_t curVal(AtomicGet(C_)); + + if (!curVal) { + return false; + } + + intptr_t newVal(curVal + 1); + + if (AtomicCas(&C_, newVal, curVal)) { + return true; + } + } + } + + inline intptr_t Dec() noexcept { + return AtomicDecrement(C_); + } + + inline intptr_t Value() const noexcept { + return AtomicGet(C_); + } + + private: + TAtomic C_; + }; + + typedef TIntrusivePtr<TSPCounted> TSPCountedRef; + + class TWeakCount; + + class TSPCount { + public: + TSPCount(TSPCounted* c = nullptr) noexcept + : C_(c) + { + } + + inline void Swap(TSPCount& r) noexcept { + DoSwap(C_, r.C_); + } + + inline size_t UseCount() const noexcept { + if (!C_) { + return 0; + } + return C_->Value(); + } + + inline bool operator!() const noexcept { + return !C_; + } + + inline TSPCounted* GetCounted() const noexcept { + return C_.Get(); + } + + inline void Reset() noexcept { + if (!!C_) { + C_.Drop(); + } + } + + protected: + TIntrusivePtr<TSPCounted> C_; + }; + + class TSharedCount: public TSPCount { + public: + inline TSharedCount() noexcept { + } + + /// @throws std::bad_alloc + inline explicit TSharedCount(const TSharedCount& r) + : TSPCount(r.C_.Get()) + { + if (!!C_) { + (C_->Inc()); + } + } + + //'c' must exist and has already increased ref + inline explicit TSharedCount(TSPCounted* c) noexcept + : TSPCount(c) + { + } + + public: + /// @throws std::bad_alloc + inline void Inc() { + if (!C_) { + TSPCountedRef(new TSPCounted()).Swap(C_); + } + C_->Inc(); + } + + inline bool TryInc() noexcept { + if (!C_) { + return false; + } + return C_->TryInc(); + } + + inline intptr_t Dec() noexcept { + if (!C_) { + Y_ASSERT(0); + return 0; + } + return C_->Dec(); + } + + void Drop() noexcept { + C_.Drop(); + } + + protected: + template <class Y> + friend class TSharedPtrB; + + // 'c' MUST BE already incremented + void Assign(TSPCounted* c) noexcept { + TSPCountedRef(c).Swap(C_); + } + + private: + TSharedCount& operator=(const TSharedCount&); //disable + }; + + class TWeakCount: public TSPCount { + public: + inline TWeakCount() noexcept { + } + + inline explicit TWeakCount(const TWeakCount& r) noexcept + : TSPCount(r.GetCounted()) + { + } + + inline explicit TWeakCount(const TSharedCount& r) noexcept + : TSPCount(r.GetCounted()) + { + } + + private: + TWeakCount& operator=(const TWeakCount&); //disable + }; + + template <class T> + class TWeakPtrB; + + template <class T> + class TSharedPtrB { + public: + inline TSharedPtrB() noexcept + : T_(nullptr) + { + } + + /// @throws std::bad_alloc + inline TSharedPtrB(T* t) + : T_(nullptr) + { + if (t) { + THolder<T> h(t); + C_.Inc(); + T_ = h.Release(); + } + } + + inline TSharedPtrB(const TSharedPtrB<T>& r) noexcept + : T_(r.T_) + , C_(r.C_) + { + Y_ASSERT((!!T_ && !!C_.UseCount()) || (!T_ && !C_.UseCount())); + } + + inline TSharedPtrB(const TWeakPtrB<T>& r) noexcept + : T_(r.T_) + { + if (T_) { + TSPCounted* spc = r.C_.GetCounted(); + + if (spc && spc->TryInc()) { + C_.Assign(spc); + } else { //obsolete ptr + T_ = nullptr; + } + } + } + + inline ~TSharedPtrB() { + Reset(); + } + + TSharedPtrB& operator=(const TSharedPtrB<T>& r) noexcept { + TSharedPtrB<T>(r).Swap(*this); + return *this; + } + + TSharedPtrB& operator=(const TWeakPtrB<T>& r) noexcept { + TSharedPtrB<T>(r).Swap(*this); + return *this; + } + + void Swap(TSharedPtrB<T>& r) noexcept { + DoSwap(T_, r.T_); + DoSwap(C_, r.C_); + Y_ASSERT((!!T_ && !!UseCount()) || (!T_ && !UseCount())); + } + + inline bool operator!() const noexcept { + return !T_; + } + + inline T* Get() noexcept { + return T_; + } + + inline T* operator->() noexcept { + return T_; + } + + inline T* operator->() const noexcept { + return T_; + } + + inline T& operator*() noexcept { + return *T_; + } + + inline T& operator*() const noexcept { + return *T_; + } + + inline void Reset() noexcept { + if (T_) { + if (C_.Dec() == 0) { + delete T_; + } + T_ = nullptr; + C_.Drop(); + } + } + + inline size_t UseCount() const noexcept { + return C_.UseCount(); + } + + protected: + template <class Y> + friend class TWeakPtrB; + + T* T_; + TSharedCount C_; + }; + + template <class T> + class TWeakPtrB { + public: + inline TWeakPtrB() noexcept + : T_(nullptr) + { + } + + inline TWeakPtrB(const TWeakPtrB<T>& r) noexcept + : T_(r.T_) + , C_(r.C_) + { + } + + inline TWeakPtrB(const TSharedPtrB<T>& r) noexcept + : T_(r.T_) + , C_(r.C_) + { + } + + TWeakPtrB& operator=(const TWeakPtrB<T>& r) noexcept { + TWeakPtrB(r).Swap(*this); + return *this; + } + + TWeakPtrB& operator=(const TSharedPtrB<T>& r) noexcept { + TWeakPtrB(r).Swap(*this); + return *this; + } + + inline void Swap(TWeakPtrB<T>& r) noexcept { + DoSwap(T_, r.T_); + DoSwap(C_, r.C_); + } + + inline void Reset() noexcept { + T_ = 0; + C_.Reset(); + } + + inline size_t UseCount() const noexcept { + return C_.UseCount(); + } + + protected: + template <class Y> + friend class TSharedPtrB; + + T* T_; + TWeakCount C_; + }; + +} |