xref: /aosp_15_r20/external/cronet/base/memory/weak_ptr.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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()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_);
20 }
21 
Invalidate()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.
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() const36 bool 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() const42 bool WeakReference::Flag::MaybeValid() const {
43   return !invalidated_.IsSet();
44 }
45 
46 #if DCHECK_IS_ON()
DetachFromSequence()47 void WeakReference::Flag::DetachFromSequence() {
48   DETACH_FROM_SEQUENCE(sequence_checker_);
49 }
50 
BindToCurrentSequence()51 void 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)60 WeakReference::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()70 void WeakReference::Reset() {
71   flag_ = nullptr;
72 }
73 
IsValid() const74 bool WeakReference::IsValid() const {
75   return flag_ && flag_->IsValid();
76 }
77 
MaybeValid() const78 bool WeakReference::MaybeValid() const {
79   return flag_ && flag_->MaybeValid();
80 }
81 
WeakReferenceOwner()82 WeakReferenceOwner::WeakReferenceOwner()
83     : flag_(MakeRefCounted<WeakReference::Flag>()) {}
84 
~WeakReferenceOwner()85 WeakReferenceOwner::~WeakReferenceOwner() {
86   flag_->Invalidate();
87 }
88 
GetRef() const89 WeakReference 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()99 void WeakReferenceOwner::Invalidate() {
100   flag_->Invalidate();
101   flag_ = MakeRefCounted<WeakReference::Flag>();
102 }
103 
BindToCurrentSequence()104 void WeakReferenceOwner::BindToCurrentSequence() {
105 #if DCHECK_IS_ON()
106   flag_->BindToCurrentSequence();
107 #endif
108 }
109 
WeakPtrFactoryBase(uintptr_t ptr)110 WeakPtrFactoryBase::WeakPtrFactoryBase(uintptr_t ptr) : ptr_(ptr) {
111   DCHECK(ptr_);
112 }
113 
~WeakPtrFactoryBase()114 WeakPtrFactoryBase::~WeakPtrFactoryBase() {
115   ptr_ = 0;
116 }
117 
118 }  // namespace base::internal
119