OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Native Client 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 NATIVE_CLIENT_SRC_INCLUDE_REF_COUNTED_H_ |
| 6 #define NATIVE_CLIENT_SRC_INCLUDE_REF_COUNTED_H_ |
| 7 |
| 8 namespace nacl { |
| 9 |
| 10 namespace subtle { |
| 11 |
| 12 class RefCountedBase { |
| 13 public: |
| 14 static bool ImplementsThreadSafeReferenceCounting() { return false; } |
| 15 |
| 16 bool HasOneRef() const { return ref_count_ == 1; } |
| 17 |
| 18 protected: |
| 19 RefCountedBase() : ref_count_(0) { } |
| 20 ~RefCountedBase() { } |
| 21 |
| 22 void AddRef() const { ++ref_count_; } |
| 23 |
| 24 // Returns true if the object should self-delete. |
| 25 bool Release() const { return --ref_count_ == 0; } |
| 26 |
| 27 private: |
| 28 mutable int ref_count_; |
| 29 |
| 30 RefCountedBase(const RefCountedBase&); |
| 31 void operator=(const RefCountedBase&); |
| 32 }; |
| 33 |
| 34 } // namespace subtle |
| 35 |
| 36 // |
| 37 // A base class for reference counted classes. Otherwise, known as a cheap |
| 38 // knock-off of WebKit's RefCounted<T> class. To use this guy just extend your |
| 39 // class from it like so: |
| 40 // |
| 41 // class MyFoo : public nacl::RefCounted<MyFoo> { |
| 42 // ... |
| 43 // private: |
| 44 // friend class nacl::RefCounted<MyFoo>; |
| 45 // ~MyFoo(); |
| 46 // }; |
| 47 // |
| 48 // You should always make your destructor private, to avoid any code deleting |
| 49 // the object accidently while there are references to it. |
| 50 template <class T> |
| 51 class RefCounted : public subtle::RefCountedBase { |
| 52 public: |
| 53 RefCounted() { } |
| 54 ~RefCounted() { } |
| 55 |
| 56 void AddRef() const { |
| 57 subtle::RefCountedBase::AddRef(); |
| 58 } |
| 59 |
| 60 void Release() const { |
| 61 if (subtle::RefCountedBase::Release()) { |
| 62 delete static_cast<const T*>(this); |
| 63 } |
| 64 } |
| 65 |
| 66 private: |
| 67 RefCounted(const RefCounted<T>&); |
| 68 void operator=(const RefCounted<T>&); |
| 69 }; |
| 70 |
| 71 // |
| 72 // A wrapper for some piece of data so we can place other things in |
| 73 // scoped_refptrs<>. |
| 74 // |
| 75 template<typename T> |
| 76 class RefCountedData : public nacl::RefCounted< nacl::RefCountedData<T> > { |
| 77 public: |
| 78 RefCountedData() : data() {} |
| 79 RefCountedData(const T& in_value) : data(in_value) {} |
| 80 |
| 81 T data; |
| 82 }; |
| 83 |
| 84 } // namespace nacl |
| 85 |
| 86 // |
| 87 // A smart pointer class for reference counted objects. Use this class instead |
| 88 // of calling AddRef and Release manually on a reference counted object to |
| 89 // avoid common memory leaks caused by forgetting to Release an object |
| 90 // reference. Sample usage: |
| 91 // |
| 92 // class MyFoo : public RefCounted<MyFoo> { |
| 93 // ... |
| 94 // }; |
| 95 // |
| 96 // void some_function() { |
| 97 // scoped_refptr<MyFoo> foo = new MyFoo(); |
| 98 // foo->Method(param); |
| 99 // // |foo| is released when this function returns |
| 100 // } |
| 101 // |
| 102 // void some_other_function() { |
| 103 // scoped_refptr<MyFoo> foo = new MyFoo(); |
| 104 // ... |
| 105 // foo = NULL; // explicitly releases |foo| |
| 106 // ... |
| 107 // if (foo) |
| 108 // foo->Method(param); |
| 109 // } |
| 110 // |
| 111 // The above examples show how scoped_refptr<T> acts like a pointer to T. |
| 112 // Given two scoped_refptr<T> classes, it is also possible to exchange |
| 113 // references between the two objects, like so: |
| 114 // |
| 115 // { |
| 116 // scoped_refptr<MyFoo> a = new MyFoo(); |
| 117 // scoped_refptr<MyFoo> b; |
| 118 // |
| 119 // b.swap(a); |
| 120 // // now, |b| references the MyFoo object, and |a| references NULL. |
| 121 // } |
| 122 // |
| 123 // To make both |a| and |b| in the above example reference the same MyFoo |
| 124 // object, simply use the assignment operator: |
| 125 // |
| 126 // { |
| 127 // scoped_refptr<MyFoo> a = new MyFoo(); |
| 128 // scoped_refptr<MyFoo> b; |
| 129 // |
| 130 // b = a; |
| 131 // // now, |a| and |b| each own a reference to the same MyFoo object. |
| 132 // } |
| 133 // |
| 134 template <class T> |
| 135 class scoped_refptr { |
| 136 public: |
| 137 scoped_refptr() : ptr_((T*)0) { |
| 138 } |
| 139 |
| 140 scoped_refptr(T* p) : ptr_(p) { |
| 141 if (ptr_) |
| 142 ptr_->AddRef(); |
| 143 } |
| 144 |
| 145 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { |
| 146 if (ptr_) |
| 147 ptr_->AddRef(); |
| 148 } |
| 149 |
| 150 template <typename U> |
| 151 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { |
| 152 if (ptr_) |
| 153 ptr_->AddRef(); |
| 154 } |
| 155 |
| 156 ~scoped_refptr() { |
| 157 if (ptr_) |
| 158 ptr_->Release(); |
| 159 } |
| 160 |
| 161 T* get() const { return ptr_; } |
| 162 operator T*() const { return ptr_; } |
| 163 T* operator->() const { return ptr_; } |
| 164 |
| 165 // Release a pointer. |
| 166 // The return value is the current pointer held by this object. |
| 167 // If this object holds a NULL pointer, the return value is NULL. |
| 168 // After this operation, this object will hold a NULL pointer, |
| 169 // and will not own the object any more. |
| 170 T* release() { |
| 171 T* retVal = ptr_; |
| 172 ptr_ = (void*)0; |
| 173 return retVal; |
| 174 } |
| 175 |
| 176 scoped_refptr<T>& operator=(T* p) { |
| 177 // AddRef first so that self assignment should work |
| 178 if (p) |
| 179 p->AddRef(); |
| 180 if (ptr_ ) |
| 181 ptr_ ->Release(); |
| 182 ptr_ = p; |
| 183 return *this; |
| 184 } |
| 185 |
| 186 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { |
| 187 return *this = r.ptr_; |
| 188 } |
| 189 |
| 190 template <typename U> |
| 191 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { |
| 192 return *this = r.get(); |
| 193 } |
| 194 |
| 195 void swap(T** pp) { |
| 196 T* p = ptr_; |
| 197 ptr_ = *pp; |
| 198 *pp = p; |
| 199 } |
| 200 |
| 201 void swap(scoped_refptr<T>& r) { |
| 202 swap(&r.ptr_); |
| 203 } |
| 204 |
| 205 protected: |
| 206 T* ptr_; |
| 207 }; |
| 208 |
| 209 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without |
| 210 // having to retype all the template arguments |
| 211 template <typename T> |
| 212 scoped_refptr<T> make_scoped_refptr(T* t) { |
| 213 return scoped_refptr<T>(t); |
| 214 } |
| 215 |
| 216 #endif // NATIVE_CLIENT_SRC_INCLUDE_REF_COUNTED_H_ |
| 217 |
OLD | NEW |