1 // Copyright 2011 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/memory/weak_ptr.h" 6 7 #if DCHECK_IS_ON() 8 #include <ostream> 9 10 #include "base/debug/stack_trace.h" 11 #endif 12 13 namespace base::internal { 14 Flag()15WeakReference::Flag::Flag() { 16 // Flags only become bound when checked for validity, or invalidated, 17 // so that we can check that later validity/invalidation operations on 18 // the same Flag take place on the same sequenced thread. 19 DETACH_FROM_SEQUENCE(sequence_checker_); 20 } 21 Invalidate()22void WeakReference::Flag::Invalidate() { 23 // The flag being invalidated with a single ref implies that there are no 24 // weak pointers in existence. Allow deletion on other thread in this case. 25 #if DCHECK_IS_ON() 26 std::unique_ptr<debug::StackTrace> bound_at; 27 DCHECK(sequence_checker_.CalledOnValidSequence(&bound_at) || HasOneRef()) 28 << "WeakPtrs must be invalidated on the same sequenced thread as where " 29 << "they are bound.\n" 30 << (bound_at ? "This was bound at:\n" + bound_at->ToString() : "") 31 << "Check failed at:"; 32 #endif 33 invalidated_.Set(); 34 } 35 IsValid() const36bool WeakReference::Flag::IsValid() const { 37 // WeakPtrs must be checked on the same sequenced thread. 38 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 39 return !invalidated_.IsSet(); 40 } 41 MaybeValid() const42bool WeakReference::Flag::MaybeValid() const { 43 return !invalidated_.IsSet(); 44 } 45 46 #if DCHECK_IS_ON() DetachFromSequence()47void WeakReference::Flag::DetachFromSequence() { 48 DETACH_FROM_SEQUENCE(sequence_checker_); 49 } 50 BindToCurrentSequence()51void WeakReference::Flag::BindToCurrentSequence() { 52 DETACH_FROM_SEQUENCE(sequence_checker_); 53 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 54 } 55 #endif 56 57 WeakReference::Flag::~Flag() = default; 58 59 WeakReference::WeakReference() = default; WeakReference(const scoped_refptr<Flag> & flag)60WeakReference::WeakReference(const scoped_refptr<Flag>& flag) : flag_(flag) {} 61 WeakReference::~WeakReference() = default; 62 63 WeakReference::WeakReference(const WeakReference& other) = default; 64 WeakReference& WeakReference::operator=(const WeakReference& other) = default; 65 66 WeakReference::WeakReference(WeakReference&& other) noexcept = default; 67 WeakReference& WeakReference::operator=(WeakReference&& other) noexcept = 68 default; 69 Reset()70void WeakReference::Reset() { 71 flag_ = nullptr; 72 } 73 IsValid() const74bool WeakReference::IsValid() const { 75 return flag_ && flag_->IsValid(); 76 } 77 MaybeValid() const78bool WeakReference::MaybeValid() const { 79 return flag_ && flag_->MaybeValid(); 80 } 81 WeakReferenceOwner()82WeakReferenceOwner::WeakReferenceOwner() 83 : flag_(MakeRefCounted<WeakReference::Flag>()) {} 84 ~WeakReferenceOwner()85WeakReferenceOwner::~WeakReferenceOwner() { 86 flag_->Invalidate(); 87 } 88 GetRef() const89WeakReference WeakReferenceOwner::GetRef() const { 90 #if DCHECK_IS_ON() 91 // If we hold the last reference to the Flag then detach the SequenceChecker. 92 if (!HasRefs()) 93 flag_->DetachFromSequence(); 94 #endif 95 96 return WeakReference(flag_); 97 } 98 Invalidate()99void WeakReferenceOwner::Invalidate() { 100 flag_->Invalidate(); 101 flag_ = MakeRefCounted<WeakReference::Flag>(); 102 } 103 BindToCurrentSequence()104void WeakReferenceOwner::BindToCurrentSequence() { 105 #if DCHECK_IS_ON() 106 flag_->BindToCurrentSequence(); 107 #endif 108 } 109 WeakPtrFactoryBase(uintptr_t ptr)110WeakPtrFactoryBase::WeakPtrFactoryBase(uintptr_t ptr) : ptr_(ptr) { 111 DCHECK(ptr_); 112 } 113 ~WeakPtrFactoryBase()114WeakPtrFactoryBase::~WeakPtrFactoryBase() { 115 ptr_ = 0; 116 } 117 118 } // namespace base::internal 119