#ifndef WEAK_PTR_INL_H_ #error "Direct inclusion of this file is not allowed, include weak_ptr.h" // For the sake of sane code completion. #include "weak_ptr.h" #endif namespace NYT { //////////////////////////////////////////////////////////////////////////////// template TWeakPtr::TWeakPtr(std::nullptr_t) { } template TWeakPtr::TWeakPtr(T* p) noexcept : T_(p) { #if defined(_tsan_enabled_) if (T_) { RefCounter_ = GetRefCounter(T_); } #endif AcquireRef(); } template TWeakPtr::TWeakPtr(const TIntrusivePtr& ptr) noexcept : TWeakPtr(ptr.Get()) { } template template TWeakPtr::TWeakPtr(const TIntrusivePtr& ptr) noexcept : TWeakPtr(ptr.Get()) { static_assert( std::derived_from, "Cast allowed only for types derived from TRefCountedBase"); } template TWeakPtr::TWeakPtr(const TWeakPtr& other) noexcept : T_(other.T_) #if defined(_tsan_enabled_) , RefCounter_(other.RefCounter_) #endif { AcquireRef(); } template template TWeakPtr::TWeakPtr(const TWeakPtr& other) noexcept : TWeakPtr(other.Lock()) { static_assert( std::derived_from, "Cast allowed only for types derived from TRefCountedBase"); } template TWeakPtr::TWeakPtr(TWeakPtr&& other) noexcept { other.Swap(*this); } template template TWeakPtr::TWeakPtr(TWeakPtr&& other) noexcept { static_assert( std::derived_from, "Cast allowed only for types derived from TRefCountedBase"); TIntrusivePtr strongOther = other.Lock(); if (strongOther) { T_ = other.T_; other.T_ = nullptr; #if defined(_tsan_enabled_) RefCounter_ = other.RefCounter_; other.RefCounter_ = nullptr; #endif } } template TWeakPtr::~TWeakPtr() { ReleaseRef(); } template template TWeakPtr& TWeakPtr::operator=(const TIntrusivePtr& ptr) noexcept { static_assert( std::is_convertible_v, "U* must be convertible to T*"); TWeakPtr(ptr).Swap(*this); return *this; } template TWeakPtr& TWeakPtr::operator=(const TWeakPtr& other) noexcept { TWeakPtr(other).Swap(*this); return *this; } template template TWeakPtr& TWeakPtr::operator=(const TWeakPtr& other) noexcept { static_assert( std::is_convertible_v, "U* must be convertible to T*"); TWeakPtr(other).Swap(*this); return *this; } template TWeakPtr& TWeakPtr::operator=(TWeakPtr&& other) noexcept { other.Swap(*this); return *this; } template template TWeakPtr& TWeakPtr::operator=(TWeakPtr&& other) noexcept { static_assert( std::is_convertible_v, "U* must be convertible to T*"); TWeakPtr(std::move(other)).Swap(*this); return *this; } template void TWeakPtr::Reset() // noexcept { TWeakPtr().Swap(*this); } template void TWeakPtr::Reset(T* p) // noexcept { TWeakPtr(p).Swap(*this); } template template void TWeakPtr::Reset(const TIntrusivePtr& ptr) // noexcept { static_assert( std::is_convertible_v, "U* must be convertible to T*"); TWeakPtr(ptr).Swap(*this); } template void TWeakPtr::Swap(TWeakPtr& other) noexcept { DoSwap(T_, other.T_); #if defined(_tsan_enabled_) DoSwap(RefCounter_, other.RefCounter_); #endif } template TIntrusivePtr TWeakPtr::Lock() const noexcept { return T_ && GetRefCounterImpl()->TryRef() ? TIntrusivePtr(T_, false) : TIntrusivePtr(); } template bool TWeakPtr::IsExpired() const noexcept { return !T_ || (GetRefCounterImpl()->GetRefCount() == 0); } template T* TWeakPtr::Get() const noexcept { return T_; } template const TRefCounter* TWeakPtr::TryGetRefCounterImpl() const { return T_ ? GetRefCounterImpl() : nullptr; } template void TWeakPtr::AcquireRef() { if (T_) { GetRefCounterImpl()->WeakRef(); } } template void TWeakPtr::ReleaseRef() { if (T_) { // Support incomplete type. if (GetRefCounterImpl()->WeakUnref()) { DeallocateRefCounted(T_); } } } #if defined(_tsan_enabled_) template const TRefCounter* TWeakPtr::GetRefCounterImpl() const { return RefCounter_; } #else template const TRefCounter* TWeakPtr::GetRefCounterImpl() const { return GetRefCounter(T_); } #endif //////////////////////////////////////////////////////////////////////////////// template bool operator==(const TWeakPtr& lhs, const TWeakPtr& rhs) { return lhs.Get() == rhs.Get(); } template bool operator==(const TIntrusivePtr& lhs, const TWeakPtr& rhs) { return lhs.Get() == rhs.Get(); } template bool operator==(const TWeakPtr& lhs, const TIntrusivePtr& rhs) { return lhs.Get() == rhs.Get(); } template bool operator==(T1* lhs, const TWeakPtr& rhs) { return lhs == rhs.Get(); } template bool operator==(const TWeakPtr& lhs, T2* rhs) { return lhs.Get() == rhs; } template bool operator==(std::nullptr_t, const TWeakPtr& rhs) { return nullptr == rhs.Get(); } template bool operator==(const TWeakPtr& lhs, std::nullptr_t) { return lhs.Get() == nullptr; } //////////////////////////////////////////////////////////////////////////////// template TWeakPtr MakeWeak(T* p) { return TWeakPtr(p); } template TWeakPtr MakeWeak(const TIntrusivePtr& p) { return TWeakPtr(p); } template int ResetAndGetResidualRefCount(TIntrusivePtr& pointer) { auto weakPointer = MakeWeak(pointer); pointer.Reset(); pointer = weakPointer.Lock(); if (pointer) { // This _may_ return 0 if we are again the only holder of the pointee. return pointer->GetRefCount() - 1; } else { return 0; } } //////////////////////////////////////////////////////////////////////////////// template std::size_t TTransparentWeakPtrHasher::operator()(const TWeakPtr& ptr) const { return THash()(ptr.Get()); } template std::size_t TTransparentWeakPtrHasher::operator()(const TIntrusivePtr& ptr) const { return THash()(ptr.Get()); } template std::size_t TTransparentWeakPtrHasher::operator()(T* ptr) const { return THash()(ptr); } //////////////////////////////////////////////////////////////////////////////// //! Abseil hash support for TWeakPtr. template THash AbslHashValue(THash hash, const TWeakPtr& ptr) { return THash::combine(std::move(hash), ptr.Get()); } //////////////////////////////////////////////////////////////////////////////// } // namespace NYT //////////////////////////////////////////////////////////////////////////////// //! A hasher for TWeakPtr. template size_t THash>::operator()(const NYT::TWeakPtr& ptr) const { return THash()(ptr.Get()); } ////////////////////////////////////////////////////////////////////////////////