1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174 |
- #pragma once
- #include "fwd.h"
- #include "utility.h"
- #include "intrlist.h"
- #include "refcount.h"
- #include "typetraits.h"
- #include "singleton.h"
- #include <type_traits>
- #include <utility>
- #include <util/system/compiler.h>
- #include <util/system/defaults.h>
- #include <util/system/yassert.h>
- template <class T, class U>
- using TGuardConversion = typename std::enable_if_t<std::is_convertible<U*, T*>::value>;
- template <class T>
- inline void AssertTypeComplete() {
- // If compiler triggers this error from destructor of your class with
- // smart pointer, then may be you should move the destructor definition
- // to the .cpp file, where type T have full definition.
- //
- // 'delete' called on pointer to incomplete type is
- // undefined behavior (missing destructor call/corrupted memory manager).
- // 'sizeof' is used to trigger compile-time error.
- static_assert(sizeof(T) != 0, "Type must be complete");
- }
- template <class T>
- inline void CheckedDelete(T* t) {
- AssertTypeComplete<T>();
- delete t;
- }
- template <class T>
- inline void CheckedArrayDelete(T* t) {
- AssertTypeComplete<T>();
- delete[] t;
- }
- class TNoAction {
- public:
- template <class T>
- static inline void Destroy(T*) noexcept {
- }
- };
- class TDelete {
- public:
- template <class T>
- static inline void Destroy(T* t) noexcept {
- CheckedDelete(t);
- }
- /*
- * special handling for nullptr - call nothing
- */
- static inline void Destroy(std::nullptr_t) noexcept {
- }
- /*
- * special handling for void* - call ::operator delete()
- */
- static void Destroy(void* t) noexcept;
- };
- class TDeleteArray {
- public:
- template <class T>
- static inline void Destroy(T* t) noexcept {
- CheckedArrayDelete(t);
- }
- };
- class TDestructor {
- public:
- template <class T>
- static inline void Destroy(T* t) noexcept {
- (void)t;
- t->~T();
- }
- };
- class TFree {
- public:
- template <class T>
- static inline void Destroy(T* t) noexcept {
- DoDestroy((void*)t);
- }
- private:
- /*
- * we do not want dependancy on cstdlib here...
- */
- static void DoDestroy(void* t) noexcept;
- };
- template <class Base, class T>
- class TPointerCommon {
- public:
- using TValueType = T;
- inline T* operator->() const noexcept {
- T* ptr = AsT();
- Y_ASSERT(ptr);
- return ptr;
- }
- #ifndef __cpp_impl_three_way_comparison
- template <class C>
- inline bool operator==(const C& p) const noexcept {
- return (p == AsT());
- }
- template <class C>
- inline bool operator!=(const C& p) const noexcept {
- return (p != AsT());
- }
- #endif
- inline explicit operator bool() const noexcept {
- return nullptr != AsT();
- }
- protected:
- inline T* AsT() const noexcept {
- return (static_cast<const Base*>(this))->Get();
- }
- static inline T* DoRelease(T*& t) noexcept {
- T* ret = t;
- t = nullptr;
- return ret;
- }
- };
- template <class Base, class T>
- class TPointerBase: public TPointerCommon<Base, T> {
- public:
- inline T& operator*() const noexcept {
- Y_ASSERT(this->AsT());
- return *(this->AsT());
- }
- inline T& operator[](size_t n) const noexcept {
- Y_ASSERT(this->AsT());
- return (this->AsT())[n];
- }
- };
- /*
- * void*-like pointers does not have operator*
- */
- template <class Base>
- class TPointerBase<Base, void>: public TPointerCommon<Base, void> {
- };
- template <class T, class D>
- class TAutoPtr: public TPointerBase<TAutoPtr<T, D>, T> {
- public:
- inline TAutoPtr(T* t = nullptr) noexcept
- : T_(t)
- {
- }
- inline TAutoPtr(const TAutoPtr& t) noexcept
- : T_(t.Release())
- {
- }
- inline ~TAutoPtr() {
- DoDestroy();
- }
- inline TAutoPtr& operator=(const TAutoPtr& t) noexcept {
- if (this != &t) {
- Reset(t.Release());
- }
- return *this;
- }
- inline T* Release() const noexcept Y_WARN_UNUSED_RESULT {
- return this->DoRelease(T_);
- }
- Y_REINITIALIZES_OBJECT inline void Reset(T* t) noexcept {
- if (T_ != t) {
- DoDestroy();
- T_ = t;
- }
- }
- Y_REINITIALIZES_OBJECT inline void Reset() noexcept {
- Destroy();
- }
- inline void Destroy() noexcept {
- Reset(nullptr);
- }
- inline void Swap(TAutoPtr& r) noexcept {
- DoSwap(T_, r.T_);
- }
- inline T* Get() const noexcept {
- return T_;
- }
- #ifdef __cpp_impl_three_way_comparison
- template <class Other>
- inline bool operator==(const Other& p) const noexcept {
- return (p == Get());
- }
- #endif
- private:
- inline void DoDestroy() noexcept {
- if (T_) {
- D::Destroy(T_);
- }
- }
- private:
- mutable T* T_;
- };
- template <class T, class D>
- class THolder: public TPointerBase<THolder<T, D>, T> {
- public:
- constexpr THolder() noexcept
- : T_(nullptr)
- {
- }
- constexpr THolder(std::nullptr_t) noexcept
- : T_(nullptr)
- {
- }
- explicit THolder(T* t) noexcept
- : T_(t)
- {
- }
- inline THolder(TAutoPtr<T, D> t) noexcept
- : T_(t.Release())
- {
- }
- template <class U, class = TGuardConversion<T, U>>
- inline THolder(TAutoPtr<U, D> t) noexcept
- : T_(t.Release())
- {
- }
- inline THolder(THolder&& that) noexcept
- : T_(that.Release())
- {
- }
- template <class U, class = TGuardConversion<T, U>>
- inline THolder(THolder<U, D>&& that) noexcept
- : T_(that.Release())
- {
- }
- THolder(const THolder&) = delete;
- THolder& operator=(const THolder&) = delete;
- inline ~THolder() {
- DoDestroy();
- }
- inline void Destroy() noexcept {
- Reset(nullptr);
- }
- inline T* Release() noexcept Y_WARN_UNUSED_RESULT {
- return this->DoRelease(T_);
- }
- Y_REINITIALIZES_OBJECT inline void Reset(T* t) noexcept {
- if (T_ != t) {
- DoDestroy();
- T_ = t;
- }
- }
- Y_REINITIALIZES_OBJECT inline void Reset(TAutoPtr<T, D> t) noexcept {
- Reset(t.Release());
- }
- Y_REINITIALIZES_OBJECT inline void Reset() noexcept {
- Destroy();
- }
- inline void Swap(THolder& r) noexcept {
- DoSwap(T_, r.T_);
- }
- inline T* Get() const noexcept {
- return T_;
- }
- inline operator TAutoPtr<T, D>() noexcept {
- return Release();
- }
- THolder& operator=(std::nullptr_t) noexcept {
- this->Reset(nullptr);
- return *this;
- }
- THolder& operator=(THolder&& that) noexcept {
- this->Reset(that.Release());
- return *this;
- }
- template <class U>
- THolder& operator=(THolder<U, D>&& that) noexcept {
- this->Reset(that.Release());
- return *this;
- }
- #ifdef __cpp_impl_three_way_comparison
- template <class Other>
- inline bool operator==(const Other& p) const noexcept {
- return (p == Get());
- }
- #endif
- private:
- inline void DoDestroy() noexcept {
- if (T_) {
- D::Destroy(T_);
- }
- }
- private:
- T* T_;
- };
- template <typename T, typename... Args>
- [[nodiscard]] THolder<T> MakeHolder(Args&&... args) {
- return THolder<T>(new T(std::forward<Args>(args)...));
- }
- /*
- * usage:
- * class T: public TRefCounted<T>
- * and we get methods Ref() && UnRef() with
- * proper destruction of last UnRef()
- */
- template <class T, class C, class D>
- class TRefCounted {
- public:
- inline TRefCounted(long initval = 0) noexcept
- : Counter_(initval)
- {
- }
- inline ~TRefCounted() = default;
- inline void Ref(intptr_t d) noexcept {
- auto resultCount = Counter_.Add(d);
- Y_ASSERT(resultCount >= d);
- (void)resultCount;
- }
- inline void Ref() noexcept {
- auto resultCount = Counter_.Inc();
- Y_ASSERT(resultCount != 0);
- (void)resultCount;
- }
- inline void UnRef(intptr_t d) noexcept {
- auto resultCount = Counter_.Sub(d);
- Y_ASSERT(resultCount >= 0);
- if (resultCount == 0) {
- D::Destroy(static_cast<T*>(this));
- }
- }
- inline void UnRef() noexcept {
- UnRef(1);
- }
- inline intptr_t RefCount() const noexcept {
- return Counter_.Val();
- }
- inline void DecRef() noexcept {
- auto resultCount = Counter_.Dec();
- Y_ASSERT(resultCount >= 0);
- (void)resultCount;
- }
- TRefCounted(const TRefCounted&)
- : Counter_(0)
- {
- }
- void operator=(const TRefCounted&) {
- }
- private:
- C Counter_;
- };
- /**
- * Atomically reference-counted base with a virtual destructor.
- *
- * @note Plays well with inheritance, should be used for refcounted base classes.
- */
- struct TThrRefBase: public TRefCounted<TThrRefBase, TAtomicCounter> {
- virtual ~TThrRefBase();
- };
- /**
- * Atomically reference-counted base.
- *
- * Deletes refcounted object as type T.
- *
- * @warning Additional care should be taken with regard to inheritance. If used
- * as a base class, @p T should either declare a virtual destructor, or be
- * derived from @p TThrRefBase instead. Otherwise, only destructor of class @p T
- * would be called, potentially slicing the object and creating memory leaks.
- *
- * @note To avoid accidental inheritance when it is not originally intended,
- * class @p T should be marked as final.
- */
- template <class T, class D = TDelete>
- using TAtomicRefCount = TRefCounted<T, TAtomicCounter, D>;
- /**
- * Non-atomically reference-counted base.
- *
- * @warning Not thread-safe. Use with great care. If in doubt, use @p ThrRefBase
- * or @p TAtomicRefCount instead.
- */
- template <class T, class D = TDelete>
- using TSimpleRefCount = TRefCounted<T, TSimpleCounter, D>;
- template <class T>
- class TDefaultIntrusivePtrOps {
- public:
- static inline void Ref(T* t) noexcept {
- Y_ASSERT(t);
- t->Ref();
- }
- static inline void UnRef(T* t) noexcept {
- Y_ASSERT(t);
- t->UnRef();
- }
- static inline void DecRef(T* t) noexcept {
- Y_ASSERT(t);
- t->DecRef();
- }
- static inline long RefCount(const T* t) noexcept {
- Y_ASSERT(t);
- return t->RefCount();
- }
- };
- template <class T, class Ops>
- class TIntrusivePtr: public TPointerBase<TIntrusivePtr<T, Ops>, T> {
- template <class U, class O>
- friend class TIntrusivePtr;
- template <class U, class O>
- friend class TIntrusiveConstPtr;
- public:
- struct TNoIncrement {
- };
- inline TIntrusivePtr(T* t = nullptr) noexcept
- : T_(t)
- {
- Ops();
- Ref();
- }
- inline TIntrusivePtr(T* t, TNoIncrement) noexcept
- : T_(t)
- {
- Ops();
- }
- inline ~TIntrusivePtr() {
- UnRef();
- }
- inline TIntrusivePtr(const TIntrusivePtr& p) noexcept
- : T_(p.T_)
- {
- Ref();
- }
- // NOTE:
- // without std::enable_if_t compiler sometimes tries to use this constructor inappropriately
- // e.g.
- // struct A {};
- // struct B {};
- // void Func(TIntrusivePtr<A>);
- // void Func(TIntrusivePtr<B>);
- // ...
- // Func(TIntrusivePtr<A>(new A)); // <--- compiler can't decide which version of Func to use
- template <class U, class = TGuardConversion<T, U>>
- inline TIntrusivePtr(const TIntrusivePtr<U>& p) noexcept
- : T_(p.Get())
- {
- Ref();
- }
- template <class U, class = TGuardConversion<T, U>>
- inline TIntrusivePtr(TIntrusivePtr<U>&& p) noexcept
- : T_(p.T_)
- {
- p.T_ = nullptr;
- }
- inline TIntrusivePtr(TIntrusivePtr&& p) noexcept
- : T_(nullptr)
- {
- Swap(p);
- }
- inline TIntrusivePtr& operator=(TIntrusivePtr p) noexcept {
- p.Swap(*this);
- return *this;
- }
- // Effectively replace both:
- // Reset(const TIntrusivePtr&)
- // Reset(TIntrusivePtr&&)
- Y_REINITIALIZES_OBJECT inline void Reset(TIntrusivePtr t) noexcept {
- Swap(t);
- }
- Y_REINITIALIZES_OBJECT inline void Reset() noexcept {
- Drop();
- }
- inline T* Get() const noexcept {
- return T_;
- }
- inline void Swap(TIntrusivePtr& r) noexcept {
- DoSwap(T_, r.T_);
- }
- inline void Drop() noexcept {
- TIntrusivePtr(nullptr).Swap(*this);
- }
- inline T* Release() const noexcept Y_WARN_UNUSED_RESULT {
- T* res = T_;
- if (T_) {
- Ops::DecRef(T_);
- T_ = nullptr;
- }
- return res;
- }
- inline long RefCount() const noexcept {
- return T_ ? Ops::RefCount(T_) : 0;
- }
- #ifdef __cpp_impl_three_way_comparison
- template <class Other>
- inline bool operator==(const Other& p) const noexcept {
- return (p == Get());
- }
- #endif
- private:
- inline void Ref() noexcept {
- if (T_) {
- Ops::Ref(T_);
- }
- }
- inline void UnRef() noexcept {
- if (T_) {
- Ops::UnRef(T_);
- }
- }
- private:
- mutable T* T_;
- };
- template <class T, class Ops>
- struct THash<TIntrusivePtr<T, Ops>>: THash<const T*> {
- using THash<const T*>::operator();
- inline size_t operator()(const TIntrusivePtr<T, Ops>& ptr) const {
- return THash<const T*>::operator()(ptr.Get());
- }
- };
- // Behaves like TIntrusivePtr but returns const T* to prevent user from accidentally modifying the referenced object.
- template <class T, class Ops>
- class TIntrusiveConstPtr: public TPointerBase<TIntrusiveConstPtr<T, Ops>, const T> {
- public:
- inline TIntrusiveConstPtr(T* t = nullptr) noexcept // we need a non-const pointer to Ref(), UnRef() and eventually delete it.
- : T_(t)
- {
- Ops();
- Ref();
- }
- inline ~TIntrusiveConstPtr() {
- UnRef();
- }
- inline TIntrusiveConstPtr(const TIntrusiveConstPtr& p) noexcept
- : T_(p.T_)
- {
- Ref();
- }
- inline TIntrusiveConstPtr(TIntrusiveConstPtr&& p) noexcept
- : T_(nullptr)
- {
- Swap(p);
- }
- inline TIntrusiveConstPtr(TIntrusivePtr<T> p) noexcept
- : T_(p.T_)
- {
- p.T_ = nullptr;
- }
- template <class U, class = TGuardConversion<T, U>>
- inline TIntrusiveConstPtr(const TIntrusiveConstPtr<U>& p) noexcept
- : T_(p.T_)
- {
- Ref();
- }
- template <class U, class = TGuardConversion<T, U>>
- inline TIntrusiveConstPtr(TIntrusiveConstPtr<U>&& p) noexcept
- : T_(p.T_)
- {
- p.T_ = nullptr;
- }
- inline TIntrusiveConstPtr& operator=(TIntrusiveConstPtr p) noexcept {
- p.Swap(*this);
- return *this;
- }
- // Effectively replace both:
- // Reset(const TIntrusiveConstPtr&)
- // Reset(TIntrusiveConstPtr&&)
- Y_REINITIALIZES_OBJECT inline void Reset(TIntrusiveConstPtr t) noexcept {
- Swap(t);
- }
- Y_REINITIALIZES_OBJECT inline void Reset() noexcept {
- Drop();
- }
- inline const T* Get() const noexcept {
- return T_;
- }
- inline void Swap(TIntrusiveConstPtr& r) noexcept {
- DoSwap(T_, r.T_);
- }
- inline void Drop() noexcept {
- TIntrusiveConstPtr(nullptr).Swap(*this);
- }
- inline long RefCount() const noexcept {
- return T_ ? Ops::RefCount(T_) : 0;
- }
- #ifdef __cpp_impl_three_way_comparison
- template <class Other>
- inline bool operator==(const Other& p) const noexcept {
- return (p == Get());
- }
- #endif
- private:
- inline void Ref() noexcept {
- if (T_ != nullptr) {
- Ops::Ref(T_);
- }
- }
- inline void UnRef() noexcept {
- if (T_ != nullptr) {
- Ops::UnRef(T_);
- }
- }
- private:
- T* T_;
- template <class U, class O>
- friend class TIntrusiveConstPtr;
- };
- template <class T, class Ops>
- struct THash<TIntrusiveConstPtr<T, Ops>>: THash<const T*> {
- using THash<const T*>::operator();
- inline size_t operator()(const TIntrusiveConstPtr<T, Ops>& ptr) const {
- return THash<const T*>::operator()(ptr.Get());
- }
- };
- template <class T, class Ops>
- class TSimpleIntrusiveOps {
- using TFunc = void (*)(T*)
- #if __cplusplus >= 201703
- noexcept
- #endif
- ;
- static void DoRef(T* t) noexcept {
- Ops::Ref(t);
- }
- static void DoUnRef(T* t) noexcept {
- Ops::UnRef(t);
- }
- public:
- inline TSimpleIntrusiveOps() noexcept {
- InitStaticOps();
- }
- inline ~TSimpleIntrusiveOps() = default;
- static inline void Ref(T* t) noexcept {
- Ref_(t);
- }
- static inline void UnRef(T* t) noexcept {
- UnRef_(t);
- }
- private:
- static inline void InitStaticOps() noexcept {
- struct TInit {
- inline TInit() noexcept {
- Ref_ = DoRef;
- UnRef_ = DoUnRef;
- }
- };
- Singleton<TInit>();
- }
- private:
- static TFunc Ref_;
- static TFunc UnRef_;
- };
- template <class T, class Ops>
- typename TSimpleIntrusiveOps<T, Ops>::TFunc TSimpleIntrusiveOps<T, Ops>::Ref_ = nullptr;
- template <class T, class Ops>
- typename TSimpleIntrusiveOps<T, Ops>::TFunc TSimpleIntrusiveOps<T, Ops>::UnRef_ = nullptr;
- template <typename T, class Ops = TDefaultIntrusivePtrOps<T>, typename... Args>
- [[nodiscard]] TIntrusivePtr<T, Ops> MakeIntrusive(Args&&... args) {
- return new T{std::forward<Args>(args)...};
- }
- template <typename T, class Ops = TDefaultIntrusivePtrOps<T>, typename... Args>
- [[nodiscard]] TIntrusiveConstPtr<T, Ops> MakeIntrusiveConst(Args&&... args) {
- return new T{std::forward<Args>(args)...};
- }
- template <class T, class C, class D>
- class TSharedPtr: public TPointerBase<TSharedPtr<T, C, D>, T> {
- template <class TT, class CC, class DD>
- friend class TSharedPtr;
- public:
- inline TSharedPtr() noexcept
- : T_(nullptr)
- , C_(nullptr)
- {
- }
- inline TSharedPtr(T* t) {
- THolder<T, D> h(t);
- Init(h);
- }
- inline TSharedPtr(TAutoPtr<T, D> t) {
- Init(t);
- }
- inline TSharedPtr(T* t, C* c) noexcept
- : T_(t)
- , C_(c)
- {
- }
- template <class TT, class = TGuardConversion<T, TT>>
- inline TSharedPtr(THolder<TT>&& t) {
- Init(t);
- }
- inline ~TSharedPtr() {
- UnRef();
- }
- inline TSharedPtr(const TSharedPtr& t) noexcept
- : T_(t.T_)
- , C_(t.C_)
- {
- Ref();
- }
- inline TSharedPtr(TSharedPtr&& t) noexcept
- : T_(nullptr)
- , C_(nullptr)
- {
- Swap(t);
- }
- template <class TT, class = TGuardConversion<T, TT>>
- inline TSharedPtr(const TSharedPtr<TT, C, D>& t) noexcept
- : T_(t.T_)
- , C_(t.C_)
- {
- Ref();
- }
- template <class TT, class = TGuardConversion<T, TT>>
- inline TSharedPtr(TSharedPtr<TT, C, D>&& t) noexcept
- : T_(t.T_)
- , C_(t.C_)
- {
- t.T_ = nullptr;
- t.C_ = nullptr;
- }
- inline TSharedPtr& operator=(TSharedPtr t) noexcept {
- t.Swap(*this);
- return *this;
- }
- // Effectively replace both:
- // Reset(const TSharedPtr& t)
- // Reset(TSharedPtr&& t)
- Y_REINITIALIZES_OBJECT inline void Reset(TSharedPtr t) noexcept {
- Swap(t);
- }
- Y_REINITIALIZES_OBJECT inline void Reset() noexcept {
- Drop();
- }
- inline void Drop() noexcept {
- TSharedPtr().Swap(*this);
- }
- inline T* Get() const noexcept {
- return T_;
- }
- inline C* ReferenceCounter() const noexcept {
- return C_;
- }
- inline void Swap(TSharedPtr& r) noexcept {
- DoSwap(T_, r.T_);
- DoSwap(C_, r.C_);
- }
- inline long RefCount() const noexcept {
- return C_ ? C_->Val() : 0;
- }
- template <class TT>
- [[nodiscard]] inline TSharedPtr<TT, C, D> As() & noexcept {
- static_assert(std::has_virtual_destructor<TT>(), "Type should have a virtual dtor");
- static_assert(std::is_base_of<T, TT>(), "When downcasting from T to TT, T should be a parent of TT");
- if (const auto ttPtr = dynamic_cast<TT*>(T_)) {
- TSharedPtr<TT, C, D> ttSharedPtr(ttPtr, C_);
- ttSharedPtr.Ref();
- return ttSharedPtr;
- } else {
- return TSharedPtr<TT, C, D>{};
- }
- }
- template <class TT>
- [[nodiscard]] inline TSharedPtr<TT, C, D> As() && noexcept {
- static_assert(std::has_virtual_destructor<TT>(), "Type should have a virtual dtor");
- static_assert(std::is_base_of<T, TT>(), "When downcasting from T to TT, T should be a parent of TT");
- if (const auto ttPtr = dynamic_cast<TT*>(T_)) {
- TSharedPtr<TT, C, D> ttSharedPtr(ttPtr, C_);
- T_ = nullptr;
- C_ = nullptr;
- return ttSharedPtr;
- } else {
- return TSharedPtr<TT, C, D>{};
- }
- }
- #ifdef __cpp_impl_three_way_comparison
- template <class Other>
- inline bool operator==(const Other& p) const noexcept {
- return (p == Get());
- }
- #endif
- private:
- template <class X>
- inline void Init(X& t) {
- C_ = !!t ? new C(1) : nullptr;
- T_ = t.Release();
- }
- inline void Ref() noexcept {
- if (C_) {
- C_->Inc();
- }
- }
- inline void UnRef() noexcept {
- if (C_ && !C_->Dec()) {
- DoDestroy();
- }
- }
- inline void DoDestroy() noexcept {
- if (T_) {
- D::Destroy(T_);
- }
- delete C_;
- }
- private:
- T* T_;
- C* C_;
- };
- template <class T, class C, class D>
- struct THash<TSharedPtr<T, C, D>>: THash<const T*> {
- using THash<const T*>::operator();
- inline size_t operator()(const TSharedPtr<T, C, D>& ptr) const {
- return THash<const T*>::operator()(ptr.Get());
- }
- };
- template <class T, class D = TDelete>
- using TAtomicSharedPtr = TSharedPtr<T, TAtomicCounter, D>;
- // use with great care. if in doubt, use TAtomicSharedPtr instead
- template <class T, class D = TDelete>
- using TSimpleSharedPtr = TSharedPtr<T, TSimpleCounter, D>;
- template <typename T, typename C, typename... Args>
- [[nodiscard]] TSharedPtr<T, C> MakeShared(Args&&... args) {
- return new T{std::forward<Args>(args)...};
- }
- template <typename T, typename... Args>
- [[nodiscard]] inline TAtomicSharedPtr<T> MakeAtomicShared(Args&&... args) {
- return MakeShared<T, TAtomicCounter>(std::forward<Args>(args)...);
- }
- template <typename T, typename... Args>
- [[nodiscard]] inline TSimpleSharedPtr<T> MakeSimpleShared(Args&&... args) {
- return MakeShared<T, TSimpleCounter>(std::forward<Args>(args)...);
- }
- class TCopyClone {
- public:
- template <class T>
- static inline T* Copy(T* t) {
- if (t)
- return t->Clone();
- return nullptr;
- }
- };
- class TCopyNew {
- public:
- template <class T>
- static inline T* Copy(T* t) {
- if (t)
- return new T(*t);
- return nullptr;
- }
- };
- template <class T, class C, class D>
- class TCopyPtr: public TPointerBase<TCopyPtr<T, C, D>, T> {
- public:
- inline TCopyPtr(T* t = nullptr) noexcept
- : T_(t)
- {
- }
- inline TCopyPtr(const TCopyPtr& t)
- : T_(C::Copy(t.Get()))
- {
- }
- inline TCopyPtr(TCopyPtr&& t) noexcept
- : T_(nullptr)
- {
- Swap(t);
- }
- inline ~TCopyPtr() {
- DoDestroy();
- }
- inline TCopyPtr& operator=(TCopyPtr t) noexcept {
- t.Swap(*this);
- return *this;
- }
- inline T* Release() noexcept Y_WARN_UNUSED_RESULT {
- return DoRelease(T_);
- }
- Y_REINITIALIZES_OBJECT inline void Reset(T* t) noexcept {
- if (T_ != t) {
- DoDestroy();
- T_ = t;
- }
- }
- Y_REINITIALIZES_OBJECT inline void Reset() noexcept {
- Destroy();
- }
- inline void Destroy() noexcept {
- Reset(nullptr);
- }
- inline void Swap(TCopyPtr& r) noexcept {
- DoSwap(T_, r.T_);
- }
- inline T* Get() const noexcept {
- return T_;
- }
- #ifdef __cpp_impl_three_way_comparison
- template <class Other>
- inline bool operator==(const Other& p) const noexcept {
- return (p == Get());
- }
- #endif
- private:
- inline void DoDestroy() noexcept {
- if (T_)
- D::Destroy(T_);
- }
- private:
- T* T_;
- };
- // Copy-on-write pointer
- template <class TPtr, class TCopy>
- class TCowPtr: public TPointerBase<TCowPtr<TPtr, TCopy>, const typename TPtr::TValueType> {
- using T = typename TPtr::TValueType;
- public:
- inline TCowPtr() = default;
- inline TCowPtr(const TPtr& p)
- : T_(p)
- {
- }
- inline TCowPtr(T* p)
- : T_(p)
- {
- }
- inline const T* Get() const noexcept {
- return Const();
- }
- inline const T* Const() const noexcept {
- return T_.Get();
- }
- inline T* Mutable() {
- Unshare();
- return T_.Get();
- }
- inline bool Shared() const noexcept {
- return T_.RefCount() > 1;
- }
- inline void Swap(TCowPtr& r) noexcept {
- T_.Swap(r.T_);
- }
- Y_REINITIALIZES_OBJECT inline void Reset(TCowPtr p) {
- p.Swap(*this);
- }
- Y_REINITIALIZES_OBJECT inline void Reset() {
- T_.Reset();
- }
- #ifdef __cpp_impl_three_way_comparison
- template <class Other>
- inline bool operator==(const Other& p) const noexcept {
- return (p == Get());
- }
- #endif
- private:
- inline void Unshare() {
- if (Shared()) {
- Reset(TCopy::Copy(T_.Get()));
- }
- }
- private:
- TPtr T_;
- };
- // saves .Get() on argument passing. Intended usage: Func(TPtrArg<X> p); ... TIntrusivePtr<X> p2; Func(p2);
- template <class T>
- class TPtrArg {
- T* Ptr;
- public:
- TPtrArg(T* p)
- : Ptr(p)
- {
- }
- TPtrArg(const TIntrusivePtr<T>& p)
- : Ptr(p.Get())
- {
- }
- operator T*() const {
- return Ptr;
- }
- T* operator->() const {
- return Ptr;
- }
- T* Get() const {
- return Ptr;
- }
- };
|