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/. */
7 #ifndef mozilla_RefPtr_h
8 #define mozilla_RefPtr_h
10 #include "mozilla/AlreadyAddRefed.h"
11 #include "mozilla/Assertions.h"
12 #include "mozilla/Attributes.h"
14 /*****************************************************************************/
16 // template <class T> class RefPtrGetterAddRefs;
18 class nsQueryReferent
;
19 class nsCOMPtr_helper
;
23 template<class T
> class OwningNonNull
;
24 template<class T
> class StaticRefPtr
;
26 // Traditionally, RefPtr supports automatic refcounting of any pointer type
27 // with AddRef() and Release() methods that follow the traditional semantics.
29 // This traits class can be specialized to operate on other pointer types. For
30 // example, we specialize this trait for opaque FFI types that represent
31 // refcounted objects in Rust.
33 // Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
38 static void AddRef(U
* aPtr
) {
41 static void Release(U
* aPtr
) {
46 } // namespace mozilla
49 class MOZ_IS_REFPTR RefPtr
53 assign_with_AddRef(T
* aRawPtr
)
56 ConstRemovingRefPtrTraits
<T
>::AddRef(aRawPtr
);
58 assign_assuming_AddRef(aRawPtr
);
62 assign_assuming_AddRef(T
* aNewPtr
)
67 ConstRemovingRefPtrTraits
<T
>::Release(oldPtr
);
72 T
* MOZ_OWNING_REF mRawPtr
;
75 typedef T element_type
;
80 ConstRemovingRefPtrTraits
<T
>::Release(mRawPtr
);
88 // default constructor
92 RefPtr(const RefPtr
<T
>& aSmartPtr
)
93 : mRawPtr(aSmartPtr
.mRawPtr
)
97 ConstRemovingRefPtrTraits
<T
>::AddRef(mRawPtr
);
101 RefPtr(RefPtr
<T
>&& aRefPtr
)
102 : mRawPtr(aRefPtr
.mRawPtr
)
104 aRefPtr
.mRawPtr
= nullptr;
107 // construct from a raw pointer (of the right type)
109 MOZ_IMPLICIT
RefPtr(T
* aRawPtr
)
113 ConstRemovingRefPtrTraits
<T
>::AddRef(mRawPtr
);
117 MOZ_IMPLICIT
RefPtr(decltype(nullptr))
122 template <typename I
>
123 MOZ_IMPLICIT
RefPtr(already_AddRefed
<I
>& aSmartPtr
)
124 : mRawPtr(aSmartPtr
.take())
125 // construct from |already_AddRefed|
129 template <typename I
>
130 MOZ_IMPLICIT
RefPtr(already_AddRefed
<I
>&& aSmartPtr
)
131 : mRawPtr(aSmartPtr
.take())
132 // construct from |otherRefPtr.forget()|
136 template <typename I
>
137 MOZ_IMPLICIT
RefPtr(const RefPtr
<I
>& aSmartPtr
)
138 : mRawPtr(aSmartPtr
.get())
139 // copy-construct from a smart pointer with a related pointer type
142 ConstRemovingRefPtrTraits
<T
>::AddRef(mRawPtr
);
146 template <typename I
>
147 MOZ_IMPLICIT
RefPtr(RefPtr
<I
>&& aSmartPtr
)
148 : mRawPtr(aSmartPtr
.forget().take())
149 // construct from |Move(RefPtr<SomeSubclassOfT>)|.
153 MOZ_IMPLICIT
RefPtr(const nsQueryReferent
& aHelper
);
154 MOZ_IMPLICIT
RefPtr(const nsCOMPtr_helper
& aHelper
);
156 // Defined in OwningNonNull.h
158 MOZ_IMPLICIT
RefPtr(const mozilla::OwningNonNull
<U
>& aOther
);
160 // Defined in StaticPtr.h
162 MOZ_IMPLICIT
RefPtr(const mozilla::StaticRefPtr
<U
>& aOther
);
164 // Assignment operators
167 operator=(decltype(nullptr))
169 assign_assuming_AddRef(nullptr);
174 operator=(const RefPtr
<T
>& aRhs
)
175 // copy assignment operator
177 assign_with_AddRef(aRhs
.mRawPtr
);
181 template <typename I
>
183 operator=(const RefPtr
<I
>& aRhs
)
184 // assign from an RefPtr of a related pointer type
186 assign_with_AddRef(aRhs
.get());
192 // assign from a raw pointer (of the right type)
194 assign_with_AddRef(aRhs
);
198 template <typename I
>
200 operator=(already_AddRefed
<I
>& aRhs
)
201 // assign from |already_AddRefed|
203 assign_assuming_AddRef(aRhs
.take());
207 template <typename I
>
209 operator=(already_AddRefed
<I
> && aRhs
)
210 // assign from |otherRefPtr.forget()|
212 assign_assuming_AddRef(aRhs
.take());
216 RefPtr
<T
>& operator=(const nsQueryReferent
& aQueryReferent
);
217 RefPtr
<T
>& operator=(const nsCOMPtr_helper
& aHelper
);
220 operator=(RefPtr
<T
> && aRefPtr
)
222 assign_assuming_AddRef(aRefPtr
.mRawPtr
);
223 aRefPtr
.mRawPtr
= nullptr;
227 // Defined in OwningNonNull.h
230 operator=(const mozilla::OwningNonNull
<U
>& aOther
);
232 // Defined in StaticPtr.h
235 operator=(const mozilla::StaticRefPtr
<U
>& aOther
);
237 // Other pointer operators
240 swap(RefPtr
<T
>& aRhs
)
241 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
243 T
* temp
= aRhs
.mRawPtr
;
244 aRhs
.mRawPtr
= mRawPtr
;
250 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
258 MOZ_MAY_CALL_AFTER_MUST_RETURN
260 // return the value of mRawPtr and null out mRawPtr. Useful for
261 // already_AddRefed return values.
265 return already_AddRefed
<T
>(temp
);
268 template <typename I
>
271 // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
272 // Useful to avoid unnecessary AddRef/Release pairs with "out"
273 // parameters where aRhs bay be a T** or an I** where I is a base class
276 MOZ_ASSERT(aRhs
, "Null pointer passed to forget!");
282 forget(nsISupports
** aRhs
)
284 MOZ_ASSERT(aRhs
, "Null pointer passed to forget!");
285 *aRhs
= ToSupports(mRawPtr
);
292 Prefer the implicit conversion provided automatically by |operator T*() const|.
293 Use |get()| to resolve ambiguity or to get a castable pointer.
296 return const_cast<T
*>(mRawPtr
);
299 operator T
*() const &
301 ...makes an |RefPtr| act like its underlying raw pointer type whenever it
302 is used in a context where a raw pointer is expected. It is this operator
303 that makes an |RefPtr| substitutable for a raw pointer.
305 Prefer the implicit use of this operator to calling |get()|, except where
306 necessary to resolve ambiguity.
312 // Don't allow implicit conversion of temporary RefPtr to raw pointer,
313 // because the refcount might be one and the pointer will immediately become
315 operator T
*() const && = delete;
317 // These are needed to avoid the deleted operator above. XXX Why is operator!
318 // needed separately? Shouldn't the compiler prefer using the non-deleted
319 // operator bool instead of the deleted operator T*?
320 explicit operator bool() const { return !!mRawPtr
; }
321 bool operator!() const { return !mRawPtr
; }
324 operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
326 MOZ_ASSERT(mRawPtr
!= nullptr,
327 "You can't dereference a NULL RefPtr with operator->().");
331 template <typename R
, typename
... Args
>
334 typedef R (T::*member_function
)(Args
...);
336 member_function mFunction
;
338 Proxy(T
* aRawPtr
, member_function aFunction
)
343 template<typename
... ActualArgs
>
344 R
operator()(ActualArgs
&&... aArgs
)
346 return ((*mRawPtr
).*mFunction
)(std::forward
<ActualArgs
>(aArgs
)...);
350 template <typename R
, typename
... Args
>
351 Proxy
<R
, Args
...> operator->*(R (T::*aFptr
)(Args
...)) const
353 MOZ_ASSERT(mRawPtr
!= nullptr,
354 "You can't dereference a NULL RefPtr with operator->*().");
355 return Proxy
<R
, Args
...>(get(), aFptr
);
360 // This is not intended to be used by clients. See |address_of|
368 // This is not intended to be used by clients. See |address_of|
378 MOZ_ASSERT(mRawPtr
!= nullptr,
379 "You can't dereference a NULL RefPtr with operator*().");
386 assign_assuming_AddRef(nullptr);
387 return reinterpret_cast<T
**>(&mRawPtr
);
390 // This helper class makes |RefPtr<const T>| possible by casting away
391 // the constness from the pointer when calling AddRef() and Release().
393 // This is necessary because AddRef() and Release() implementations can't
394 // generally expected to be const themselves (without heavy use of |mutable|
395 // and |const_cast| in their own implementations).
397 // This should be sound because while |RefPtr<const T>| provides a
398 // const view of an object, the object itself should not be const (it
399 // would have to be allocated as |new const T| or similar to be const).
401 struct ConstRemovingRefPtrTraits
403 static void AddRef(U
* aPtr
) {
404 mozilla::RefPtrTraits
<U
>::AddRef(aPtr
);
406 static void Release(U
* aPtr
) {
407 mozilla::RefPtrTraits
<U
>::Release(aPtr
);
411 struct ConstRemovingRefPtrTraits
<const U
>
413 static void AddRef(const U
* aPtr
) {
414 mozilla::RefPtrTraits
<U
>::AddRef(const_cast<U
*>(aPtr
));
416 static void Release(const U
* aPtr
) {
417 mozilla::RefPtrTraits
<U
>::Release(const_cast<U
*>(aPtr
));
422 class nsCycleCollectionTraversalCallback
;
423 template <typename T
>
425 CycleCollectionNoteChild(nsCycleCollectionTraversalCallback
& aCallback
,
426 T
* aChild
, const char* aName
, uint32_t aFlags
);
428 template <typename T
>
430 ImplCycleCollectionUnlink(RefPtr
<T
>& aField
)
435 template <typename T
>
437 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback
& aCallback
,
442 CycleCollectionNoteChild(aCallback
, aField
.get(), aName
, aFlags
);
447 address_of(RefPtr
<T
>& aPtr
)
449 return aPtr
.get_address();
453 inline const RefPtr
<T
>*
454 address_of(const RefPtr
<T
>& aPtr
)
456 return aPtr
.get_address();
460 class RefPtrGetterAddRefs
464 This class is designed to be used for anonymous temporary objects in the
465 argument list of calls that return COM interface pointers, e.g.,
468 ...->GetAddRefedPointer(getter_AddRefs(fooP))
470 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
472 When initialized with a |RefPtr|, as in the example above, it returns
473 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
474 outer call (|GetAddRefedPointer| in this case) can fill in.
476 This type should be a nested class inside |RefPtr<T>|.
481 RefPtrGetterAddRefs(RefPtr
<T
>& aSmartPtr
)
482 : mTargetSmartPtr(aSmartPtr
)
484 // nothing else to do
489 return reinterpret_cast<void**>(mTargetSmartPtr
.StartAssignment());
494 return mTargetSmartPtr
.StartAssignment();
500 return *(mTargetSmartPtr
.StartAssignment());
504 RefPtr
<T
>& mTargetSmartPtr
;
508 inline RefPtrGetterAddRefs
<T
>
509 getter_AddRefs(RefPtr
<T
>& aSmartPtr
)
511 Used around a |RefPtr| when
512 ...makes the class |RefPtrGetterAddRefs<T>| invisible.
515 return RefPtrGetterAddRefs
<T
>(aSmartPtr
);
519 // Comparing two |RefPtr|s
521 template <class T
, class U
>
523 operator==(const RefPtr
<T
>& aLhs
, const RefPtr
<U
>& aRhs
)
525 return static_cast<const T
*>(aLhs
.get()) == static_cast<const U
*>(aRhs
.get());
529 template <class T
, class U
>
531 operator!=(const RefPtr
<T
>& aLhs
, const RefPtr
<U
>& aRhs
)
533 return static_cast<const T
*>(aLhs
.get()) != static_cast<const U
*>(aRhs
.get());
537 // Comparing an |RefPtr| to a raw pointer
539 template <class T
, class U
>
541 operator==(const RefPtr
<T
>& aLhs
, const U
* aRhs
)
543 return static_cast<const T
*>(aLhs
.get()) == static_cast<const U
*>(aRhs
);
546 template <class T
, class U
>
548 operator==(const U
* aLhs
, const RefPtr
<T
>& aRhs
)
550 return static_cast<const U
*>(aLhs
) == static_cast<const T
*>(aRhs
.get());
553 template <class T
, class U
>
555 operator!=(const RefPtr
<T
>& aLhs
, const U
* aRhs
)
557 return static_cast<const T
*>(aLhs
.get()) != static_cast<const U
*>(aRhs
);
560 template <class T
, class U
>
562 operator!=(const U
* aLhs
, const RefPtr
<T
>& aRhs
)
564 return static_cast<const U
*>(aLhs
) != static_cast<const T
*>(aRhs
.get());
567 template <class T
, class U
>
569 operator==(const RefPtr
<T
>& aLhs
, U
* aRhs
)
571 return static_cast<const T
*>(aLhs
.get()) == const_cast<const U
*>(aRhs
);
574 template <class T
, class U
>
576 operator==(U
* aLhs
, const RefPtr
<T
>& aRhs
)
578 return const_cast<const U
*>(aLhs
) == static_cast<const T
*>(aRhs
.get());
581 template <class T
, class U
>
583 operator!=(const RefPtr
<T
>& aLhs
, U
* aRhs
)
585 return static_cast<const T
*>(aLhs
.get()) != const_cast<const U
*>(aRhs
);
588 template <class T
, class U
>
590 operator!=(U
* aLhs
, const RefPtr
<T
>& aRhs
)
592 return const_cast<const U
*>(aLhs
) != static_cast<const T
*>(aRhs
.get());
595 // Comparing an |RefPtr| to |nullptr|
599 operator==(const RefPtr
<T
>& aLhs
, decltype(nullptr))
601 return aLhs
.get() == nullptr;
606 operator==(decltype(nullptr), const RefPtr
<T
>& aRhs
)
608 return nullptr == aRhs
.get();
613 operator!=(const RefPtr
<T
>& aLhs
, decltype(nullptr))
615 return aLhs
.get() != nullptr;
620 operator!=(decltype(nullptr), const RefPtr
<T
>& aRhs
)
622 return nullptr != aRhs
.get();
625 /*****************************************************************************/
628 inline already_AddRefed
<T
>
636 inline already_AddRefed
<T
>
637 do_AddRef(const RefPtr
<T
>& aObj
)
646 * Helper function to be able to conveniently write things like:
648 * already_AddRefed<T>
651 * return MakeAndAddRef<T>(...);
654 template<typename T
, typename
... Args
>
656 MakeAndAddRef(Args
&&... aArgs
)
658 RefPtr
<T
> p(new T(std::forward
<Args
>(aArgs
)...));
663 * Helper function to be able to conveniently write things like:
665 * auto runnable = MakeRefPtr<ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>>(
666 * mOnSuccess, mOnFailure, *error, mWindowID);
668 template<typename T
, typename
... Args
>
670 MakeRefPtr(Args
&&... aArgs
)
672 RefPtr
<T
> p(new T(std::forward
<Args
>(aArgs
)...));
676 } // namespace mozilla
678 #endif /* mozilla_RefPtr_h */