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 3 // found in the LICENSE file. 4 5 #ifndef BASE_MEMORY_REF_COUNTED_H_ 6 #define BASE_MEMORY_REF_COUNTED_H_ 7 8 #include <cassert> 9 10 #include "base/atomic_ref_count.h" 11 #include "base/base_export.h" 12 #include "base/compiler_specific.h" 13 #ifndef NDEBUG 14 #include "base/logging.h" 15 #endif 16 #include "base/threading/thread_collision_warner.h" 17 18 namespace base { 19 20 namespace subtle { 21 22 class BASE_EXPORT RefCountedBase { 23 public: 24 bool HasOneRef() const { return ref_count_ == 1; } 25 26 protected: 27 RefCountedBase() 28 : ref_count_(0) 29 #ifndef NDEBUG 30 , in_dtor_(false) 31 #endif 32 { 33 } 34 35 ~RefCountedBase() { 36 #ifndef NDEBUG 37 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; 38 #endif 39 } 40 41 42 void AddRef() const { 43 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 44 // Current thread books the critical section "AddRelease" 45 // without release it. 46 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); 47 #ifndef NDEBUG 48 DCHECK(!in_dtor_); 49 #endif 50 ++ref_count_; 51 } 52 53 // Returns true if the object should self-delete. 54 bool Release() const { 55 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 56 // Current thread books the critical section "AddRelease" 57 // without release it. 58 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); 59 #ifndef NDEBUG 60 DCHECK(!in_dtor_); 61 #endif 62 if (--ref_count_ == 0) { 63 #ifndef NDEBUG 64 in_dtor_ = true; 65 #endif 66 return true; 67 } 68 return false; 69 } 70 71 private: 72 mutable int ref_count_; 73 #ifndef NDEBUG 74 mutable bool in_dtor_; 75 #endif 76 77 DFAKE_MUTEX(add_release_); 78 79 DISALLOW_COPY_AND_ASSIGN(RefCountedBase); 80 }; 81 82 class BASE_EXPORT RefCountedThreadSafeBase { 83 public: 84 bool HasOneRef() const; 85 86 protected: 87 RefCountedThreadSafeBase(); 88 ~RefCountedThreadSafeBase(); 89 90 void AddRef() const; 91 92 // Returns true if the object should self-delete. 93 bool Release() const; 94 95 private: 96 mutable AtomicRefCount ref_count_; 97 #ifndef NDEBUG 98 mutable bool in_dtor_; 99 #endif 100 101 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); 102 }; 103 104 } // namespace subtle 105 106 // 107 // A base class for reference counted classes. Otherwise, known as a cheap 108 // knock-off of WebKit's RefCounted<T> class. To use this guy just extend your 109 // class from it like so: 110 // 111 // class MyFoo : public base::RefCounted<MyFoo> { 112 // ... 113 // private: 114 // friend class base::RefCounted<MyFoo>; 115 // ~MyFoo(); 116 // }; 117 // 118 // You should always make your destructor private, to avoid any code deleting 119 // the object accidently while there are references to it. 120 template <class T> 121 class RefCounted : public subtle::RefCountedBase { 122 public: 123 RefCounted() {} 124 125 void AddRef() const { 126 subtle::RefCountedBase::AddRef(); 127 } 128 129 void Release() const { 130 if (subtle::RefCountedBase::Release()) { 131 delete static_cast<const T*>(this); 132 } 133 } 134 135 protected: 136 ~RefCounted() {} 137 138 private: 139 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>); 140 }; 141 142 // Forward declaration. 143 template <class T, typename Traits> class RefCountedThreadSafe; 144 145 // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref 146 // count reaches 0. Overload to delete it on a different thread etc. 147 template<typename T> 148 struct DefaultRefCountedThreadSafeTraits { 149 static void Destruct(const T* x) { 150 // Delete through RefCountedThreadSafe to make child classes only need to be 151 // friend with RefCountedThreadSafe instead of this struct, which is an 152 // implementation detail. 153 RefCountedThreadSafe<T, 154 DefaultRefCountedThreadSafeTraits>::DeleteInternal(x); 155 } 156 }; 157 158 // 159 // A thread-safe variant of RefCounted<T> 160 // 161 // class MyFoo : public base::RefCountedThreadSafe<MyFoo> { 162 // ... 163 // }; 164 // 165 // If you're using the default trait, then you should add compile time 166 // asserts that no one else is deleting your object. i.e. 167 // private: 168 // friend class base::RefCountedThreadSafe<MyFoo>; 169 // ~MyFoo(); 170 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > 171 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { 172 public: 173 RefCountedThreadSafe() {} 174 175 void AddRef() const { 176 subtle::RefCountedThreadSafeBase::AddRef(); 177 } 178 179 void Release() const { 180 if (subtle::RefCountedThreadSafeBase::Release()) { 181 Traits::Destruct(static_cast<const T*>(this)); 182 } 183 } 184 185 protected: 186 ~RefCountedThreadSafe() {} 187 188 private: 189 friend struct DefaultRefCountedThreadSafeTraits<T>; 190 static void DeleteInternal(const T* x) { delete x; } 191 192 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); 193 }; 194 195 // 196 // A thread-safe wrapper for some piece of data so we can place other 197 // things in scoped_refptrs<>. 198 // 199 template<typename T> 200 class RefCountedData 201 : public base::RefCountedThreadSafe< base::RefCountedData<T> > { 202 public: 203 RefCountedData() : data() {} 204 RefCountedData(const T& in_value) : data(in_value) {} 205 206 T data; 207 208 private: 209 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >; 210 ~RefCountedData() {} 211 }; 212 213 } // namespace base 214 215 // 216 // A smart pointer class for reference counted objects. Use this class instead 217 // of calling AddRef and Release manually on a reference counted object to 218 // avoid common memory leaks caused by forgetting to Release an object 219 // reference. Sample usage: 220 // 221 // class MyFoo : public RefCounted<MyFoo> { 222 // ... 223 // }; 224 // 225 // void some_function() { 226 // scoped_refptr<MyFoo> foo = new MyFoo(); 227 // foo->Method(param); 228 // // |foo| is released when this function returns 229 // } 230 // 231 // void some_other_function() { 232 // scoped_refptr<MyFoo> foo = new MyFoo(); 233 // ... 234 // foo = NULL; // explicitly releases |foo| 235 // ... 236 // if (foo) 237 // foo->Method(param); 238 // } 239 // 240 // The above examples show how scoped_refptr<T> acts like a pointer to T. 241 // Given two scoped_refptr<T> classes, it is also possible to exchange 242 // references between the two objects, like so: 243 // 244 // { 245 // scoped_refptr<MyFoo> a = new MyFoo(); 246 // scoped_refptr<MyFoo> b; 247 // 248 // b.swap(a); 249 // // now, |b| references the MyFoo object, and |a| references NULL. 250 // } 251 // 252 // To make both |a| and |b| in the above example reference the same MyFoo 253 // object, simply use the assignment operator: 254 // 255 // { 256 // scoped_refptr<MyFoo> a = new MyFoo(); 257 // scoped_refptr<MyFoo> b; 258 // 259 // b = a; 260 // // now, |a| and |b| each own a reference to the same MyFoo object. 261 // } 262 // 263 template <class T> 264 class scoped_refptr { 265 public: 266 typedef T element_type; 267 268 scoped_refptr() : ptr_(NULL) { 269 } 270 271 scoped_refptr(T* p) : ptr_(p) { 272 if (ptr_) 273 ptr_->AddRef(); 274 } 275 276 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { 277 if (ptr_) 278 ptr_->AddRef(); 279 } 280 281 template <typename U> 282 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { 283 if (ptr_) 284 ptr_->AddRef(); 285 } 286 287 ~scoped_refptr() { 288 if (ptr_) 289 ptr_->Release(); 290 } 291 292 T* get() const { return ptr_; } 293 294 // Allow scoped_refptr<C> to be used in boolean expression 295 // and comparison operations. 296 operator T*() const { return ptr_; } 297 298 T* operator->() const { 299 assert(ptr_ != NULL); 300 return ptr_; 301 } 302 303 scoped_refptr<T>& operator=(T* p) { 304 // AddRef first so that self assignment should work 305 if (p) 306 p->AddRef(); 307 T* old_ptr = ptr_; 308 ptr_ = p; 309 if (old_ptr) 310 old_ptr->Release(); 311 return *this; 312 } 313 314 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { 315 return *this = r.ptr_; 316 } 317 318 template <typename U> 319 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { 320 return *this = r.get(); 321 } 322 323 void swap(T** pp) { 324 T* p = ptr_; 325 ptr_ = *pp; 326 *pp = p; 327 } 328 329 void swap(scoped_refptr<T>& r) { 330 swap(&r.ptr_); 331 } 332 333 protected: 334 T* ptr_; 335 }; 336 337 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without 338 // having to retype all the template arguments 339 template <typename T> 340 scoped_refptr<T> make_scoped_refptr(T* t) { 341 return scoped_refptr<T>(t); 342 } 343 344 #endif // BASE_MEMORY_REF_COUNTED_H_ 345