1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
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/ref_counted.h"
6
7#include "base/logging.h"
8#include "base/threading/thread_collision_warner.h"
9
10namespace base {
11
12namespace subtle {
13
14RefCountedBase::RefCountedBase()
15    : ref_count_(0)
16#ifndef NDEBUG
17    , in_dtor_(false)
18#endif
19    {
20}
21
22RefCountedBase::~RefCountedBase() {
23#ifndef NDEBUG
24  DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
25#endif
26}
27
28void RefCountedBase::AddRef() const {
29  // TODO(maruel): Add back once it doesn't assert 500 times/sec.
30  // Current thread books the critical section "AddRelease" without release it.
31  // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
32#ifndef NDEBUG
33  DCHECK(!in_dtor_);
34#endif
35  ++ref_count_;
36}
37
38bool RefCountedBase::Release() const {
39  // TODO(maruel): Add back once it doesn't assert 500 times/sec.
40  // Current thread books the critical section "AddRelease" without release it.
41  // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
42#ifndef NDEBUG
43  DCHECK(!in_dtor_);
44#endif
45  if (--ref_count_ == 0) {
46#ifndef NDEBUG
47    in_dtor_ = true;
48#endif
49    return true;
50  }
51  return false;
52}
53
54bool RefCountedThreadSafeBase::HasOneRef() const {
55  return AtomicRefCountIsOne(
56      &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_);
57}
58
59RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) {
60#ifndef NDEBUG
61  in_dtor_ = false;
62#endif
63}
64
65RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
66#ifndef NDEBUG
67  DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
68                      "calling Release()";
69#endif
70}
71
72void RefCountedThreadSafeBase::AddRef() const {
73#ifndef NDEBUG
74  DCHECK(!in_dtor_);
75#endif
76  AtomicRefCountInc(&ref_count_);
77}
78
79bool RefCountedThreadSafeBase::Release() const {
80#ifndef NDEBUG
81  DCHECK(!in_dtor_);
82  DCHECK(!AtomicRefCountIsZero(&ref_count_));
83#endif
84  if (!AtomicRefCountDec(&ref_count_)) {
85#ifndef NDEBUG
86    in_dtor_ = true;
87#endif
88    return true;
89  }
90  return false;
91}
92
93}  // namespace subtle
94
95}  // namespace base
96