• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017 Marshall A. Greenblatt. Portions copyright (c) 2011
2 // Google Inc. All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //    * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //    * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //    * Neither the name of Google Inc. nor the name Chromium Embedded
15 // Framework nor the names of its contributors may be used to endorse
16 // or promote products derived from this software without specific prior
17 // written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #ifndef CEF_INCLUDE_BASE_CEF_SCOPED_REFPTR_H_
32 #define CEF_INCLUDE_BASE_CEF_SCOPED_REFPTR_H_
33 #pragma once
34 
35 #if defined(USING_CHROMIUM_INCLUDES)
36 // When building CEF include the Chromium header directly.
37 #include "base/memory/scoped_refptr.h"
38 #else  // !USING_CHROMIUM_INCLUDES
39 // The following is substantially similar to the Chromium implementation.
40 // If the Chromium implementation diverges the below implementation should be
41 // updated to match.
42 
43 #include <stddef.h>
44 
45 #include <iosfwd>
46 #include <type_traits>
47 #include <utility>
48 
49 #include "include/base/cef_compiler_specific.h"
50 #include "include/base/cef_logging.h"
51 
52 template <class T>
53 class scoped_refptr;
54 
55 namespace base {
56 
57 template <class, typename>
58 class RefCounted;
59 template <class, typename>
60 class RefCountedThreadSafe;
61 class SequencedTaskRunner;
62 class WrappedPromise;
63 
64 template <typename T>
65 scoped_refptr<T> AdoptRef(T* t);
66 
67 namespace internal {
68 
69 class BasePromise;
70 
71 }  // namespace internal
72 
73 namespace cef_subtle {
74 
75 enum AdoptRefTag { kAdoptRefTag };
76 enum StartRefCountFromZeroTag { kStartRefCountFromZeroTag };
77 enum StartRefCountFromOneTag { kStartRefCountFromOneTag };
78 
79 template <typename T, typename U, typename V>
IsRefCountPreferenceOverridden(const T *,const RefCounted<U,V> *)80 constexpr bool IsRefCountPreferenceOverridden(const T*,
81                                               const RefCounted<U, V>*) {
82   return !std::is_same<std::decay_t<decltype(T::kRefCountPreference)>,
83                        std::decay_t<decltype(U::kRefCountPreference)>>::value;
84 }
85 
86 template <typename T, typename U, typename V>
IsRefCountPreferenceOverridden(const T *,const RefCountedThreadSafe<U,V> *)87 constexpr bool IsRefCountPreferenceOverridden(
88     const T*,
89     const RefCountedThreadSafe<U, V>*) {
90   return !std::is_same<std::decay_t<decltype(T::kRefCountPreference)>,
91                        std::decay_t<decltype(U::kRefCountPreference)>>::value;
92 }
93 
IsRefCountPreferenceOverridden(...)94 constexpr bool IsRefCountPreferenceOverridden(...) {
95   return false;
96 }
97 
98 }  // namespace cef_subtle
99 
100 // Creates a scoped_refptr from a raw pointer without incrementing the reference
101 // count. Use this only for a newly created object whose reference count starts
102 // from 1 instead of 0.
103 template <typename T>
AdoptRef(T * obj)104 scoped_refptr<T> AdoptRef(T* obj) {
105   using Tag = std::decay_t<decltype(T::kRefCountPreference)>;
106   static_assert(std::is_same<cef_subtle::StartRefCountFromOneTag, Tag>::value,
107                 "Use AdoptRef only if the reference count starts from one.");
108 
109   DCHECK(obj);
110   DCHECK(obj->HasOneRef());
111   obj->Adopted();
112   return scoped_refptr<T>(obj, cef_subtle::kAdoptRefTag);
113 }
114 
115 namespace cef_subtle {
116 
117 template <typename T>
AdoptRefIfNeeded(T * obj,StartRefCountFromZeroTag)118 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) {
119   return scoped_refptr<T>(obj);
120 }
121 
122 template <typename T>
AdoptRefIfNeeded(T * obj,StartRefCountFromOneTag)123 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) {
124   return AdoptRef(obj);
125 }
126 
127 }  // namespace cef_subtle
128 
129 // Constructs an instance of T, which is a ref counted type, and wraps the
130 // object into a scoped_refptr<T>.
131 template <typename T, typename... Args>
MakeRefCounted(Args &&...args)132 scoped_refptr<T> MakeRefCounted(Args&&... args) {
133   T* obj = new T(std::forward<Args>(args)...);
134   return cef_subtle::AdoptRefIfNeeded(obj, T::kRefCountPreference);
135 }
136 
137 // Takes an instance of T, which is a ref counted type, and wraps the object
138 // into a scoped_refptr<T>.
139 template <typename T>
WrapRefCounted(T * t)140 scoped_refptr<T> WrapRefCounted(T* t) {
141   return scoped_refptr<T>(t);
142 }
143 
144 }  // namespace base
145 
146 //
147 // A smart pointer class for reference counted objects.  Use this class instead
148 // of calling AddRef and Release manually on a reference counted object to
149 // avoid common memory leaks caused by forgetting to Release an object
150 // reference.  Sample usage:
151 //
152 //   class MyFoo : public RefCounted<MyFoo> {
153 //    ...
154 //    private:
155 //     friend class RefCounted<MyFoo>;  // Allow destruction by RefCounted<>.
156 //     ~MyFoo();                        // Destructor must be private/protected.
157 //   };
158 //
159 //   void some_function() {
160 //     scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
161 //     foo->Method(param);
162 //     // |foo| is released when this function returns
163 //   }
164 //
165 //   void some_other_function() {
166 //     scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
167 //     ...
168 //     foo.reset();  // explicitly releases |foo|
169 //     ...
170 //     if (foo)
171 //       foo->Method(param);
172 //   }
173 //
174 // The above examples show how scoped_refptr<T> acts like a pointer to T.
175 // Given two scoped_refptr<T> classes, it is also possible to exchange
176 // references between the two objects, like so:
177 //
178 //   {
179 //     scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
180 //     scoped_refptr<MyFoo> b;
181 //
182 //     b.swap(a);
183 //     // now, |b| references the MyFoo object, and |a| references nullptr.
184 //   }
185 //
186 // To make both |a| and |b| in the above example reference the same MyFoo
187 // object, simply use the assignment operator:
188 //
189 //   {
190 //     scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
191 //     scoped_refptr<MyFoo> b;
192 //
193 //     b = a;
194 //     // now, |a| and |b| each own a reference to the same MyFoo object.
195 //   }
196 //
197 // Also see Chromium's ownership and calling conventions:
198 // https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++.md#object-ownership-and-calling-conventions
199 // Specifically:
200 //   If the function (at least sometimes) takes a ref on a refcounted object,
201 //   declare the param as scoped_refptr<T>. The caller can decide whether it
202 //   wishes to transfer ownership (by calling std::move(t) when passing t) or
203 //   retain its ref (by simply passing t directly).
204 //   In other words, use scoped_refptr like you would a std::unique_ptr except
205 //   in the odd case where it's required to hold on to a ref while handing one
206 //   to another component (if a component merely needs to use t on the stack
207 //   without keeping a ref: pass t as a raw T*).
208 template <class T>
209 class TRIVIAL_ABI scoped_refptr {
210  public:
211   typedef T element_type;
212 
213   constexpr scoped_refptr() = default;
214 
215   // Allow implicit construction from nullptr.
scoped_refptr(std::nullptr_t)216   constexpr scoped_refptr(std::nullptr_t) {}
217 
218   // Constructs from a raw pointer. Note that this constructor allows implicit
219   // conversion from T* to scoped_refptr<T> which is strongly discouraged. If
220   // you are creating a new ref-counted object please use
221   // base::MakeRefCounted<T>() or base::WrapRefCounted<T>(). Otherwise you
222   // should move or copy construct from an existing scoped_refptr<T> to the
223   // ref-counted object.
scoped_refptr(T * p)224   scoped_refptr(T* p) : ptr_(p) {
225     if (ptr_)
226       AddRef(ptr_);
227   }
228 
229   // Copy constructor. This is required in addition to the copy conversion
230   // constructor below.
scoped_refptr(const scoped_refptr & r)231   scoped_refptr(const scoped_refptr& r) : scoped_refptr(r.ptr_) {}
232 
233   // Copy conversion constructor.
234   template <typename U,
235             typename = typename std::enable_if<
236                 std::is_convertible<U*, T*>::value>::type>
scoped_refptr(const scoped_refptr<U> & r)237   scoped_refptr(const scoped_refptr<U>& r) : scoped_refptr(r.ptr_) {}
238 
239   // Move constructor. This is required in addition to the move conversion
240   // constructor below.
scoped_refptr(scoped_refptr && r)241   scoped_refptr(scoped_refptr&& r) noexcept : ptr_(r.ptr_) { r.ptr_ = nullptr; }
242 
243   // Move conversion constructor.
244   template <typename U,
245             typename = typename std::enable_if<
246                 std::is_convertible<U*, T*>::value>::type>
scoped_refptr(scoped_refptr<U> && r)247   scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.ptr_) {
248     r.ptr_ = nullptr;
249   }
250 
~scoped_refptr()251   ~scoped_refptr() {
252     static_assert(!base::cef_subtle::IsRefCountPreferenceOverridden(
253                       static_cast<T*>(nullptr), static_cast<T*>(nullptr)),
254                   "It's unsafe to override the ref count preference."
255                   " Please remove REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE"
256                   " from subclasses.");
257     if (ptr_)
258       Release(ptr_);
259   }
260 
get()261   T* get() const { return ptr_; }
262 
263   T& operator*() const {
264     DCHECK(ptr_);
265     return *ptr_;
266   }
267 
268   T* operator->() const {
269     DCHECK(ptr_);
270     return ptr_;
271   }
272 
273   scoped_refptr& operator=(std::nullptr_t) {
274     reset();
275     return *this;
276   }
277 
278   scoped_refptr& operator=(T* p) { return *this = scoped_refptr(p); }
279 
280   // Unified assignment operator.
281   scoped_refptr& operator=(scoped_refptr r) noexcept {
282     swap(r);
283     return *this;
284   }
285 
286   // Sets managed object to null and releases reference to the previous managed
287   // object, if it existed.
reset()288   void reset() { scoped_refptr().swap(*this); }
289 
290   // Returns the owned pointer (if any), releasing ownership to the caller. The
291   // caller is responsible for managing the lifetime of the reference.
292   T* release() WARN_UNUSED_RESULT;
293 
swap(scoped_refptr & r)294   void swap(scoped_refptr& r) noexcept { std::swap(ptr_, r.ptr_); }
295 
296   explicit operator bool() const { return ptr_ != nullptr; }
297 
298   template <typename U>
299   bool operator==(const scoped_refptr<U>& rhs) const {
300     return ptr_ == rhs.get();
301   }
302 
303   template <typename U>
304   bool operator!=(const scoped_refptr<U>& rhs) const {
305     return !operator==(rhs);
306   }
307 
308   template <typename U>
309   bool operator<(const scoped_refptr<U>& rhs) const {
310     return ptr_ < rhs.get();
311   }
312 
313  protected:
314   T* ptr_ = nullptr;
315 
316  private:
317   template <typename U>
318   friend scoped_refptr<U> base::AdoptRef(U*);
319   friend class ::base::SequencedTaskRunner;
320 
321   // Friend access so these classes can use the constructor below as part of a
322   // binary size optimization.
323   friend class ::base::internal::BasePromise;
324   friend class ::base::WrappedPromise;
325 
scoped_refptr(T * p,base::cef_subtle::AdoptRefTag)326   scoped_refptr(T* p, base::cef_subtle::AdoptRefTag) : ptr_(p) {}
327 
328   // Friend required for move constructors that set r.ptr_ to null.
329   template <typename U>
330   friend class scoped_refptr;
331 
332   // Non-inline helpers to allow:
333   //     class Opaque;
334   //     extern template class scoped_refptr<Opaque>;
335   // Otherwise the compiler will complain that Opaque is an incomplete type.
336   static void AddRef(T* ptr);
337   static void Release(T* ptr);
338 };
339 
340 template <typename T>
release()341 T* scoped_refptr<T>::release() {
342   T* ptr = ptr_;
343   ptr_ = nullptr;
344   return ptr;
345 }
346 
347 // static
348 template <typename T>
AddRef(T * ptr)349 void scoped_refptr<T>::AddRef(T* ptr) {
350   ptr->AddRef();
351 }
352 
353 // static
354 template <typename T>
Release(T * ptr)355 void scoped_refptr<T>::Release(T* ptr) {
356   ptr->Release();
357 }
358 
359 template <typename T, typename U>
360 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
361   return lhs.get() == rhs;
362 }
363 
364 template <typename T, typename U>
365 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
366   return lhs == rhs.get();
367 }
368 
369 template <typename T>
370 bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t null) {
371   return !static_cast<bool>(lhs);
372 }
373 
374 template <typename T>
375 bool operator==(std::nullptr_t null, const scoped_refptr<T>& rhs) {
376   return !static_cast<bool>(rhs);
377 }
378 
379 template <typename T, typename U>
380 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
381   return !operator==(lhs, rhs);
382 }
383 
384 template <typename T, typename U>
385 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
386   return !operator==(lhs, rhs);
387 }
388 
389 template <typename T>
390 bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) {
391   return !operator==(lhs, null);
392 }
393 
394 template <typename T>
395 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) {
396   return !operator==(null, rhs);
397 }
398 
399 template <typename T>
400 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
401   return out << p.get();
402 }
403 
404 template <typename T>
swap(scoped_refptr<T> & lhs,scoped_refptr<T> & rhs)405 void swap(scoped_refptr<T>& lhs, scoped_refptr<T>& rhs) noexcept {
406   lhs.swap(rhs);
407 }
408 
409 #endif  // !USING_CHROMIUM_INCLUDES
410 
411 #endif  // CEF_INCLUDE_BASE_CEF_SCOPED_REFPTR_H_
412