blob: f85ba5e40afbd2cc2e29026f06e23febb2eca1ab [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/memory/ref_counted.h"
#include "base/threading/thread_collision_warner.h"
namespace base {
namespace {
#if DCHECK_IS_ON()
AtomicRefCount g_cross_thread_ref_count_access_allow_count = 0;
#endif
} // namespace
namespace subtle {
bool RefCountedThreadSafeBase::HasOneRef() const {
return AtomicRefCountIsOne(&ref_count_);
}
RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
#if DCHECK_IS_ON()
DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
"calling Release()";
#endif
}
void RefCountedThreadSafeBase::AddRef() 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.";
#endif
AtomicRefCountInc(&ref_count_);
}
bool RefCountedThreadSafeBase::Release() const {
#if DCHECK_IS_ON()
DCHECK(!in_dtor_);
DCHECK(!AtomicRefCountIsZero(&ref_count_));
#endif
if (!AtomicRefCountDec(&ref_count_)) {
#if DCHECK_IS_ON()
in_dtor_ = true;
#endif
return true;
}
return false;
}
#if DCHECK_IS_ON()
bool RefCountedBase::CalledOnValidSequence() const {
return sequence_checker_.CalledOnValidSequence() ||
!AtomicRefCountIsZero(&g_cross_thread_ref_count_access_allow_count);
}
#endif
} // namespace subtle
#if DCHECK_IS_ON()
ScopedAllowCrossThreadRefCountAccess::ScopedAllowCrossThreadRefCountAccess() {
AtomicRefCountInc(&g_cross_thread_ref_count_access_allow_count);
}
ScopedAllowCrossThreadRefCountAccess::~ScopedAllowCrossThreadRefCountAccess() {
AtomicRefCountDec(&g_cross_thread_ref_count_access_allow_count);
}
#endif
} // namespace base