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
;
29 #endif // defined(XP_WIN)
31 // Traditionally, RefPtr supports automatic refcounting of any pointer type
32 // with AddRef() and Release() methods that follow the traditional semantics.
34 // This traits class can be specialized to operate on other pointer types. For
35 // example, we specialize this trait for opaque FFI types that represent
36 // refcounted objects in Rust.
38 // Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
43 static void AddRef(U
* aPtr
) {
46 static void Release(U
* aPtr
) {
51 } // namespace mozilla
54 class MOZ_IS_REFPTR RefPtr
58 assign_with_AddRef(T
* aRawPtr
)
61 ConstRemovingRefPtrTraits
<T
>::AddRef(aRawPtr
);
63 assign_assuming_AddRef(aRawPtr
);
67 assign_assuming_AddRef(T
* aNewPtr
)
72 ConstRemovingRefPtrTraits
<T
>::Release(oldPtr
);
77 T
* MOZ_OWNING_REF mRawPtr
;
80 typedef T element_type
;
85 ConstRemovingRefPtrTraits
<T
>::Release(mRawPtr
);
93 // default constructor
97 RefPtr(const RefPtr
<T
>& aSmartPtr
)
98 : mRawPtr(aSmartPtr
.mRawPtr
)
102 ConstRemovingRefPtrTraits
<T
>::AddRef(mRawPtr
);
106 RefPtr(RefPtr
<T
>&& aRefPtr
)
107 : mRawPtr(aRefPtr
.mRawPtr
)
109 aRefPtr
.mRawPtr
= nullptr;
112 // construct from a raw pointer (of the right type)
114 MOZ_IMPLICIT
RefPtr(T
* aRawPtr
)
118 ConstRemovingRefPtrTraits
<T
>::AddRef(mRawPtr
);
122 MOZ_IMPLICIT
RefPtr(decltype(nullptr))
127 template <typename I
>
128 MOZ_IMPLICIT
RefPtr(already_AddRefed
<I
>& aSmartPtr
)
129 : mRawPtr(aSmartPtr
.take())
130 // construct from |already_AddRefed|
134 template <typename I
>
135 MOZ_IMPLICIT
RefPtr(already_AddRefed
<I
>&& aSmartPtr
)
136 : mRawPtr(aSmartPtr
.take())
137 // construct from |otherRefPtr.forget()|
141 template <typename I
>
142 MOZ_IMPLICIT
RefPtr(const RefPtr
<I
>& aSmartPtr
)
143 : mRawPtr(aSmartPtr
.get())
144 // copy-construct from a smart pointer with a related pointer type
147 ConstRemovingRefPtrTraits
<T
>::AddRef(mRawPtr
);
151 template <typename I
>
152 MOZ_IMPLICIT
RefPtr(RefPtr
<I
>&& aSmartPtr
)
153 : mRawPtr(aSmartPtr
.forget().take())
154 // construct from |Move(RefPtr<SomeSubclassOfT>)|.
158 MOZ_IMPLICIT
RefPtr(const nsQueryReferent
& aHelper
);
159 MOZ_IMPLICIT
RefPtr(const nsCOMPtr_helper
& aHelper
);
161 MOZ_IMPLICIT
RefPtr(const mozilla::mscom::AgileReference
& aAgileRef
);
162 #endif // defined(XP_WIN)
164 // Defined in OwningNonNull.h
166 MOZ_IMPLICIT
RefPtr(const mozilla::OwningNonNull
<U
>& aOther
);
168 // Defined in StaticPtr.h
170 MOZ_IMPLICIT
RefPtr(const mozilla::StaticRefPtr
<U
>& aOther
);
172 // Assignment operators
175 operator=(decltype(nullptr))
177 assign_assuming_AddRef(nullptr);
182 operator=(const RefPtr
<T
>& aRhs
)
183 // copy assignment operator
185 assign_with_AddRef(aRhs
.mRawPtr
);
189 template <typename I
>
191 operator=(const RefPtr
<I
>& aRhs
)
192 // assign from an RefPtr of a related pointer type
194 assign_with_AddRef(aRhs
.get());
200 // assign from a raw pointer (of the right type)
202 assign_with_AddRef(aRhs
);
206 template <typename I
>
208 operator=(already_AddRefed
<I
>& aRhs
)
209 // assign from |already_AddRefed|
211 assign_assuming_AddRef(aRhs
.take());
215 template <typename I
>
217 operator=(already_AddRefed
<I
> && aRhs
)
218 // assign from |otherRefPtr.forget()|
220 assign_assuming_AddRef(aRhs
.take());
224 RefPtr
<T
>& operator=(const nsQueryReferent
& aQueryReferent
);
225 RefPtr
<T
>& operator=(const nsCOMPtr_helper
& aHelper
);
227 RefPtr
<T
>& operator=(const mozilla::mscom::AgileReference
& aAgileRef
);
228 #endif // defined(XP_WIN)
231 operator=(RefPtr
<T
> && aRefPtr
)
233 assign_assuming_AddRef(aRefPtr
.mRawPtr
);
234 aRefPtr
.mRawPtr
= nullptr;
238 // Defined in OwningNonNull.h
241 operator=(const mozilla::OwningNonNull
<U
>& aOther
);
243 // Defined in StaticPtr.h
246 operator=(const mozilla::StaticRefPtr
<U
>& aOther
);
248 // Other pointer operators
251 swap(RefPtr
<T
>& aRhs
)
252 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
254 T
* temp
= aRhs
.mRawPtr
;
255 aRhs
.mRawPtr
= mRawPtr
;
261 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
269 MOZ_MAY_CALL_AFTER_MUST_RETURN
271 // return the value of mRawPtr and null out mRawPtr. Useful for
272 // already_AddRefed return values.
276 return already_AddRefed
<T
>(temp
);
279 template <typename I
>
282 // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
283 // Useful to avoid unnecessary AddRef/Release pairs with "out"
284 // parameters where aRhs bay be a T** or an I** where I is a base class
287 MOZ_ASSERT(aRhs
, "Null pointer passed to forget!");
293 forget(nsISupports
** aRhs
)
295 MOZ_ASSERT(aRhs
, "Null pointer passed to forget!");
296 *aRhs
= ToSupports(mRawPtr
);
303 Prefer the implicit conversion provided automatically by |operator T*() const|.
304 Use |get()| to resolve ambiguity or to get a castable pointer.
307 return const_cast<T
*>(mRawPtr
);
310 operator T
*() const &
312 ...makes an |RefPtr| act like its underlying raw pointer type whenever it
313 is used in a context where a raw pointer is expected. It is this operator
314 that makes an |RefPtr| substitutable for a raw pointer.
316 Prefer the implicit use of this operator to calling |get()|, except where
317 necessary to resolve ambiguity.
323 // Don't allow implicit conversion of temporary RefPtr to raw pointer,
324 // because the refcount might be one and the pointer will immediately become
326 operator T
*() const && = delete;
328 // These are needed to avoid the deleted operator above. XXX Why is operator!
329 // needed separately? Shouldn't the compiler prefer using the non-deleted
330 // operator bool instead of the deleted operator T*?
331 explicit operator bool() const { return !!mRawPtr
; }
332 bool operator!() const { return !mRawPtr
; }
335 operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
337 MOZ_ASSERT(mRawPtr
!= nullptr,
338 "You can't dereference a NULL RefPtr with operator->().");
342 template <typename R
, typename
... Args
>
345 typedef R (T::*member_function
)(Args
...);
347 member_function mFunction
;
349 Proxy(T
* aRawPtr
, member_function aFunction
)
354 template<typename
... ActualArgs
>
355 R
operator()(ActualArgs
&&... aArgs
)
357 return ((*mRawPtr
).*mFunction
)(std::forward
<ActualArgs
>(aArgs
)...);
361 template <typename R
, typename
... Args
>
362 Proxy
<R
, Args
...> operator->*(R (T::*aFptr
)(Args
...)) const
364 MOZ_ASSERT(mRawPtr
!= nullptr,
365 "You can't dereference a NULL RefPtr with operator->*().");
366 return Proxy
<R
, Args
...>(get(), aFptr
);
371 // This is not intended to be used by clients. See |address_of|
379 // This is not intended to be used by clients. See |address_of|
389 MOZ_ASSERT(mRawPtr
!= nullptr,
390 "You can't dereference a NULL RefPtr with operator*().");
397 assign_assuming_AddRef(nullptr);
398 return reinterpret_cast<T
**>(&mRawPtr
);
401 // This helper class makes |RefPtr<const T>| possible by casting away
402 // the constness from the pointer when calling AddRef() and Release().
404 // This is necessary because AddRef() and Release() implementations can't
405 // generally expected to be const themselves (without heavy use of |mutable|
406 // and |const_cast| in their own implementations).
408 // This should be sound because while |RefPtr<const T>| provides a
409 // const view of an object, the object itself should not be const (it
410 // would have to be allocated as |new const T| or similar to be const).
412 struct ConstRemovingRefPtrTraits
414 static void AddRef(U
* aPtr
) {
415 mozilla::RefPtrTraits
<U
>::AddRef(aPtr
);
417 static void Release(U
* aPtr
) {
418 mozilla::RefPtrTraits
<U
>::Release(aPtr
);
422 struct ConstRemovingRefPtrTraits
<const U
>
424 static void AddRef(const U
* aPtr
) {
425 mozilla::RefPtrTraits
<U
>::AddRef(const_cast<U
*>(aPtr
));
427 static void Release(const U
* aPtr
) {
428 mozilla::RefPtrTraits
<U
>::Release(const_cast<U
*>(aPtr
));
433 class nsCycleCollectionTraversalCallback
;
434 template <typename T
>
436 CycleCollectionNoteChild(nsCycleCollectionTraversalCallback
& aCallback
,
437 T
* aChild
, const char* aName
, uint32_t aFlags
);
439 template <typename T
>
441 ImplCycleCollectionUnlink(RefPtr
<T
>& aField
)
446 template <typename T
>
448 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback
& aCallback
,
453 CycleCollectionNoteChild(aCallback
, aField
.get(), aName
, aFlags
);
458 address_of(RefPtr
<T
>& aPtr
)
460 return aPtr
.get_address();
464 inline const RefPtr
<T
>*
465 address_of(const RefPtr
<T
>& aPtr
)
467 return aPtr
.get_address();
471 class RefPtrGetterAddRefs
475 This class is designed to be used for anonymous temporary objects in the
476 argument list of calls that return COM interface pointers, e.g.,
479 ...->GetAddRefedPointer(getter_AddRefs(fooP))
481 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
483 When initialized with a |RefPtr|, as in the example above, it returns
484 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
485 outer call (|GetAddRefedPointer| in this case) can fill in.
487 This type should be a nested class inside |RefPtr<T>|.
492 RefPtrGetterAddRefs(RefPtr
<T
>& aSmartPtr
)
493 : mTargetSmartPtr(aSmartPtr
)
495 // nothing else to do
500 return reinterpret_cast<void**>(mTargetSmartPtr
.StartAssignment());
505 return mTargetSmartPtr
.StartAssignment();
511 return *(mTargetSmartPtr
.StartAssignment());
515 RefPtr
<T
>& mTargetSmartPtr
;
519 inline RefPtrGetterAddRefs
<T
>
520 getter_AddRefs(RefPtr
<T
>& aSmartPtr
)
522 Used around a |RefPtr| when
523 ...makes the class |RefPtrGetterAddRefs<T>| invisible.
526 return RefPtrGetterAddRefs
<T
>(aSmartPtr
);
530 // Comparing two |RefPtr|s
532 template <class T
, class U
>
534 operator==(const RefPtr
<T
>& aLhs
, const RefPtr
<U
>& aRhs
)
536 return static_cast<const T
*>(aLhs
.get()) == static_cast<const U
*>(aRhs
.get());
540 template <class T
, class U
>
542 operator!=(const RefPtr
<T
>& aLhs
, const RefPtr
<U
>& aRhs
)
544 return static_cast<const T
*>(aLhs
.get()) != static_cast<const U
*>(aRhs
.get());
548 // Comparing an |RefPtr| to a raw pointer
550 template <class T
, class U
>
552 operator==(const RefPtr
<T
>& aLhs
, const U
* aRhs
)
554 return static_cast<const T
*>(aLhs
.get()) == static_cast<const U
*>(aRhs
);
557 template <class T
, class U
>
559 operator==(const U
* aLhs
, const RefPtr
<T
>& aRhs
)
561 return static_cast<const U
*>(aLhs
) == static_cast<const T
*>(aRhs
.get());
564 template <class T
, class U
>
566 operator!=(const RefPtr
<T
>& aLhs
, const U
* aRhs
)
568 return static_cast<const T
*>(aLhs
.get()) != static_cast<const U
*>(aRhs
);
571 template <class T
, class U
>
573 operator!=(const U
* aLhs
, const RefPtr
<T
>& aRhs
)
575 return static_cast<const U
*>(aLhs
) != static_cast<const T
*>(aRhs
.get());
578 template <class T
, class U
>
580 operator==(const RefPtr
<T
>& aLhs
, U
* aRhs
)
582 return static_cast<const T
*>(aLhs
.get()) == const_cast<const U
*>(aRhs
);
585 template <class T
, class U
>
587 operator==(U
* aLhs
, const RefPtr
<T
>& aRhs
)
589 return const_cast<const U
*>(aLhs
) == static_cast<const T
*>(aRhs
.get());
592 template <class T
, class U
>
594 operator!=(const RefPtr
<T
>& aLhs
, U
* aRhs
)
596 return static_cast<const T
*>(aLhs
.get()) != const_cast<const U
*>(aRhs
);
599 template <class T
, class U
>
601 operator!=(U
* aLhs
, const RefPtr
<T
>& aRhs
)
603 return const_cast<const U
*>(aLhs
) != static_cast<const T
*>(aRhs
.get());
606 // Comparing an |RefPtr| to |nullptr|
610 operator==(const RefPtr
<T
>& aLhs
, decltype(nullptr))
612 return aLhs
.get() == nullptr;
617 operator==(decltype(nullptr), const RefPtr
<T
>& aRhs
)
619 return nullptr == aRhs
.get();
624 operator!=(const RefPtr
<T
>& aLhs
, decltype(nullptr))
626 return aLhs
.get() != nullptr;
631 operator!=(decltype(nullptr), const RefPtr
<T
>& aRhs
)
633 return nullptr != aRhs
.get();
636 /*****************************************************************************/
639 inline already_AddRefed
<T
>
647 inline already_AddRefed
<T
>
648 do_AddRef(const RefPtr
<T
>& aObj
)
657 * Helper function to be able to conveniently write things like:
659 * already_AddRefed<T>
662 * return MakeAndAddRef<T>(...);
665 template<typename T
, typename
... Args
>
667 MakeAndAddRef(Args
&&... aArgs
)
669 RefPtr
<T
> p(new T(std::forward
<Args
>(aArgs
)...));
674 * Helper function to be able to conveniently write things like:
676 * auto runnable = MakeRefPtr<ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>>(
677 * mOnSuccess, mOnFailure, *error, mWindowID);
679 template<typename T
, typename
... Args
>
681 MakeRefPtr(Args
&&... aArgs
)
683 RefPtr
<T
> p(new T(std::forward
<Args
>(aArgs
)...));
687 } // namespace mozilla
689 #endif /* mozilla_RefPtr_h */