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

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

Issue 1004593005: base::RefCounted now DCHECKs when referenced from multiple threads. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix lots of tests using UnsafeRefCounted. Created 5 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
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 <cassert> 8 #include <cassert>
9 #include <iosfwd> 9 #include <iosfwd>
10 10
11 #include "base/atomic_ref_count.h" 11 #include "base/atomic_ref_count.h"
12 #include "base/base_export.h" 12 #include "base/base_export.h"
13 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
14 #ifndef NDEBUG 14 #ifndef NDEBUG
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #endif 16 #endif
17 #include "base/threading/thread_checker.h"
17 #include "base/threading/thread_collision_warner.h" 18 #include "base/threading/thread_collision_warner.h"
18 #include "build/build_config.h" 19 #include "build/build_config.h"
19 20
20 namespace base { 21 namespace base {
21 22
22 namespace subtle { 23 namespace subtle {
23 24
24 class BASE_EXPORT RefCountedBase { 25 class BASE_EXPORT RefCountedBase {
25 public: 26 public:
26 bool HasOneRef() const { return ref_count_ == 1; } 27 bool HasOneRef() const { return ref_count_ == 1; }
(...skipping 11 matching lines...) Expand all
38 #ifndef NDEBUG 39 #ifndef NDEBUG
39 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; 40 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
40 #endif 41 #endif
41 } 42 }
42 43
43 44
44 void AddRef() const { 45 void AddRef() const {
45 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 46 // TODO(maruel): Add back once it doesn't assert 500 times/sec.
46 // Current thread books the critical section "AddRelease" 47 // Current thread books the critical section "AddRelease"
47 // without release it. 48 // without release it.
48 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); 49 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
noyau (Ping after 24h) 2015/03/24 09:01:21 Since your code is now doing the same thing, it's
49 #ifndef NDEBUG 50 #ifndef NDEBUG
50 DCHECK(!in_dtor_); 51 DCHECK(!in_dtor_);
51 #endif 52 #endif
52 ++ref_count_; 53 ++ref_count_;
53 } 54 }
54 55
55 // Returns true if the object should self-delete. 56 // Returns true if the object should self-delete.
56 bool Release() const { 57 bool Release() const {
57 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 58 // TODO(maruel): Add back once it doesn't assert 500 times/sec.
58 // Current thread books the critical section "AddRelease" 59 // Current thread books the critical section "AddRelease"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 // 113 //
113 // class MyFoo : public base::RefCounted<MyFoo> { 114 // class MyFoo : public base::RefCounted<MyFoo> {
114 // ... 115 // ...
115 // private: 116 // private:
116 // friend class base::RefCounted<MyFoo>; 117 // friend class base::RefCounted<MyFoo>;
117 // ~MyFoo(); 118 // ~MyFoo();
118 // }; 119 // };
119 // 120 //
120 // You should always make your destructor private, to avoid any code deleting 121 // You should always make your destructor private, to avoid any code deleting
121 // the object accidently while there are references to it. 122 // the object accidently while there are references to it.
123 //
124 // RefCounted objects are not thread-safe. To use a ref-counted object from more
125 // than one thead, use a RefCountedThreadSafe.
122 template <class T> 126 template <class T>
123 class RefCounted : public subtle::RefCountedBase { 127 class RefCounted : public subtle::RefCountedBase {
124 public: 128 public:
125 RefCounted() {} 129 RefCounted() {}
126 130
127 void AddRef() const { 131 void AddRef() const {
132 DCHECK(thread_checker_.CalledOnValidThread());
128 subtle::RefCountedBase::AddRef(); 133 subtle::RefCountedBase::AddRef();
129 } 134 }
130 135
131 void Release() const { 136 void Release() const {
137 DCHECK(thread_checker_.CalledOnValidThread());
132 if (subtle::RefCountedBase::Release()) { 138 if (subtle::RefCountedBase::Release()) {
133 delete static_cast<const T*>(this); 139 delete static_cast<const T*>(this);
134 } 140 }
135 } 141 }
136 142
137 protected: 143 protected:
138 ~RefCounted() {} 144 ~RefCounted() {}
139 145
140 private: 146 private:
147 base::ThreadChecker thread_checker_;
148
141 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>); 149 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
142 }; 150 };
143 151
152 // Same as RefCounted, but does not enforce thread safety. Subclasses of
153 // UnsafeRefCounted probably have race conditions and should be fixed up, either
154 // by ensuring they are only referenced from one thread (and moving to
155 // RefCounted), or by moving to RefCountedThreadSafe.
156 template <class T>
157 class UnsafeRefCounted : public subtle::RefCountedBase {
158 public:
159 UnsafeRefCounted() {}
160
161 void AddRef() const { subtle::RefCountedBase::AddRef(); }
162
163 void Release() const {
164 if (subtle::RefCountedBase::Release())
165 delete static_cast<const T*>(this);
166 }
167
168 protected:
169 ~UnsafeRefCounted() {}
170
171 private:
172 DISALLOW_COPY_AND_ASSIGN(UnsafeRefCounted<T>);
173 };
174
144 // Forward declaration. 175 // Forward declaration.
145 template <class T, typename Traits> class RefCountedThreadSafe; 176 template <class T, typename Traits> class RefCountedThreadSafe;
146 177
147 // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref 178 // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
148 // count reaches 0. Overload to delete it on a different thread etc. 179 // count reaches 0. Overload to delete it on a different thread etc.
149 template<typename T> 180 template<typename T>
150 struct DefaultRefCountedThreadSafeTraits { 181 struct DefaultRefCountedThreadSafeTraits {
151 static void Destruct(const T* x) { 182 static void Destruct(const T* x) {
152 // Delete through RefCountedThreadSafe to make child classes only need to be 183 // Delete through RefCountedThreadSafe to make child classes only need to be
153 // friend with RefCountedThreadSafe instead of this struct, which is an 184 // friend with RefCountedThreadSafe instead of this struct, which is an
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) { 442 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
412 return !operator==(lhs, rhs); 443 return !operator==(lhs, rhs);
413 } 444 }
414 445
415 template <typename T> 446 template <typename T>
416 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { 447 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
417 return out << p.get(); 448 return out << p.get();
418 } 449 }
419 450
420 #endif // BASE_MEMORY_REF_COUNTED_H_ 451 #endif // BASE_MEMORY_REF_COUNTED_H_
OLDNEW
« no previous file with comments | « base/deferred_sequenced_task_runner_unittest.cc ('k') | components/nacl/loader/nacl_ipc_adapter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698