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