scoped_refptr.h 12 KB

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