RefPtr.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* vim: set ts=8 sts=2 et sw=2 tw=80: */
  3. /* This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. #ifndef mozilla_RefPtr_h
  7. #define mozilla_RefPtr_h
  8. #include "mozilla/AlreadyAddRefed.h"
  9. #include "mozilla/Assertions.h"
  10. #include "mozilla/Attributes.h"
  11. /*****************************************************************************/
  12. // template <class T> class RefPtrGetterAddRefs;
  13. class nsCOMPtr_helper;
  14. namespace mozilla {
  15. template<class T> class OwningNonNull;
  16. template<class T> class StaticRefPtr;
  17. // Traditionally, RefPtr supports automatic refcounting of any pointer type
  18. // with AddRef() and Release() methods that follow the traditional semantics.
  19. //
  20. // This traits class can be specialized to operate on other pointer types. For
  21. // example, we specialize this trait for opaque FFI types that represent
  22. // refcounted objects in Rust.
  23. //
  24. // Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
  25. // qualified type.
  26. template<class U>
  27. struct RefPtrTraits
  28. {
  29. static void AddRef(U* aPtr) {
  30. aPtr->AddRef();
  31. }
  32. static void Release(U* aPtr) {
  33. aPtr->Release();
  34. }
  35. };
  36. } // namespace mozilla
  37. template <class T>
  38. class RefPtr
  39. {
  40. private:
  41. void
  42. assign_with_AddRef(T* aRawPtr)
  43. {
  44. if (aRawPtr) {
  45. ConstRemovingRefPtrTraits<T>::AddRef(aRawPtr);
  46. }
  47. assign_assuming_AddRef(aRawPtr);
  48. }
  49. void
  50. assign_assuming_AddRef(T* aNewPtr)
  51. {
  52. T* oldPtr = mRawPtr;
  53. mRawPtr = aNewPtr;
  54. if (oldPtr) {
  55. ConstRemovingRefPtrTraits<T>::Release(oldPtr);
  56. }
  57. }
  58. private:
  59. T* MOZ_OWNING_REF mRawPtr;
  60. public:
  61. typedef T element_type;
  62. ~RefPtr()
  63. {
  64. if (mRawPtr) {
  65. ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
  66. }
  67. }
  68. // Constructors
  69. RefPtr()
  70. : mRawPtr(nullptr)
  71. // default constructor
  72. {
  73. }
  74. RefPtr(const RefPtr<T>& aSmartPtr)
  75. : mRawPtr(aSmartPtr.mRawPtr)
  76. // copy-constructor
  77. {
  78. if (mRawPtr) {
  79. ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
  80. }
  81. }
  82. RefPtr(RefPtr<T>&& aRefPtr)
  83. : mRawPtr(aRefPtr.mRawPtr)
  84. {
  85. aRefPtr.mRawPtr = nullptr;
  86. }
  87. // construct from a raw pointer (of the right type)
  88. MOZ_IMPLICIT RefPtr(T* aRawPtr)
  89. : mRawPtr(aRawPtr)
  90. {
  91. if (mRawPtr) {
  92. ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
  93. }
  94. }
  95. MOZ_IMPLICIT RefPtr(decltype(nullptr))
  96. : mRawPtr(nullptr)
  97. {
  98. }
  99. template <typename I>
  100. MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
  101. : mRawPtr(aSmartPtr.take())
  102. // construct from |already_AddRefed|
  103. {
  104. }
  105. template <typename I>
  106. MOZ_IMPLICIT RefPtr(already_AddRefed<I>&& aSmartPtr)
  107. : mRawPtr(aSmartPtr.take())
  108. // construct from |otherRefPtr.forget()|
  109. {
  110. }
  111. template <typename I>
  112. MOZ_IMPLICIT RefPtr(const RefPtr<I>& aSmartPtr)
  113. : mRawPtr(aSmartPtr.get())
  114. // copy-construct from a smart pointer with a related pointer type
  115. {
  116. if (mRawPtr) {
  117. ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
  118. }
  119. }
  120. template <typename I>
  121. MOZ_IMPLICIT RefPtr(RefPtr<I>&& aSmartPtr)
  122. : mRawPtr(aSmartPtr.forget().take())
  123. // construct from |Move(RefPtr<SomeSubclassOfT>)|.
  124. {
  125. }
  126. MOZ_IMPLICIT RefPtr(const nsCOMPtr_helper& aHelper);
  127. // Defined in OwningNonNull.h
  128. template<class U>
  129. MOZ_IMPLICIT RefPtr(const mozilla::OwningNonNull<U>& aOther);
  130. // Defined in StaticPtr.h
  131. template<class U>
  132. MOZ_IMPLICIT RefPtr(const mozilla::StaticRefPtr<U>& aOther);
  133. // Assignment operators
  134. RefPtr<T>&
  135. operator=(decltype(nullptr))
  136. {
  137. assign_assuming_AddRef(nullptr);
  138. return *this;
  139. }
  140. RefPtr<T>&
  141. operator=(const RefPtr<T>& aRhs)
  142. // copy assignment operator
  143. {
  144. assign_with_AddRef(aRhs.mRawPtr);
  145. return *this;
  146. }
  147. template <typename I>
  148. RefPtr<T>&
  149. operator=(const RefPtr<I>& aRhs)
  150. // assign from an RefPtr of a related pointer type
  151. {
  152. assign_with_AddRef(aRhs.get());
  153. return *this;
  154. }
  155. RefPtr<T>&
  156. operator=(T* aRhs)
  157. // assign from a raw pointer (of the right type)
  158. {
  159. assign_with_AddRef(aRhs);
  160. return *this;
  161. }
  162. template <typename I>
  163. RefPtr<T>&
  164. operator=(already_AddRefed<I>& aRhs)
  165. // assign from |already_AddRefed|
  166. {
  167. assign_assuming_AddRef(aRhs.take());
  168. return *this;
  169. }
  170. template <typename I>
  171. RefPtr<T>&
  172. operator=(already_AddRefed<I> && aRhs)
  173. // assign from |otherRefPtr.forget()|
  174. {
  175. assign_assuming_AddRef(aRhs.take());
  176. return *this;
  177. }
  178. RefPtr<T>& operator=(const nsCOMPtr_helper& aHelper);
  179. RefPtr<T>&
  180. operator=(RefPtr<T> && aRefPtr)
  181. {
  182. assign_assuming_AddRef(aRefPtr.mRawPtr);
  183. aRefPtr.mRawPtr = nullptr;
  184. return *this;
  185. }
  186. // Defined in OwningNonNull.h
  187. template<class U>
  188. RefPtr<T>&
  189. operator=(const mozilla::OwningNonNull<U>& aOther);
  190. // Defined in StaticPtr.h
  191. template<class U>
  192. RefPtr<T>&
  193. operator=(const mozilla::StaticRefPtr<U>& aOther);
  194. // Other pointer operators
  195. void
  196. swap(RefPtr<T>& aRhs)
  197. // ...exchange ownership with |aRhs|; can save a pair of refcount operations
  198. {
  199. T* temp = aRhs.mRawPtr;
  200. aRhs.mRawPtr = mRawPtr;
  201. mRawPtr = temp;
  202. }
  203. void
  204. swap(T*& aRhs)
  205. // ...exchange ownership with |aRhs|; can save a pair of refcount operations
  206. {
  207. T* temp = aRhs;
  208. aRhs = mRawPtr;
  209. mRawPtr = temp;
  210. }
  211. already_AddRefed<T>
  212. forget()
  213. // return the value of mRawPtr and null out mRawPtr. Useful for
  214. // already_AddRefed return values.
  215. {
  216. T* temp = nullptr;
  217. swap(temp);
  218. return already_AddRefed<T>(temp);
  219. }
  220. template <typename I>
  221. void
  222. forget(I** aRhs)
  223. // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
  224. // Useful to avoid unnecessary AddRef/Release pairs with "out"
  225. // parameters where aRhs bay be a T** or an I** where I is a base class
  226. // of T.
  227. {
  228. MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
  229. *aRhs = mRawPtr;
  230. mRawPtr = nullptr;
  231. }
  232. T*
  233. get() const
  234. /*
  235. Prefer the implicit conversion provided automatically by |operator T*() const|.
  236. Use |get()| to resolve ambiguity or to get a castable pointer.
  237. */
  238. {
  239. return const_cast<T*>(mRawPtr);
  240. }
  241. operator T*() const
  242. #ifdef MOZ_HAVE_REF_QUALIFIERS
  243. &
  244. #endif
  245. /*
  246. ...makes an |RefPtr| act like its underlying raw pointer type whenever it
  247. is used in a context where a raw pointer is expected. It is this operator
  248. that makes an |RefPtr| substitutable for a raw pointer.
  249. Prefer the implicit use of this operator to calling |get()|, except where
  250. necessary to resolve ambiguity.
  251. */
  252. {
  253. return get();
  254. }
  255. #ifdef MOZ_HAVE_REF_QUALIFIERS
  256. // Don't allow implicit conversion of temporary RefPtr to raw pointer,
  257. // because the refcount might be one and the pointer will immediately become
  258. // invalid.
  259. operator T*() const && = delete;
  260. // These are needed to avoid the deleted operator above. XXX Why is operator!
  261. // needed separately? Shouldn't the compiler prefer using the non-deleted
  262. // operator bool instead of the deleted operator T*?
  263. explicit operator bool() const { return !!mRawPtr; }
  264. bool operator!() const { return !mRawPtr; }
  265. #endif
  266. T*
  267. operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
  268. {
  269. MOZ_ASSERT(mRawPtr != nullptr,
  270. "You can't dereference a NULL RefPtr with operator->().");
  271. return get();
  272. }
  273. template <typename R, typename... Args>
  274. class Proxy
  275. {
  276. typedef R (T::*member_function)(Args...);
  277. T* mRawPtr;
  278. member_function mFunction;
  279. public:
  280. Proxy(T* aRawPtr, member_function aFunction)
  281. : mRawPtr(aRawPtr),
  282. mFunction(aFunction)
  283. {
  284. }
  285. template<typename... ActualArgs>
  286. R operator()(ActualArgs&&... aArgs)
  287. {
  288. return ((*mRawPtr).*mFunction)(mozilla::Forward<ActualArgs>(aArgs)...);
  289. }
  290. };
  291. template <typename R, typename... Args>
  292. Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const
  293. {
  294. MOZ_ASSERT(mRawPtr != nullptr,
  295. "You can't dereference a NULL RefPtr with operator->*().");
  296. return Proxy<R, Args...>(get(), aFptr);
  297. }
  298. RefPtr<T>*
  299. get_address()
  300. // This is not intended to be used by clients. See |address_of|
  301. // below.
  302. {
  303. return this;
  304. }
  305. const RefPtr<T>*
  306. get_address() const
  307. // This is not intended to be used by clients. See |address_of|
  308. // below.
  309. {
  310. return this;
  311. }
  312. public:
  313. T&
  314. operator*() const
  315. {
  316. MOZ_ASSERT(mRawPtr != nullptr,
  317. "You can't dereference a NULL RefPtr with operator*().");
  318. return *get();
  319. }
  320. T**
  321. StartAssignment()
  322. {
  323. assign_assuming_AddRef(nullptr);
  324. return reinterpret_cast<T**>(&mRawPtr);
  325. }
  326. private:
  327. // This helper class makes |RefPtr<const T>| possible by casting away
  328. // the constness from the pointer when calling AddRef() and Release().
  329. //
  330. // This is necessary because AddRef() and Release() implementations can't
  331. // generally expected to be const themselves (without heavy use of |mutable|
  332. // and |const_cast| in their own implementations).
  333. //
  334. // This should be sound because while |RefPtr<const T>| provides a
  335. // const view of an object, the object itself should not be const (it
  336. // would have to be allocated as |new const T| or similar to be const).
  337. template<class U>
  338. struct ConstRemovingRefPtrTraits
  339. {
  340. static void AddRef(U* aPtr) {
  341. mozilla::RefPtrTraits<U>::AddRef(aPtr);
  342. }
  343. static void Release(U* aPtr) {
  344. mozilla::RefPtrTraits<U>::Release(aPtr);
  345. }
  346. };
  347. template<class U>
  348. struct ConstRemovingRefPtrTraits<const U>
  349. {
  350. static void AddRef(const U* aPtr) {
  351. mozilla::RefPtrTraits<U>::AddRef(const_cast<U*>(aPtr));
  352. }
  353. static void Release(const U* aPtr) {
  354. mozilla::RefPtrTraits<U>::Release(const_cast<U*>(aPtr));
  355. }
  356. };
  357. };
  358. class nsCycleCollectionTraversalCallback;
  359. template <typename T>
  360. void
  361. CycleCollectionNoteChild(nsCycleCollectionTraversalCallback& aCallback,
  362. T* aChild, const char* aName, uint32_t aFlags);
  363. template <typename T>
  364. inline void
  365. ImplCycleCollectionUnlink(RefPtr<T>& aField)
  366. {
  367. aField = nullptr;
  368. }
  369. template <typename T>
  370. inline void
  371. ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
  372. RefPtr<T>& aField,
  373. const char* aName,
  374. uint32_t aFlags = 0)
  375. {
  376. CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
  377. }
  378. template <class T>
  379. inline RefPtr<T>*
  380. address_of(RefPtr<T>& aPtr)
  381. {
  382. return aPtr.get_address();
  383. }
  384. template <class T>
  385. inline const RefPtr<T>*
  386. address_of(const RefPtr<T>& aPtr)
  387. {
  388. return aPtr.get_address();
  389. }
  390. template <class T>
  391. class RefPtrGetterAddRefs
  392. /*
  393. ...
  394. This class is designed to be used for anonymous temporary objects in the
  395. argument list of calls that return COM interface pointers, e.g.,
  396. RefPtr<IFoo> fooP;
  397. ...->GetAddRefedPointer(getter_AddRefs(fooP))
  398. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
  399. When initialized with a |RefPtr|, as in the example above, it returns
  400. a |void**|, a |T**|, or an |nsISupports**| as needed, that the
  401. outer call (|GetAddRefedPointer| in this case) can fill in.
  402. This type should be a nested class inside |RefPtr<T>|.
  403. */
  404. {
  405. public:
  406. explicit
  407. RefPtrGetterAddRefs(RefPtr<T>& aSmartPtr)
  408. : mTargetSmartPtr(aSmartPtr)
  409. {
  410. // nothing else to do
  411. }
  412. operator void**()
  413. {
  414. return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
  415. }
  416. operator T**()
  417. {
  418. return mTargetSmartPtr.StartAssignment();
  419. }
  420. T*&
  421. operator*()
  422. {
  423. return *(mTargetSmartPtr.StartAssignment());
  424. }
  425. private:
  426. RefPtr<T>& mTargetSmartPtr;
  427. };
  428. template <class T>
  429. inline RefPtrGetterAddRefs<T>
  430. getter_AddRefs(RefPtr<T>& aSmartPtr)
  431. /*
  432. Used around a |RefPtr| when
  433. ...makes the class |RefPtrGetterAddRefs<T>| invisible.
  434. */
  435. {
  436. return RefPtrGetterAddRefs<T>(aSmartPtr);
  437. }
  438. // Comparing two |RefPtr|s
  439. template <class T, class U>
  440. inline bool
  441. operator==(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs)
  442. {
  443. return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
  444. }
  445. template <class T, class U>
  446. inline bool
  447. operator!=(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs)
  448. {
  449. return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
  450. }
  451. // Comparing an |RefPtr| to a raw pointer
  452. template <class T, class U>
  453. inline bool
  454. operator==(const RefPtr<T>& aLhs, const U* aRhs)
  455. {
  456. return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs);
  457. }
  458. template <class T, class U>
  459. inline bool
  460. operator==(const U* aLhs, const RefPtr<T>& aRhs)
  461. {
  462. return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
  463. }
  464. template <class T, class U>
  465. inline bool
  466. operator!=(const RefPtr<T>& aLhs, const U* aRhs)
  467. {
  468. return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs);
  469. }
  470. template <class T, class U>
  471. inline bool
  472. operator!=(const U* aLhs, const RefPtr<T>& aRhs)
  473. {
  474. return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
  475. }
  476. template <class T, class U>
  477. inline bool
  478. operator==(const RefPtr<T>& aLhs, U* aRhs)
  479. {
  480. return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
  481. }
  482. template <class T, class U>
  483. inline bool
  484. operator==(U* aLhs, const RefPtr<T>& aRhs)
  485. {
  486. return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
  487. }
  488. template <class T, class U>
  489. inline bool
  490. operator!=(const RefPtr<T>& aLhs, U* aRhs)
  491. {
  492. return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
  493. }
  494. template <class T, class U>
  495. inline bool
  496. operator!=(U* aLhs, const RefPtr<T>& aRhs)
  497. {
  498. return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
  499. }
  500. // Comparing an |RefPtr| to |nullptr|
  501. template <class T>
  502. inline bool
  503. operator==(const RefPtr<T>& aLhs, decltype(nullptr))
  504. {
  505. return aLhs.get() == nullptr;
  506. }
  507. template <class T>
  508. inline bool
  509. operator==(decltype(nullptr), const RefPtr<T>& aRhs)
  510. {
  511. return nullptr == aRhs.get();
  512. }
  513. template <class T>
  514. inline bool
  515. operator!=(const RefPtr<T>& aLhs, decltype(nullptr))
  516. {
  517. return aLhs.get() != nullptr;
  518. }
  519. template <class T>
  520. inline bool
  521. operator!=(decltype(nullptr), const RefPtr<T>& aRhs)
  522. {
  523. return nullptr != aRhs.get();
  524. }
  525. /*****************************************************************************/
  526. template <class T>
  527. inline already_AddRefed<T>
  528. do_AddRef(T* aObj)
  529. {
  530. RefPtr<T> ref(aObj);
  531. return ref.forget();
  532. }
  533. template <class T>
  534. inline already_AddRefed<T>
  535. do_AddRef(const RefPtr<T>& aObj)
  536. {
  537. RefPtr<T> ref(aObj);
  538. return ref.forget();
  539. }
  540. namespace mozilla {
  541. /**
  542. * Helper function to be able to conveniently write things like:
  543. *
  544. * already_AddRefed<T>
  545. * f(...)
  546. * {
  547. * return MakeAndAddRef<T>(...);
  548. * }
  549. */
  550. template<typename T, typename... Args>
  551. already_AddRefed<T>
  552. MakeAndAddRef(Args&&... aArgs)
  553. {
  554. RefPtr<T> p(new T(Forward<Args>(aArgs)...));
  555. return p.forget();
  556. }
  557. } // namespace mozilla
  558. #endif /* mozilla_RefPtr_h */