• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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