xref: /aosp_15_r20/external/webrtc/api/scoped_refptr.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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