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) {} 77 scoped_refptr(T * p)78 scoped_refptr(T* p) : ptr_(p) { // NOLINT(runtime/explicit) 79 if (ptr_) 80 ptr_->AddRef(); 81 } 82 scoped_refptr(const scoped_refptr<T> & r)83 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { 84 if (ptr_) 85 ptr_->AddRef(); 86 } 87 88 template <typename U> scoped_refptr(const scoped_refptr<U> & r)89 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { 90 if (ptr_) 91 ptr_->AddRef(); 92 } 93 94 // Move constructors. scoped_refptr(scoped_refptr<T> && r)95 scoped_refptr(scoped_refptr<T>&& r) noexcept : ptr_(r.release()) {} 96 97 template <typename U> scoped_refptr(scoped_refptr<U> && r)98 scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.release()) {} 99 ~scoped_refptr()100 ~scoped_refptr() { 101 if (ptr_) 102 ptr_->Release(); 103 } 104 get()105 T* get() const { return ptr_; } 106 operator T*() const { return ptr_; } 107 T* operator->() const { return ptr_; } 108 109 // Returns the (possibly null) raw pointer, and makes the scoped_refptr hold a 110 // null pointer, all without touching the reference count of the underlying 111 // pointed-to object. The object is still reference counted, and the caller of 112 // release() is now the proud owner of one reference, so it is responsible for 113 // calling Release() once on the object when no longer using it. release()114 T* release() { 115 T* retVal = ptr_; 116 ptr_ = nullptr; 117 return retVal; 118 } 119 120 scoped_refptr<T>& operator=(T* p) { 121 // AddRef first so that self assignment should work 122 if (p) 123 p->AddRef(); 124 if (ptr_) 125 ptr_->Release(); 126 ptr_ = p; 127 return *this; 128 } 129 130 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { 131 return *this = r.ptr_; 132 } 133 134 template <typename U> 135 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { 136 return *this = r.get(); 137 } 138 139 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) noexcept { 140 scoped_refptr<T>(std::move(r)).swap(*this); 141 return *this; 142 } 143 144 template <typename U> 145 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) noexcept { 146 scoped_refptr<T>(std::move(r)).swap(*this); 147 return *this; 148 } 149 swap(T ** pp)150 void swap(T** pp) noexcept { 151 T* p = ptr_; 152 ptr_ = *pp; 153 *pp = p; 154 } 155 swap(scoped_refptr<T> & r)156 void swap(scoped_refptr<T>& r) noexcept { swap(&r.ptr_); } 157 158 protected: 159 T* ptr_; 160 }; 161 162 } // namespace rtc 163 164 #endif // API_SCOPED_REFPTR_H_ 165