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