[email protected] | 15f8012 | 2010-07-28 16:48:10 | [diff] [blame] | 1 | // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 4 | |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 5 | #ifndef BASE_REF_COUNTED_H_ |
| 6 | #define BASE_REF_COUNTED_H_ |
[email protected] | 32b76ef | 2010-07-26 23:08:24 | [diff] [blame] | 7 | #pragma once |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 8 | |
[email protected] | f9be538 | 2008-08-06 11:55:42 | [diff] [blame] | 9 | #include "base/atomic_ref_count.h" |
[email protected] | 0d02a5f | 2009-01-26 19:29:07 | [diff] [blame] | 10 | #include "base/thread_collision_warner.h" |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 11 | |
| 12 | namespace base { |
| 13 | |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 14 | namespace subtle { |
| 15 | |
| 16 | class RefCountedBase { |
[email protected] | 59326aac | 2009-09-25 23:34:34 | [diff] [blame] | 17 | public: |
[email protected] | 39fe32a | 2009-09-30 04:29:20 | [diff] [blame] | 18 | static bool ImplementsThreadSafeReferenceCounting() { return false; } |
| 19 | |
[email protected] | 59326aac | 2009-09-25 23:34:34 | [diff] [blame] | 20 | bool HasOneRef() const { return ref_count_ == 1; } |
| 21 | |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 22 | protected: |
| 23 | RefCountedBase(); |
| 24 | ~RefCountedBase(); |
| 25 | |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 26 | void AddRef() const; |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 27 | |
| 28 | // Returns true if the object should self-delete. |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 29 | bool Release() const; |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 30 | |
| 31 | private: |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 32 | mutable int ref_count_; |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 33 | #ifndef NDEBUG |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 34 | mutable bool in_dtor_; |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 35 | #endif |
| 36 | |
[email protected] | 0d02a5f | 2009-01-26 19:29:07 | [diff] [blame] | 37 | DFAKE_MUTEX(add_release_); |
| 38 | |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 39 | DISALLOW_COPY_AND_ASSIGN(RefCountedBase); |
| 40 | }; |
| 41 | |
| 42 | class RefCountedThreadSafeBase { |
[email protected] | 59326aac | 2009-09-25 23:34:34 | [diff] [blame] | 43 | public: |
[email protected] | 39fe32a | 2009-09-30 04:29:20 | [diff] [blame] | 44 | static bool ImplementsThreadSafeReferenceCounting() { return true; } |
| 45 | |
[email protected] | 59326aac | 2009-09-25 23:34:34 | [diff] [blame] | 46 | bool HasOneRef() const; |
| 47 | |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 48 | protected: |
| 49 | RefCountedThreadSafeBase(); |
| 50 | ~RefCountedThreadSafeBase(); |
| 51 | |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 52 | void AddRef() const; |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 53 | |
| 54 | // Returns true if the object should self-delete. |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 55 | bool Release() const; |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 56 | |
| 57 | private: |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 58 | mutable AtomicRefCount ref_count_; |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 59 | #ifndef NDEBUG |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 60 | mutable bool in_dtor_; |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 61 | #endif |
| 62 | |
| 63 | DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); |
| 64 | }; |
| 65 | |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 66 | } // namespace subtle |
| 67 | |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 68 | // |
| 69 | // A base class for reference counted classes. Otherwise, known as a cheap |
| 70 | // knock-off of WebKit's RefCounted<T> class. To use this guy just extend your |
| 71 | // class from it like so: |
| 72 | // |
| 73 | // class MyFoo : public base::RefCounted<MyFoo> { |
| 74 | // ... |
[email protected] | 877d55d | 2009-11-05 21:53:08 | [diff] [blame] | 75 | // private: |
| 76 | // friend class base::RefCounted<MyFoo>; |
| 77 | // ~MyFoo(); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 78 | // }; |
| 79 | // |
[email protected] | 877d55d | 2009-11-05 21:53:08 | [diff] [blame] | 80 | // You should always make your destructor private, to avoid any code deleting |
| 81 | // the object accidently while there are references to it. |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 82 | template <class T> |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 83 | class RefCounted : public subtle::RefCountedBase { |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 84 | public: |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 85 | RefCounted() { } |
| 86 | ~RefCounted() { } |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 87 | |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 88 | void AddRef() const { |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 89 | subtle::RefCountedBase::AddRef(); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 90 | } |
| 91 | |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 92 | void Release() const { |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 93 | if (subtle::RefCountedBase::Release()) { |
[email protected] | 41ba551 | 2010-10-02 00:15:02 | [diff] [blame] | 94 | delete static_cast<const T*>(this); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 95 | } |
| 96 | } |
| 97 | |
| 98 | private: |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 99 | DISALLOW_COPY_AND_ASSIGN(RefCounted<T>); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 100 | }; |
| 101 | |
[email protected] | f671062 | 2009-11-02 06:10:30 | [diff] [blame] | 102 | // Forward declaration. |
| 103 | template <class T, typename Traits> class RefCountedThreadSafe; |
| 104 | |
| 105 | // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref |
| 106 | // count reaches 0. Overload to delete it on a different thread etc. |
| 107 | template<typename T> |
| 108 | struct DefaultRefCountedThreadSafeTraits { |
| 109 | static void Destruct(T* x) { |
| 110 | // Delete through RefCountedThreadSafe to make child classes only need to be |
| 111 | // friend with RefCountedThreadSafe instead of this struct, which is an |
| 112 | // implementation detail. |
[email protected] | 15f8012 | 2010-07-28 16:48:10 | [diff] [blame] | 113 | RefCountedThreadSafe<T, |
| 114 | DefaultRefCountedThreadSafeTraits>::DeleteInternal(x); |
[email protected] | f671062 | 2009-11-02 06:10:30 | [diff] [blame] | 115 | } |
| 116 | }; |
| 117 | |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 118 | // |
| 119 | // A thread-safe variant of RefCounted<T> |
| 120 | // |
| 121 | // class MyFoo : public base::RefCountedThreadSafe<MyFoo> { |
| 122 | // ... |
| 123 | // }; |
| 124 | // |
[email protected] | 877d55d | 2009-11-05 21:53:08 | [diff] [blame] | 125 | // If you're using the default trait, then you should add compile time |
[email protected] | f671062 | 2009-11-02 06:10:30 | [diff] [blame] | 126 | // asserts that no one else is deleting your object. i.e. |
| 127 | // private: |
[email protected] | 877d55d | 2009-11-05 21:53:08 | [diff] [blame] | 128 | // friend class base::RefCountedThreadSafe<MyFoo>; |
[email protected] | f671062 | 2009-11-02 06:10:30 | [diff] [blame] | 129 | // ~MyFoo(); |
| 130 | template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 131 | class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 132 | public: |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 133 | RefCountedThreadSafe() { } |
| 134 | ~RefCountedThreadSafe() { } |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 135 | |
| 136 | void AddRef() { |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 137 | subtle::RefCountedThreadSafeBase::AddRef(); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | void Release() { |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 141 | if (subtle::RefCountedThreadSafeBase::Release()) { |
[email protected] | f671062 | 2009-11-02 06:10:30 | [diff] [blame] | 142 | Traits::Destruct(static_cast<T*>(this)); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 143 | } |
| 144 | } |
| 145 | |
[email protected] | be2cfb00 | 2008-12-10 17:42:21 | [diff] [blame] | 146 | private: |
[email protected] | f671062 | 2009-11-02 06:10:30 | [diff] [blame] | 147 | friend struct DefaultRefCountedThreadSafeTraits<T>; |
| 148 | static void DeleteInternal(T* x) { delete x; } |
| 149 | |
| 150 | DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 151 | }; |
| 152 | |
[email protected] | 0aa5531 | 2008-10-17 21:53:08 | [diff] [blame] | 153 | // |
| 154 | // A wrapper for some piece of data so we can place other things in |
| 155 | // scoped_refptrs<>. |
| 156 | // |
| 157 | template<typename T> |
| 158 | class RefCountedData : public base::RefCounted< base::RefCountedData<T> > { |
| 159 | public: |
| 160 | RefCountedData() : data() {} |
| 161 | RefCountedData(const T& in_value) : data(in_value) {} |
| 162 | |
| 163 | T data; |
| 164 | }; |
| 165 | |
[email protected] | 38c1fb71 | 2008-08-15 13:35:59 | [diff] [blame] | 166 | } // namespace base |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 167 | |
| 168 | // |
| 169 | // A smart pointer class for reference counted objects. Use this class instead |
| 170 | // of calling AddRef and Release manually on a reference counted object to |
| 171 | // avoid common memory leaks caused by forgetting to Release an object |
| 172 | // reference. Sample usage: |
| 173 | // |
| 174 | // class MyFoo : public RefCounted<MyFoo> { |
| 175 | // ... |
| 176 | // }; |
| 177 | // |
| 178 | // void some_function() { |
| 179 | // scoped_refptr<MyFoo> foo = new MyFoo(); |
| 180 | // foo->Method(param); |
| 181 | // // |foo| is released when this function returns |
| 182 | // } |
| 183 | // |
| 184 | // void some_other_function() { |
| 185 | // scoped_refptr<MyFoo> foo = new MyFoo(); |
| 186 | // ... |
| 187 | // foo = NULL; // explicitly releases |foo| |
| 188 | // ... |
| 189 | // if (foo) |
| 190 | // foo->Method(param); |
| 191 | // } |
| 192 | // |
| 193 | // The above examples show how scoped_refptr<T> acts like a pointer to T. |
| 194 | // Given two scoped_refptr<T> classes, it is also possible to exchange |
| 195 | // references between the two objects, like so: |
| 196 | // |
| 197 | // { |
| 198 | // scoped_refptr<MyFoo> a = new MyFoo(); |
| 199 | // scoped_refptr<MyFoo> b; |
| 200 | // |
| 201 | // b.swap(a); |
| 202 | // // now, |b| references the MyFoo object, and |a| references NULL. |
| 203 | // } |
| 204 | // |
| 205 | // To make both |a| and |b| in the above example reference the same MyFoo |
| 206 | // object, simply use the assignment operator: |
| 207 | // |
| 208 | // { |
| 209 | // scoped_refptr<MyFoo> a = new MyFoo(); |
| 210 | // scoped_refptr<MyFoo> b; |
| 211 | // |
| 212 | // b = a; |
| 213 | // // now, |a| and |b| each own a reference to the same MyFoo object. |
| 214 | // } |
| 215 | // |
| 216 | template <class T> |
| 217 | class scoped_refptr { |
| 218 | public: |
| 219 | scoped_refptr() : ptr_(NULL) { |
| 220 | } |
| 221 | |
| 222 | scoped_refptr(T* p) : ptr_(p) { |
| 223 | if (ptr_) |
| 224 | ptr_->AddRef(); |
| 225 | } |
| 226 | |
| 227 | scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { |
| 228 | if (ptr_) |
| 229 | ptr_->AddRef(); |
| 230 | } |
| 231 | |
[email protected] | f8f8250 | 2009-11-20 23:14:23 | [diff] [blame] | 232 | template <typename U> |
| 233 | scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { |
| 234 | if (ptr_) |
| 235 | ptr_->AddRef(); |
| 236 | } |
| 237 | |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 238 | ~scoped_refptr() { |
| 239 | if (ptr_) |
| 240 | ptr_->Release(); |
| 241 | } |
| 242 | |
| 243 | T* get() const { return ptr_; } |
| 244 | operator T*() const { return ptr_; } |
| 245 | T* operator->() const { return ptr_; } |
| 246 | |
[email protected] | a5da6d61 | 2009-08-04 02:00:56 | [diff] [blame] | 247 | // Release a pointer. |
| 248 | // The return value is the current pointer held by this object. |
| 249 | // If this object holds a NULL pointer, the return value is NULL. |
| 250 | // After this operation, this object will hold a NULL pointer, |
| 251 | // and will not own the object any more. |
| 252 | T* release() { |
| 253 | T* retVal = ptr_; |
| 254 | ptr_ = NULL; |
| 255 | return retVal; |
| 256 | } |
| 257 | |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 258 | scoped_refptr<T>& operator=(T* p) { |
| 259 | // AddRef first so that self assignment should work |
| 260 | if (p) |
| 261 | p->AddRef(); |
| 262 | if (ptr_ ) |
| 263 | ptr_ ->Release(); |
| 264 | ptr_ = p; |
| 265 | return *this; |
| 266 | } |
| 267 | |
| 268 | scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { |
| 269 | return *this = r.ptr_; |
| 270 | } |
| 271 | |
[email protected] | f8f8250 | 2009-11-20 23:14:23 | [diff] [blame] | 272 | template <typename U> |
| 273 | scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { |
| 274 | return *this = r.get(); |
| 275 | } |
| 276 | |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 277 | void swap(T** pp) { |
| 278 | T* p = ptr_; |
| 279 | ptr_ = *pp; |
| 280 | *pp = p; |
| 281 | } |
| 282 | |
| 283 | void swap(scoped_refptr<T>& r) { |
| 284 | swap(&r.ptr_); |
| 285 | } |
| 286 | |
[email protected] | 935f776 | 2009-01-10 00:53:13 | [diff] [blame] | 287 | protected: |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 288 | T* ptr_; |
| 289 | }; |
| 290 | |
[email protected] | f8f8250 | 2009-11-20 23:14:23 | [diff] [blame] | 291 | // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without |
| 292 | // having to retype all the template arguments |
| 293 | template <typename T> |
| 294 | scoped_refptr<T> make_scoped_refptr(T* t) { |
| 295 | return scoped_refptr<T>(t); |
| 296 | } |
| 297 | |
[email protected] | 1eb89e8 | 2008-08-15 12:27:03 | [diff] [blame] | 298 | #endif // BASE_REF_COUNTED_H_ |