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