#pragma once #include #include template struct TWeakPtr; template struct TWeakRefCounted { template friend struct TWeakPtr; private: struct TRef: public TAtomicRefCount { TMutex Mutex; TSelf* Outer; TRef(TSelf* outer) : Outer(outer) { } void Release() { TGuard g(Mutex); Y_ASSERT(!!Outer); Outer = nullptr; } TIntrusivePtr Get() { TGuard g(Mutex); Y_ASSERT(!Outer || Outer->RefCount() > 0); return Outer; } }; TAtomicCounter Counter; TIntrusivePtr RefPtr; public: TWeakRefCounted() : RefPtr(new TRef(static_cast(this))) { } void Ref() { Counter.Inc(); } void UnRef() { if (Counter.Dec() == 0) { RefPtr->Release(); // drop is to prevent dtor from reading it RefPtr.Drop(); delete static_cast(this); } } void DecRef() { Counter.Dec(); } unsigned RefCount() const { return Counter.Val(); } }; template struct TWeakPtr { private: typedef TIntrusivePtr TRefPtr; TRefPtr RefPtr; public: TWeakPtr() { } TWeakPtr(T* t) { if (!!t) { RefPtr = t->RefPtr; } } TWeakPtr(TIntrusivePtr t) { if (!!t) { RefPtr = t->RefPtr; } } TIntrusivePtr Get() { if (!RefPtr) { return nullptr; } else { return RefPtr->Get(); } } };