voidAddRef()const{ #if DCHECK_IS_ON() DCHECK(!in_dtor_); DCHECK(!needs_adopt_ref_) << "This RefCounted object is created with non-zero reference count." << " The first reference to such a object has to be made by AdoptRef or" << " MakeRefCounted."; if (ref_count_ >= 1) { DCHECK(CalledOnValidSequence()); } #endif AddRefImpl(); } voidRefCountedBase::AddRefImpl()const{ // Check if |ref_count_| overflow only on 64 bit archs since the number of // objects may exceed 2^32. // To avoid the binary size bloat, use non-inline function here. CHECK(++ref_count_ > 0); }
// Returns true if the object should self-delete. boolRelease()const{ --ref_count_; #if DCHECK_IS_ON() DCHECK(!in_dtor_); if (ref_count_ == 0) in_dtor_ = true; if (ref_count_ >= 1) DCHECK(CalledOnValidSequence()); if (ref_count_ == 1) sequence_checker_.DetachFromSequence(); #endif return ref_count_ == 0; }
// Constructs an instance of T, which is a ref counted type, and wraps the // object into a scoped_refptr<T>. template <typename T, typename... Args> scoped_refptr<T> MakeRefCounted(Args&&... args){ T* obj = newT(std::forward<Args>(args)...); return subtle::AdoptRefIfNeeded(obj, T::kRefCountPreference); } namespace subtle { template <typename T> scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag){ returnscoped_refptr<T>(obj); } template <typename T> scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag){ returnAdoptRef(obj); } } // namespace subtle // Creates a scoped_refptr from a raw pointer without incrementing the reference // count. Use this only for a newly created object whose reference count starts // from 1 instead of 0. template <typename T> scoped_refptr<T> AdoptRef(T* obj){ using Tag = std::decay_t<decltype(T::kRefCountPreference)>; static_assert(std::is_same<subtle::StartRefCountFromOneTag, Tag>::value, "Use AdoptRef only for the reference count starts from one."); DCHECK(obj); DCHECK(obj->HasOneRef()); obj->Adopted(); returnscoped_refptr<T>(obj, subtle::kAdoptRefTag); } scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {}
classBASE_EXPORT WeakReferenceOwner { public: WeakReferenceOwner() = default; ~WeakReferenceOwner(); WeakReference GetRef()const; boolHasRefs()const{ return flag_ && !flag_->HasOneRef(); } voidInvalidate(); private: mutable scoped_refptr<WeakReference::Flag> flag_; }; WeakReferenceOwner::~WeakReferenceOwner() { Invalidate(); } WeakReference WeakReferenceOwner::GetRef()const{ // If we hold the last reference to the Flag then create a new one. if (!HasRefs()) flag_ = new WeakReference::Flag(); returnWeakReference(flag_); } voidWeakReferenceOwner::Invalidate(){ if (flag_) { flag_->Invalidate(); flag_ = nullptr; } } // An inner class of WeakReference classBASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { public: Flag(); voidInvalidate(); boolIsValid()const; private: friendclassbase::RefCountedThreadSafe<Flag>; ~Flag(); SequenceChecker sequence_checker_; bool is_valid_; };
classBASE_EXPORT WeakPtrBase { public: WeakPtrBase(); ~WeakPtrBase(); WeakPtrBase(const WeakPtrBase& other) = default; WeakPtrBase(WeakPtrBase&& other) = default; WeakPtrBase& operator=(const WeakPtrBase& other) = default; WeakPtrBase& operator=(WeakPtrBase&& other) = default; voidreset(){ ref_ = internal::WeakReference(); ptr_ = 0; } protected: WeakPtrBase(const WeakReference& ref, uintptr_t ptr); WeakReference ref_; // This pointer is only valid when ref_.is_valid() is true. Otherwise, its // value is undefined (as opposed to nullptr). uintptr_t ptr_; }; WeakPtrBase::WeakPtrBase() : ptr_(0) {} WeakPtrBase::~WeakPtrBase() = default; WeakPtrBase::WeakPtrBase(const WeakReference& ref, uintptr_t ptr) : ref_(ref), ptr_(ptr) {} template <typename T> classWeakPtr : public internal::WeakPtrBase { public: WeakPtr() = default; WeakPtr(std::nullptr_t) {} // Allow conversion from U to T provided U "is a" T. Note that this // is separate from the (implicit) copy and move constructors. template <typename U> WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other) { // Need to cast from U* to T* to do pointer adjustment in case of multiple // inheritance. This also enforces the "U is a T" rule. T* t = reinterpret_cast<U*>(other.ptr_); ptr_ = reinterpret_cast<uintptr_t>(t); } template <typename U> WeakPtr(WeakPtr<U>&& other) : WeakPtrBase(std::move(other)) { // Need to cast from U* to T* to do pointer adjustment in case of multiple // inheritance. This also enforces the "U is a T" rule. T* t = reinterpret_cast<U*>(other.ptr_); ptr_ = reinterpret_cast<uintptr_t>(t); } T* get()const{ return ref_.is_valid() ? reinterpret_cast<T*>(ptr_) : nullptr; } T& operator*() const { DCHECK(get() != nullptr); return *get(); } T* operator->() const { DCHECK(get() != nullptr); returnget(); } // Allow conditionals to test validity, e.g. if (weak_ptr) {...}; explicitoperatorbool()const{ returnget() != nullptr; } private: friendclassinternal::SupportsWeakPtrBase; template <typename U> friendclassWeakPtr; friendclassSupportsWeakPtr<T>; friendclassWeakPtrFactory<T>; WeakPtr(const internal::WeakReference& ref, T* ptr) : WeakPtrBase(ref, reinterpret_cast<uintptr_t>(ptr)) {} };