Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 1 | // Copyright 2011 The Chromium Authors |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 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 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 7 | #if DCHECK_IS_ON() |
| 8 | #include <ostream> |
| 9 | |
| 10 | #include "base/debug/stack_trace.h" |
| 11 | #endif |
| 12 | |
| 13 | namespace base::internal { |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 14 | |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 15 | WeakReference::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_); |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 20 | } |
| 21 | |
| 22 | void 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. |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 25 | #if DCHECK_IS_ON() |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 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:"; |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 32 | #endif |
| 33 | invalidated_.Set(); |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 34 | } |
| 35 | |
| 36 | bool WeakReference::Flag::IsValid() const { |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 37 | // WeakPtrs must be checked on the same sequenced thread. |
| 38 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 39 | return !invalidated_.IsSet(); |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 40 | } |
| 41 | |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 42 | bool WeakReference::Flag::MaybeValid() const { |
| 43 | return !invalidated_.IsSet(); |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 44 | } |
| 45 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 46 | #if DCHECK_IS_ON() |
| 47 | void WeakReference::Flag::DetachFromSequence() { |
| 48 | DETACH_FROM_SEQUENCE(sequence_checker_); |
| 49 | } |
| 50 | #endif |
| 51 | |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 52 | WeakReference::Flag::~Flag() = default; |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 53 | |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 54 | WeakReference::WeakReference() = default; |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 55 | WeakReference::WeakReference(const scoped_refptr<Flag>& flag) : flag_(flag) {} |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 56 | WeakReference::~WeakReference() = default; |
| 57 | |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 58 | WeakReference::WeakReference(const WeakReference& other) = default; |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 59 | WeakReference& WeakReference::operator=(const WeakReference& other) = default; |
| 60 | |
| 61 | WeakReference::WeakReference(WeakReference&& other) noexcept = default; |
| 62 | WeakReference& WeakReference::operator=(WeakReference&& other) noexcept = |
| 63 | default; |
| 64 | |
| 65 | void WeakReference::Reset() { |
| 66 | flag_ = nullptr; |
| 67 | } |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 68 | |
| 69 | bool WeakReference::IsValid() const { |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 70 | return flag_ && flag_->IsValid(); |
| 71 | } |
| 72 | |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 73 | bool WeakReference::MaybeValid() const { |
| 74 | return flag_ && flag_->MaybeValid(); |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 75 | } |
| 76 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 77 | WeakReferenceOwner::WeakReferenceOwner() |
| 78 | : flag_(MakeRefCounted<WeakReference::Flag>()) {} |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 79 | |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 80 | WeakReferenceOwner::~WeakReferenceOwner() { |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 81 | flag_->Invalidate(); |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | WeakReference WeakReferenceOwner::GetRef() const { |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 85 | #if DCHECK_IS_ON() |
| 86 | // If we hold the last reference to the Flag then detach the SequenceChecker. |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 87 | if (!HasRefs()) |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 88 | flag_->DetachFromSequence(); |
| 89 | #endif |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 90 | |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 91 | return WeakReference(flag_); |
| 92 | } |
| 93 | |
| 94 | void WeakReferenceOwner::Invalidate() { |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 95 | flag_->Invalidate(); |
| 96 | flag_ = MakeRefCounted<WeakReference::Flag>(); |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 97 | } |
| 98 | |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 99 | WeakPtrFactoryBase::WeakPtrFactoryBase(uintptr_t ptr) : ptr_(ptr) { |
| 100 | DCHECK(ptr_); |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 101 | } |
| 102 | |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 103 | WeakPtrFactoryBase::~WeakPtrFactoryBase() { |
| 104 | ptr_ = 0; |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 105 | } |
| 106 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 107 | } // namespace base::internal |