scoped_refptr.h (5961B)
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 = make_ref_counted<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 = make_ref_counted<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 = make_ref_counted<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 = make_ref_counted<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 <cstddef> 67 #include <utility> 68 69 #include "absl/base/nullability.h" 70 71 namespace webrtc { 72 73 template <class T> 74 class ABSL_NULLABILITY_COMPATIBLE scoped_refptr { 75 public: 76 using element_type = T; 77 78 scoped_refptr() : ptr_(nullptr) {} 79 scoped_refptr(std::nullptr_t) : ptr_(nullptr) {} // NOLINT(runtime/explicit) 80 81 explicit scoped_refptr(T* absl_nullable p) : ptr_(p) { 82 if (ptr_) 83 ptr_->AddRef(); 84 } 85 86 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { 87 if (ptr_) 88 ptr_->AddRef(); 89 } 90 91 template <typename U> 92 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { 93 if (ptr_) 94 ptr_->AddRef(); 95 } 96 97 // Move constructors. 98 scoped_refptr(scoped_refptr<T>&& r) noexcept : ptr_(r.release()) {} 99 100 template <typename U> 101 scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.release()) {} 102 103 ~scoped_refptr() { 104 if (ptr_) 105 ptr_->Release(); 106 } 107 108 T* get() const { return ptr_; } 109 explicit operator bool() const { return ptr_ != nullptr; } 110 T& operator*() const { return *ptr_; } 111 T* operator->() const { return ptr_; } 112 113 // Returns the (possibly null) raw pointer, and makes the scoped_refptr hold a 114 // null pointer, all without touching the reference count of the underlying 115 // pointed-to object. The object is still reference counted, and the caller of 116 // release() is now the proud owner of one reference, so it is responsible for 117 // calling Release() once on the object when no longer using it. 118 T* release() { 119 T* retVal = ptr_; 120 ptr_ = nullptr; 121 return retVal; 122 } 123 124 scoped_refptr<T>& operator=(T* absl_nullable p) { 125 // AddRef first so that self assignment should work 126 if (p) 127 p->AddRef(); 128 if (ptr_) 129 ptr_->Release(); 130 ptr_ = p; 131 return *this; 132 } 133 134 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { 135 return *this = r.ptr_; 136 } 137 138 template <typename U> 139 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { 140 return *this = r.get(); 141 } 142 143 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) noexcept { 144 scoped_refptr<T>(std::move(r)).swap(*this); 145 return *this; 146 } 147 148 template <typename U> 149 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) noexcept { 150 scoped_refptr<T>(std::move(r)).swap(*this); 151 return *this; 152 } 153 154 void swap(T** absl_nonnull pp) noexcept { 155 T* p = ptr_; 156 ptr_ = *pp; 157 *pp = p; 158 } 159 160 void swap(scoped_refptr<T>& r) noexcept { swap(&r.ptr_); } 161 162 protected: 163 T* ptr_; 164 }; 165 166 template <typename T, typename U> 167 bool operator==(const scoped_refptr<T>& a, const scoped_refptr<U>& b) { 168 return a.get() == b.get(); 169 } 170 template <typename T, typename U> 171 bool operator!=(const scoped_refptr<T>& a, const scoped_refptr<U>& b) { 172 return !(a == b); 173 } 174 175 template <typename T> 176 bool operator==(const scoped_refptr<T>& a, std::nullptr_t) { 177 return a.get() == nullptr; 178 } 179 180 template <typename T> 181 bool operator!=(const scoped_refptr<T>& a, std::nullptr_t) { 182 return !(a == nullptr); 183 } 184 185 template <typename T> 186 bool operator==(std::nullptr_t, const scoped_refptr<T>& a) { 187 return a.get() == nullptr; 188 } 189 190 template <typename T> 191 bool operator!=(std::nullptr_t, const 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 scoped_refptr<T>& a, const U* b) { 198 return a.get() == b; 199 } 200 template <typename T, typename U> 201 bool operator!=(const 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 scoped_refptr<U>& b) { 207 return a == b.get(); 208 } 209 template <typename T, typename U> 210 bool operator!=(const T* a, const 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 scoped_refptr<T>& a, const scoped_refptr<U>& b) { 217 return a.get() < b.get(); 218 } 219 220 } // namespace webrtc 221 222 223 #endif // API_SCOPED_REFPTR_H_