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