1 /* 2 * Copyright 2011 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // Originally these classes are from Chromium. 12 // http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/ref_counted.h?view=markup 13 14 // 15 // A smart pointer class for reference counted objects. Use this class instead 16 // of calling AddRef and Release manually on a reference counted object to 17 // avoid common memory leaks caused by forgetting to Release an object 18 // reference. Sample usage: 19 // 20 // class MyFoo : public RefCounted<MyFoo> { 21 // ... 22 // }; 23 // 24 // void some_function() { 25 // scoped_refptr<MyFoo> foo = new MyFoo(); 26 // foo->Method(param); 27 // // `foo` is released when this function returns 28 // } 29 // 30 // void some_other_function() { 31 // scoped_refptr<MyFoo> foo = new MyFoo(); 32 // ... 33 // foo = nullptr; // explicitly releases `foo` 34 // ... 35 // if (foo) 36 // foo->Method(param); 37 // } 38 // 39 // The above examples show how scoped_refptr<T> acts like a pointer to T. 40 // Given two scoped_refptr<T> classes, it is also possible to exchange 41 // references between the two objects, like so: 42 // 43 // { 44 // scoped_refptr<MyFoo> a = new MyFoo(); 45 // scoped_refptr<MyFoo> b; 46 // 47 // b.swap(a); 48 // // now, `b` references the MyFoo object, and `a` references null. 49 // } 50 // 51 // To make both `a` and `b` in the above example reference the same MyFoo 52 // object, simply use the assignment operator: 53 // 54 // { 55 // scoped_refptr<MyFoo> a = new MyFoo(); 56 // scoped_refptr<MyFoo> b; 57 // 58 // b = a; 59 // // now, `a` and `b` each own a reference to the same MyFoo object. 60 // } 61 // 62 63 #ifndef API_SCOPED_REFPTR_H_ 64 #define API_SCOPED_REFPTR_H_ 65 66 #include <memory> 67 #include <utility> 68 69 namespace rtc { 70 71 template <class T> 72 class scoped_refptr { 73 public: 74 typedef T element_type; 75 scoped_refptr()76 scoped_refptr() : ptr_(nullptr) {} scoped_refptr(std::nullptr_t)77 scoped_refptr(std::nullptr_t) : ptr_(nullptr) {} // NOLINT(runtime/explicit) 78 scoped_refptr(T * p)79 explicit scoped_refptr(T* p) : ptr_(p) { 80 if (ptr_) 81 ptr_->AddRef(); 82 } 83 scoped_refptr(const scoped_refptr<T> & r)84 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { 85 if (ptr_) 86 ptr_->AddRef(); 87 } 88 89 template <typename U> scoped_refptr(const scoped_refptr<U> & r)90 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { 91 if (ptr_) 92 ptr_->AddRef(); 93 } 94 95 // Move constructors. scoped_refptr(scoped_refptr<T> && r)96 scoped_refptr(scoped_refptr<T>&& r) noexcept : ptr_(r.release()) {} 97 98 template <typename U> scoped_refptr(scoped_refptr<U> && r)99 scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.release()) {} 100 ~scoped_refptr()101 ~scoped_refptr() { 102 if (ptr_) 103 ptr_->Release(); 104 } 105 get()106 T* get() const { return ptr_; } 107 explicit operator bool() const { return ptr_ != nullptr; } 108 T& operator*() const { return *ptr_; } 109 T* operator->() const { return ptr_; } 110 111 // Returns the (possibly null) raw pointer, and makes the scoped_refptr hold a 112 // null pointer, all without touching the reference count of the underlying 113 // pointed-to object. The object is still reference counted, and the caller of 114 // release() is now the proud owner of one reference, so it is responsible for 115 // calling Release() once on the object when no longer using it. release()116 T* release() { 117 T* retVal = ptr_; 118 ptr_ = nullptr; 119 return retVal; 120 } 121 122 scoped_refptr<T>& operator=(T* p) { 123 // AddRef first so that self assignment should work 124 if (p) 125 p->AddRef(); 126 if (ptr_) 127 ptr_->Release(); 128 ptr_ = p; 129 return *this; 130 } 131 132 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { 133 return *this = r.ptr_; 134 } 135 136 template <typename U> 137 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { 138 return *this = r.get(); 139 } 140 141 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) noexcept { 142 scoped_refptr<T>(std::move(r)).swap(*this); 143 return *this; 144 } 145 146 template <typename U> 147 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) noexcept { 148 scoped_refptr<T>(std::move(r)).swap(*this); 149 return *this; 150 } 151 swap(T ** pp)152 void swap(T** pp) noexcept { 153 T* p = ptr_; 154 ptr_ = *pp; 155 *pp = p; 156 } 157 swap(scoped_refptr<T> & r)158 void swap(scoped_refptr<T>& r) noexcept { swap(&r.ptr_); } 159 160 protected: 161 T* ptr_; 162 }; 163 164 template <typename T, typename U> 165 bool operator==(const rtc::scoped_refptr<T>& a, 166 const rtc::scoped_refptr<U>& b) { 167 return a.get() == b.get(); 168 } 169 template <typename T, typename U> 170 bool operator!=(const rtc::scoped_refptr<T>& a, 171 const rtc::scoped_refptr<U>& b) { 172 return !(a == b); 173 } 174 175 template <typename T> 176 bool operator==(const rtc::scoped_refptr<T>& a, std::nullptr_t) { 177 return a.get() == nullptr; 178 } 179 180 template <typename T> 181 bool operator!=(const rtc::scoped_refptr<T>& a, std::nullptr_t) { 182 return !(a == nullptr); 183 } 184 185 template <typename T> 186 bool operator==(std::nullptr_t, const rtc::scoped_refptr<T>& a) { 187 return a.get() == nullptr; 188 } 189 190 template <typename T> 191 bool operator!=(std::nullptr_t, const rtc::scoped_refptr<T>& a) { 192 return !(a == nullptr); 193 } 194 195 // Comparison with raw pointer. 196 template <typename T, typename U> 197 bool operator==(const rtc::scoped_refptr<T>& a, const U* b) { 198 return a.get() == b; 199 } 200 template <typename T, typename U> 201 bool operator!=(const rtc::scoped_refptr<T>& a, const U* b) { 202 return !(a == b); 203 } 204 205 template <typename T, typename U> 206 bool operator==(const T* a, const rtc::scoped_refptr<U>& b) { 207 return a == b.get(); 208 } 209 template <typename T, typename U> 210 bool operator!=(const T* a, const rtc::scoped_refptr<U>& b) { 211 return !(a == b); 212 } 213 214 // Ordered comparison, needed for use as a std::map key. 215 template <typename T, typename U> 216 bool operator<(const rtc::scoped_refptr<T>& a, const rtc::scoped_refptr<U>& b) { 217 return a.get() < b.get(); 218 } 219 220 } // namespace rtc 221 222 #endif // API_SCOPED_REFPTR_H_ 223