scoped_refptr.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_MEMORY_SCOPED_REFPTR_H_
  5. #define BASE_MEMORY_SCOPED_REFPTR_H_
  6. #include <stddef.h>
  7. #include <iosfwd>
  8. #include <type_traits>
  9. #include <utility>
  10. #include "base/check.h"
  11. #include "base/compiler_specific.h"
  12. #include "base/macros.h"
  13. template <class T>
  14. class scoped_refptr;
  15. namespace base {
  16. template <class, typename>
  17. class RefCounted;
  18. template <class, typename>
  19. class RefCountedThreadSafe;
  20. class SequencedTaskRunner;
  21. class WrappedPromise;
  22. template <typename T>
  23. scoped_refptr<T> AdoptRef(T* t);
  24. namespace internal {
  25. class BasePromise;
  26. } // namespace internal
  27. namespace subtle {
  28. enum AdoptRefTag { kAdoptRefTag };
  29. enum StartRefCountFromZeroTag { kStartRefCountFromZeroTag };
  30. enum StartRefCountFromOneTag { kStartRefCountFromOneTag };
  31. template <typename T, typename U, typename V>
  32. constexpr bool IsRefCountPreferenceOverridden(const T*,
  33. const RefCounted<U, V>*) {
  34. return !std::is_same<std::decay_t<decltype(T::kRefCountPreference)>,
  35. std::decay_t<decltype(U::kRefCountPreference)>>::value;
  36. }
  37. template <typename T, typename U, typename V>
  38. constexpr bool IsRefCountPreferenceOverridden(
  39. const T*,
  40. const RefCountedThreadSafe<U, V>*) {
  41. return !std::is_same<std::decay_t<decltype(T::kRefCountPreference)>,
  42. std::decay_t<decltype(U::kRefCountPreference)>>::value;
  43. }
  44. constexpr bool IsRefCountPreferenceOverridden(...) {
  45. return false;
  46. }
  47. } // namespace subtle
  48. // Creates a scoped_refptr from a raw pointer without incrementing the reference
  49. // count. Use this only for a newly created object whose reference count starts
  50. // from 1 instead of 0.
  51. template <typename T>
  52. scoped_refptr<T> AdoptRef(T* obj) {
  53. using Tag = std::decay_t<decltype(T::kRefCountPreference)>;
  54. static_assert(std::is_same<subtle::StartRefCountFromOneTag, Tag>::value,
  55. "Use AdoptRef only if the reference count starts from one.");
  56. DCHECK(obj);
  57. DCHECK(obj->HasOneRef());
  58. obj->Adopted();
  59. return scoped_refptr<T>(obj, subtle::kAdoptRefTag);
  60. }
  61. namespace subtle {
  62. template <typename T>
  63. scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) {
  64. return scoped_refptr<T>(obj);
  65. }
  66. template <typename T>
  67. scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) {
  68. return AdoptRef(obj);
  69. }
  70. } // namespace subtle
  71. // Constructs an instance of T, which is a ref counted type, and wraps the
  72. // object into a scoped_refptr<T>.
  73. template <typename T, typename... Args>
  74. scoped_refptr<T> MakeRefCounted(Args&&... args) {
  75. T* obj = new T(std::forward<Args>(args)...);
  76. return subtle::AdoptRefIfNeeded(obj, T::kRefCountPreference);
  77. }
  78. // Takes an instance of T, which is a ref counted type, and wraps the object
  79. // into a scoped_refptr<T>.
  80. template <typename T>
  81. scoped_refptr<T> WrapRefCounted(T* t) {
  82. return scoped_refptr<T>(t);
  83. }
  84. } // namespace base
  85. //
  86. // A smart pointer class for reference counted objects. Use this class instead
  87. // of calling AddRef and Release manually on a reference counted object to
  88. // avoid common memory leaks caused by forgetting to Release an object
  89. // reference. Sample usage:
  90. //
  91. // class MyFoo : public RefCounted<MyFoo> {
  92. // ...
  93. // private:
  94. // friend class RefCounted<MyFoo>; // Allow destruction by RefCounted<>.
  95. // ~MyFoo(); // Destructor must be private/protected.
  96. // };
  97. //
  98. // void some_function() {
  99. // scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
  100. // foo->Method(param);
  101. // // |foo| is released when this function returns
  102. // }
  103. //
  104. // void some_other_function() {
  105. // scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
  106. // ...
  107. // foo.reset(); // explicitly releases |foo|
  108. // ...
  109. // if (foo)
  110. // foo->Method(param);
  111. // }
  112. //
  113. // The above examples show how scoped_refptr<T> acts like a pointer to T.
  114. // Given two scoped_refptr<T> classes, it is also possible to exchange
  115. // references between the two objects, like so:
  116. //
  117. // {
  118. // scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
  119. // scoped_refptr<MyFoo> b;
  120. //
  121. // b.swap(a);
  122. // // now, |b| references the MyFoo object, and |a| references nullptr.
  123. // }
  124. //
  125. // To make both |a| and |b| in the above example reference the same MyFoo
  126. // object, simply use the assignment operator:
  127. //
  128. // {
  129. // scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
  130. // scoped_refptr<MyFoo> b;
  131. //
  132. // b = a;
  133. // // now, |a| and |b| each own a reference to the same MyFoo object.
  134. // }
  135. //
  136. // Also see Chromium's ownership and calling conventions:
  137. // https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++.md#object-ownership-and-calling-conventions
  138. // Specifically:
  139. // If the function (at least sometimes) takes a ref on a refcounted object,
  140. // declare the param as scoped_refptr<T>. The caller can decide whether it
  141. // wishes to transfer ownership (by calling std::move(t) when passing t) or
  142. // retain its ref (by simply passing t directly).
  143. // In other words, use scoped_refptr like you would a std::unique_ptr except
  144. // in the odd case where it's required to hold on to a ref while handing one
  145. // to another component (if a component merely needs to use t on the stack
  146. // without keeping a ref: pass t as a raw T*).
  147. template <class T>
  148. class scoped_refptr {
  149. public:
  150. typedef T element_type;
  151. constexpr scoped_refptr() = default;
  152. // Allow implicit construction from nullptr.
  153. constexpr scoped_refptr(std::nullptr_t) {}
  154. // Constructs from a raw pointer. Note that this constructor allows implicit
  155. // conversion from T* to scoped_refptr<T> which is strongly discouraged. If
  156. // you are creating a new ref-counted object please use
  157. // base::MakeRefCounted<T>() or base::WrapRefCounted<T>(). Otherwise you
  158. // should move or copy construct from an existing scoped_refptr<T> to the
  159. // ref-counted object.
  160. scoped_refptr(T* p) : ptr_(p) {
  161. if (ptr_)
  162. AddRef(ptr_);
  163. }
  164. // Copy constructor. This is required in addition to the copy conversion
  165. // constructor below.
  166. scoped_refptr(const scoped_refptr& r) : scoped_refptr(r.ptr_) {}
  167. // Copy conversion constructor.
  168. template <typename U,
  169. typename = typename std::enable_if<
  170. std::is_convertible<U*, T*>::value>::type>
  171. scoped_refptr(const scoped_refptr<U>& r) : scoped_refptr(r.ptr_) {}
  172. // Move constructor. This is required in addition to the move conversion
  173. // constructor below.
  174. scoped_refptr(scoped_refptr&& r) noexcept : ptr_(r.ptr_) { r.ptr_ = nullptr; }
  175. // Move conversion constructor.
  176. template <typename U,
  177. typename = typename std::enable_if<
  178. std::is_convertible<U*, T*>::value>::type>
  179. scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.ptr_) {
  180. r.ptr_ = nullptr;
  181. }
  182. ~scoped_refptr() {
  183. static_assert(!base::subtle::IsRefCountPreferenceOverridden(
  184. static_cast<T*>(nullptr), static_cast<T*>(nullptr)),
  185. "It's unsafe to override the ref count preference."
  186. " Please remove REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE"
  187. " from subclasses.");
  188. if (ptr_)
  189. Release(ptr_);
  190. }
  191. T* get() const { return ptr_; }
  192. T& operator*() const {
  193. DCHECK(ptr_);
  194. return *ptr_;
  195. }
  196. T* operator->() const {
  197. DCHECK(ptr_);
  198. return ptr_;
  199. }
  200. scoped_refptr& operator=(std::nullptr_t) {
  201. reset();
  202. return *this;
  203. }
  204. scoped_refptr& operator=(T* p) { return *this = scoped_refptr(p); }
  205. // Unified assignment operator.
  206. scoped_refptr& operator=(scoped_refptr r) noexcept {
  207. swap(r);
  208. return *this;
  209. }
  210. // Sets managed object to null and releases reference to the previous managed
  211. // object, if it existed.
  212. void reset() { scoped_refptr().swap(*this); }
  213. // Returns the owned pointer (if any), releasing ownership to the caller. The
  214. // caller is responsible for managing the lifetime of the reference.
  215. T* release() WARN_UNUSED_RESULT;
  216. void swap(scoped_refptr& r) noexcept { std::swap(ptr_, r.ptr_); }
  217. explicit operator bool() const { return ptr_ != nullptr; }
  218. template <typename U>
  219. bool operator==(const scoped_refptr<U>& rhs) const {
  220. return ptr_ == rhs.get();
  221. }
  222. template <typename U>
  223. bool operator!=(const scoped_refptr<U>& rhs) const {
  224. return !operator==(rhs);
  225. }
  226. template <typename U>
  227. bool operator<(const scoped_refptr<U>& rhs) const {
  228. return ptr_ < rhs.get();
  229. }
  230. protected:
  231. T* ptr_ = nullptr;
  232. private:
  233. template <typename U>
  234. friend scoped_refptr<U> base::AdoptRef(U*);
  235. friend class ::base::SequencedTaskRunner;
  236. // Friend access so these classes can use the constructor below as part of a
  237. // binary size optimization.
  238. friend class ::base::internal::BasePromise;
  239. friend class ::base::WrappedPromise;
  240. scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {}
  241. // Friend required for move constructors that set r.ptr_ to null.
  242. template <typename U>
  243. friend class scoped_refptr;
  244. // Non-inline helpers to allow:
  245. // class Opaque;
  246. // extern template class scoped_refptr<Opaque>;
  247. // Otherwise the compiler will complain that Opaque is an incomplete type.
  248. static void AddRef(T* ptr);
  249. static void Release(T* ptr);
  250. };
  251. template <typename T>
  252. T* scoped_refptr<T>::release() {
  253. T* ptr = ptr_;
  254. ptr_ = nullptr;
  255. return ptr;
  256. }
  257. // static
  258. template <typename T>
  259. void scoped_refptr<T>::AddRef(T* ptr) {
  260. ptr->AddRef();
  261. }
  262. // static
  263. template <typename T>
  264. void scoped_refptr<T>::Release(T* ptr) {
  265. ptr->Release();
  266. }
  267. template <typename T, typename U>
  268. bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
  269. return lhs.get() == rhs;
  270. }
  271. template <typename T, typename U>
  272. bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
  273. return lhs == rhs.get();
  274. }
  275. template <typename T>
  276. bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t null) {
  277. return !static_cast<bool>(lhs);
  278. }
  279. template <typename T>
  280. bool operator==(std::nullptr_t null, const scoped_refptr<T>& rhs) {
  281. return !static_cast<bool>(rhs);
  282. }
  283. template <typename T, typename U>
  284. bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
  285. return !operator==(lhs, rhs);
  286. }
  287. template <typename T, typename U>
  288. bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
  289. return !operator==(lhs, rhs);
  290. }
  291. template <typename T>
  292. bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) {
  293. return !operator==(lhs, null);
  294. }
  295. template <typename T>
  296. bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) {
  297. return !operator==(null, rhs);
  298. }
  299. template <typename T>
  300. std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
  301. return out << p.get();
  302. }
  303. template <typename T>
  304. void swap(scoped_refptr<T>& lhs, scoped_refptr<T>& rhs) noexcept {
  305. lhs.swap(rhs);
  306. }
  307. #endif // BASE_MEMORY_SCOPED_REFPTR_H_