#pragma once #include "ref_counted.h" #include namespace NYT { //////////////////////////////////////////////////////////////////////////////// template class TWeakPtr { public: using TUnderlying = T; using element_type = T; //! Default constructor. TWeakPtr() = default; //! Null constructor. TWeakPtr(std::nullptr_t); //! Constructor from an unqualified reference. /*! * Note that this constructor could be racy due to unsynchronized operations * on the object and on the counter. */ explicit TWeakPtr(T* p) noexcept; //! Constructor from a strong reference. TWeakPtr(const TIntrusivePtr& ptr) noexcept; //! Constructor from a strong reference with an upcast. template >> TWeakPtr(const TIntrusivePtr& ptr) noexcept; //! Copy constructor. TWeakPtr(const TWeakPtr& other) noexcept; //! Copy constructor with an upcast. template >> TWeakPtr(const TWeakPtr& other) noexcept; //! Move constructor. TWeakPtr(TWeakPtr&& other) noexcept; //! Move constructor with an upcast. template >> TWeakPtr(TWeakPtr&& other) noexcept; //! Destructor. ~TWeakPtr(); //! Assignment operator from a strong reference. template TWeakPtr& operator=(const TIntrusivePtr& ptr) noexcept; //! Copy assignment operator. TWeakPtr& operator=(const TWeakPtr& other) noexcept; //! Copy assignment operator with an upcast. template TWeakPtr& operator=(const TWeakPtr& other) noexcept; //! Move assignment operator. TWeakPtr& operator=(TWeakPtr&& other) noexcept; //! Move assignment operator with an upcast. template TWeakPtr& operator=(TWeakPtr&& other) noexcept; //! Drop the pointer. void Reset(); // noexcept //! Replace the pointer with a specified one. void Reset(T* p); // noexcept //! Replace the pointer with a specified one. template void Reset(const TIntrusivePtr& ptr); // noexcept //! Swap the pointer with the other one. void Swap(TWeakPtr& other) noexcept; //! Acquire a strong reference to the pointee and return a strong pointer. TIntrusivePtr Lock() const noexcept; //! Returns true if the pointee is null or already expired. bool IsExpired() const noexcept; //! Returns the underlying raw pointer. Note that it may point to an already //! expired object. T* Get() const noexcept; private: void AcquireRef(); void ReleaseRef(); template friend class TWeakPtr; T* T_ = nullptr; #if defined(_tsan_enabled_) const TRefCounter* RefCounter_ = nullptr; #endif const TRefCounter* GetRefCounterImpl() const; const TRefCounter* TryGetRefCounterImpl() const; }; //////////////////////////////////////////////////////////////////////////////// template bool operator==(const TWeakPtr& lhs, const TWeakPtr& rhs); template bool operator==(const TIntrusivePtr& lhs, const TWeakPtr& rhs); template bool operator==(const TWeakPtr& lhs, const TIntrusivePtr& rhs); template bool operator==(T1* lhs, const TWeakPtr& rhs); template bool operator==(const TWeakPtr& lhs, T2* rhs); template bool operator==(std::nullptr_t, const TWeakPtr& rhs); template bool operator==(const TWeakPtr& lhs, std::nullptr_t); //////////////////////////////////////////////////////////////////////////////// //! Creates a weak pointer wrapper for a given raw pointer. //! Compared to |TWeakPtr::ctor|, type inference enables omitting |T|. template TWeakPtr MakeWeak(T* p); //! Creates a weak pointer wrapper for a given intrusive pointer. //! Compared to |TWeakPtr::ctor|, type inference enables omitting |T|. template TWeakPtr MakeWeak(const TIntrusivePtr& p); //! A helper for acquiring weak pointer for pointee, resetting intrusive pointer and then //! returning the pointee reference count using the acquired weak pointer. //! This helper is designed for best effort in checking that the object is not leaked after //! destructing (what seems to be) the last pointer to it. //! NB: it is possible to rewrite this helper making it working event with intrinsic refcounted objects, //! but it requires much nastier integration with the intrusive pointer destruction routines. template int ResetAndGetResidualRefCount(TIntrusivePtr& pointer); //////////////////////////////////////////////////////////////////////////////// struct TTransparentWeakPtrHasher { using is_transparent = void; template std::size_t operator()(const TWeakPtr& ptr) const; template std::size_t operator()(const TIntrusivePtr& ptr) const; template std::size_t operator()(T* ptr) const; }; //////////////////////////////////////////////////////////////////////////////// } // namespace NYT template struct THash> { size_t operator()(const NYT::TWeakPtr& ptr) const; }; #define WEAK_PTR_INL_H_ #include "weak_ptr-inl.h" #undef WEAK_PTR_INL_H_