Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: base/memory/ref_counted.h

Issue 2723423002: Start BindStateBase ref count from 1 instead of 0 (Closed)
Patch Set: +test Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/callback_internal.cc ('k') | base/memory/ref_counted.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_MEMORY_REF_COUNTED_H_ 5 #ifndef BASE_MEMORY_REF_COUNTED_H_
6 #define BASE_MEMORY_REF_COUNTED_H_ 6 #define BASE_MEMORY_REF_COUNTED_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <cassert> 10 #include <cassert>
11 #include <iosfwd> 11 #include <iosfwd>
12 #include <type_traits> 12 #include <type_traits>
13 13
14 #include "base/atomic_ref_count.h" 14 #include "base/atomic_ref_count.h"
15 #include "base/base_export.h" 15 #include "base/base_export.h"
16 #include "base/compiler_specific.h" 16 #include "base/compiler_specific.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/macros.h" 18 #include "base/macros.h"
19 #include "base/threading/thread_collision_warner.h" 19 #include "base/threading/thread_collision_warner.h"
20 #include "build/build_config.h" 20 #include "build/build_config.h"
21 21
22 template <class T>
23 class scoped_refptr;
24
22 namespace base { 25 namespace base {
23 26
27 template <typename T>
28 scoped_refptr<T> AdoptRef(T* t);
29
24 namespace subtle { 30 namespace subtle {
25 31
32 enum AdoptRefTag { kAdoptRefTag };
33
26 class BASE_EXPORT RefCountedBase { 34 class BASE_EXPORT RefCountedBase {
27 public: 35 public:
28 bool HasOneRef() const { return ref_count_ == 1; } 36 bool HasOneRef() const { return ref_count_ == 1; }
29 37
30 protected: 38 protected:
31 RefCountedBase() 39 explicit RefCountedBase(size_t initial_ref_count = 0)
dcheng 2017/03/30 04:26:15 I think I would prefer that we have a default ctor
32 : ref_count_(0) 40 : ref_count_(initial_ref_count) {
33 #if DCHECK_IS_ON() 41 #if DCHECK_IS_ON()
34 , in_dtor_(false) 42 DCHECK(initial_ref_count == 0 || initial_ref_count == 1);
43 needs_adopt_ref_ = ref_count_ == 1;
35 #endif 44 #endif
36 {
37 } 45 }
38 46
39 ~RefCountedBase() { 47 ~RefCountedBase() {
40 #if DCHECK_IS_ON() 48 #if DCHECK_IS_ON()
41 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; 49 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
42 #endif 50 #endif
43 } 51 }
44 52
45
46 void AddRef() const { 53 void AddRef() const {
47 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 54 // TODO(maruel): Add back once it doesn't assert 500 times/sec.
48 // Current thread books the critical section "AddRelease" 55 // Current thread books the critical section "AddRelease"
49 // without release it. 56 // without release it.
50 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); 57 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
51 #if DCHECK_IS_ON() 58 #if DCHECK_IS_ON()
52 DCHECK(!in_dtor_); 59 DCHECK(!in_dtor_);
60 DCHECK(!needs_adopt_ref_)
61 << "This RefCounted object is created with non-zero reference count."
62 << " The first reference to such a object has to be made by AdoptRef or"
63 << " MakeShared.";
53 #endif 64 #endif
65
54 ++ref_count_; 66 ++ref_count_;
55 } 67 }
56 68
57 // Returns true if the object should self-delete. 69 // Returns true if the object should self-delete.
58 bool Release() const { 70 bool Release() const {
71 --ref_count_;
72
59 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 73 // TODO(maruel): Add back once it doesn't assert 500 times/sec.
60 // Current thread books the critical section "AddRelease" 74 // Current thread books the critical section "AddRelease"
61 // without release it. 75 // without release it.
62 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); 76 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
77
63 #if DCHECK_IS_ON() 78 #if DCHECK_IS_ON()
64 DCHECK(!in_dtor_); 79 DCHECK(!in_dtor_);
65 #endif 80 if (ref_count_ == 0)
66 if (--ref_count_ == 0) {
67 #if DCHECK_IS_ON()
68 in_dtor_ = true; 81 in_dtor_ = true;
69 #endif 82 #endif
70 return true; 83
71 } 84 return ref_count_ == 0;
dcheng 2017/03/30 04:26:15 What is the purpose / necessity for these changes?
tzik 2017/03/30 13:16:27 Oops, this is a contamination from another CL: htt
72 return false;
73 } 85 }
74 86
75 private: 87 private:
88 template <typename U>
89 friend scoped_refptr<U> base::AdoptRef(U*);
90
91 void Adopted() const {
92 #if DCHECK_IS_ON()
93 DCHECK(needs_adopt_ref_);
94 needs_adopt_ref_ = false;
95 #endif
96 }
97
76 mutable size_t ref_count_; 98 mutable size_t ref_count_;
99
77 #if DCHECK_IS_ON() 100 #if DCHECK_IS_ON()
78 mutable bool in_dtor_; 101 mutable bool needs_adopt_ref_;
102 mutable bool in_dtor_ = false;
79 #endif 103 #endif
80 104
81 DFAKE_MUTEX(add_release_); 105 DFAKE_MUTEX(add_release_);
82 106
83 DISALLOW_COPY_AND_ASSIGN(RefCountedBase); 107 DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
84 }; 108 };
85 109
86 class BASE_EXPORT RefCountedThreadSafeBase { 110 class BASE_EXPORT RefCountedThreadSafeBase {
87 public: 111 public:
88 bool HasOneRef() const; 112 bool HasOneRef() const;
89 113
90 protected: 114 protected:
91 RefCountedThreadSafeBase(); 115 explicit RefCountedThreadSafeBase(AtomicRefCount initial_ref_count = 0)
116 : ref_count_(initial_ref_count) {
117 #if DCHECK_IS_ON()
118 needs_adopt_ref_ = initial_ref_count == 1;
119 #endif
120 }
121
92 ~RefCountedThreadSafeBase(); 122 ~RefCountedThreadSafeBase();
93 123
94 void AddRef() const; 124 void AddRef() const;
95 125
96 // Returns true if the object should self-delete. 126 // Returns true if the object should self-delete.
97 bool Release() const; 127 bool Release() const;
98 128
99 private: 129 private:
100 mutable AtomicRefCount ref_count_ = 0; 130 template <typename U>
131 friend scoped_refptr<U> base::AdoptRef(U*);
132
133 void Adopted() const {
101 #if DCHECK_IS_ON() 134 #if DCHECK_IS_ON()
135 DCHECK(needs_adopt_ref_);
136 needs_adopt_ref_ = false;
137 #endif
138 }
139
140 mutable AtomicRefCount ref_count_;
141 #if DCHECK_IS_ON()
142 mutable bool needs_adopt_ref_;
102 mutable bool in_dtor_ = false; 143 mutable bool in_dtor_ = false;
103 #endif 144 #endif
104 145
105 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); 146 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
106 }; 147 };
107 148
108 } // namespace subtle 149 } // namespace subtle
109 150
110 // 151 //
111 // A base class for reference counted classes. Otherwise, known as a cheap 152 // A base class for reference counted classes. Otherwise, known as a cheap
112 // knock-off of WebKit's RefCounted<T> class. To use this, just extend your 153 // knock-off of WebKit's RefCounted<T> class. To use this, just extend your
113 // class from it like so: 154 // class from it like so:
114 // 155 //
115 // class MyFoo : public base::RefCounted<MyFoo> { 156 // class MyFoo : public base::RefCounted<MyFoo> {
116 // ... 157 // ...
117 // private: 158 // private:
118 // friend class base::RefCounted<MyFoo>; 159 // friend class base::RefCounted<MyFoo>;
119 // ~MyFoo(); 160 // ~MyFoo();
120 // }; 161 // };
121 // 162 //
122 // You should always make your destructor non-public, to avoid any code deleting 163 // You should always make your destructor non-public, to avoid any code deleting
123 // the object accidently while there are references to it. 164 // the object accidently while there are references to it.
124 template <class T> 165 template <class T>
125 class RefCounted : public subtle::RefCountedBase { 166 class RefCounted : public subtle::RefCountedBase {
126 public: 167 public:
127 RefCounted() = default; 168 explicit RefCounted(size_t initial_ref_count = 0)
169 : subtle::RefCountedBase(initial_ref_count) {}
128 170
129 void AddRef() const { 171 void AddRef() const {
130 subtle::RefCountedBase::AddRef(); 172 subtle::RefCountedBase::AddRef();
131 } 173 }
132 174
133 void Release() const { 175 void Release() const {
134 if (subtle::RefCountedBase::Release()) { 176 if (subtle::RefCountedBase::Release()) {
135 delete static_cast<const T*>(this); 177 delete static_cast<const T*>(this);
136 } 178 }
137 } 179 }
(...skipping 29 matching lines...) Expand all
167 // }; 209 // };
168 // 210 //
169 // If you're using the default trait, then you should add compile time 211 // If you're using the default trait, then you should add compile time
170 // asserts that no one else is deleting your object. i.e. 212 // asserts that no one else is deleting your object. i.e.
171 // private: 213 // private:
172 // friend class base::RefCountedThreadSafe<MyFoo>; 214 // friend class base::RefCountedThreadSafe<MyFoo>;
173 // ~MyFoo(); 215 // ~MyFoo();
174 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > 216 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
175 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { 217 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
176 public: 218 public:
177 RefCountedThreadSafe() = default; 219 explicit RefCountedThreadSafe(AtomicRefCount initial_ref_count = 0)
220 : subtle::RefCountedThreadSafeBase(initial_ref_count) {}
178 221
179 void AddRef() const { 222 void AddRef() const {
180 subtle::RefCountedThreadSafeBase::AddRef(); 223 subtle::RefCountedThreadSafeBase::AddRef();
181 } 224 }
182 225
183 void Release() const { 226 void Release() const {
184 if (subtle::RefCountedThreadSafeBase::Release()) { 227 if (subtle::RefCountedThreadSafeBase::Release()) {
185 Traits::Destruct(static_cast<const T*>(this)); 228 Traits::Destruct(static_cast<const T*>(this));
186 } 229 }
187 } 230 }
(...skipping 19 matching lines...) Expand all
207 RefCountedData() : data() {} 250 RefCountedData() : data() {}
208 RefCountedData(const T& in_value) : data(in_value) {} 251 RefCountedData(const T& in_value) : data(in_value) {}
209 252
210 T data; 253 T data;
211 254
212 private: 255 private:
213 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >; 256 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >;
214 ~RefCountedData() = default; 257 ~RefCountedData() = default;
215 }; 258 };
216 259
260 // Creates a scoped_refptr from a raw pointer without incrementing the reference
261 // count. Use this only for a newly created object whose reference count starts
262 // from 1 instead of 0.
263 template <typename T>
264 scoped_refptr<T> AdoptRef(T* t) {
265 DCHECK(!t || t->HasOneRef());
dcheng 2017/03/30 04:26:16 Hmm... why would we want to handle a null |t| here
tzik 2017/03/30 13:16:27 OK, updated to force nun-null.
266 if (t)
267 t->Adopted();
268 return scoped_refptr<T>(t, subtle::kAdoptRefTag);
269 }
270
271 // Constructs an instance of T, which is a ref counted type, and wraps the
272 // object into a scoped_refptr.
273 template <typename T, typename... Args>
274 scoped_refptr<T> MakeShared(Args&&... args) {
275 T* obj = new T(std::forward<Args>(args)...);
276 if (obj->HasOneRef())
277 return AdoptRef(obj);
278 return scoped_refptr<T>(obj);
dcheng 2017/03/30 04:26:16 Not sure if it's possible, but it would be nice if
tzik 2017/03/30 13:16:27 Trying that.
279 }
280
217 } // namespace base 281 } // namespace base
218 282
219 // 283 //
220 // A smart pointer class for reference counted objects. Use this class instead 284 // A smart pointer class for reference counted objects. Use this class instead
221 // of calling AddRef and Release manually on a reference counted object to 285 // of calling AddRef and Release manually on a reference counted object to
222 // avoid common memory leaks caused by forgetting to Release an object 286 // avoid common memory leaks caused by forgetting to Release an object
223 // reference. Sample usage: 287 // reference. Sample usage:
224 // 288 //
225 // class MyFoo : public RefCounted<MyFoo> { 289 // class MyFoo : public RefCounted<MyFoo> {
226 // ... 290 // ...
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 438
375 template <typename U> 439 template <typename U>
376 bool operator<(const scoped_refptr<U>& rhs) const { 440 bool operator<(const scoped_refptr<U>& rhs) const {
377 return ptr_ < rhs.get(); 441 return ptr_ < rhs.get();
378 } 442 }
379 443
380 protected: 444 protected:
381 T* ptr_ = nullptr; 445 T* ptr_ = nullptr;
382 446
383 private: 447 private:
448 template <typename U>
449 friend scoped_refptr<U> base::AdoptRef(U*);
450
451 scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {}
452
384 // Friend required for move constructors that set r.ptr_ to null. 453 // Friend required for move constructors that set r.ptr_ to null.
385 template <typename U> 454 template <typename U>
386 friend class scoped_refptr; 455 friend class scoped_refptr;
387 456
388 // Non-inline helpers to allow: 457 // Non-inline helpers to allow:
389 // class Opaque; 458 // class Opaque;
390 // extern template class scoped_refptr<Opaque>; 459 // extern template class scoped_refptr<Opaque>;
391 // Otherwise the compiler will complain that Opaque is an incomplete type. 460 // Otherwise the compiler will complain that Opaque is an incomplete type.
392 static void AddRef(T* ptr); 461 static void AddRef(T* ptr);
393 static void Release(T* ptr); 462 static void Release(T* ptr);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { 520 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) {
452 return !operator==(null, rhs); 521 return !operator==(null, rhs);
453 } 522 }
454 523
455 template <typename T> 524 template <typename T>
456 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { 525 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
457 return out << p.get(); 526 return out << p.get();
458 } 527 }
459 528
460 #endif // BASE_MEMORY_REF_COUNTED_H_ 529 #endif // BASE_MEMORY_REF_COUNTED_H_
OLDNEW
« no previous file with comments | « base/callback_internal.cc ('k') | base/memory/ref_counted.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698