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"
13 #include "mozilla/DbgMacro.h"
15 /*****************************************************************************/
17 // template <class T> class RefPtrGetterAddRefs;
19 class nsQueryReferent
;
20 class nsCOMPtr_helper
;
27 class StaticLocalRefPtr
;
34 #endif // defined(XP_WIN)
36 // Traditionally, RefPtr supports automatic refcounting of any pointer type
37 // with AddRef() and Release() methods that follow the traditional semantics.
39 // This traits class can be specialized to operate on other pointer types. For
40 // example, we specialize this trait for opaque FFI types that represent
41 // refcounted objects in Rust.
43 // Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
47 static void AddRef(U
* aPtr
) { aPtr
->AddRef(); }
48 static void Release(U
* aPtr
) { aPtr
->Release(); }
51 } // namespace mozilla
54 class MOZ_IS_REFPTR RefPtr
{
56 void assign_with_AddRef(T
* aRawPtr
) {
58 ConstRemovingRefPtrTraits
<T
>::AddRef(aRawPtr
);
60 assign_assuming_AddRef(aRawPtr
);
63 void assign_assuming_AddRef(T
* aNewPtr
) {
67 ConstRemovingRefPtrTraits
<T
>::Release(oldPtr
);
72 T
* MOZ_OWNING_REF mRawPtr
;
75 typedef T element_type
;
79 ConstRemovingRefPtrTraits
<T
>::Release(mRawPtr
);
87 // default constructor
90 RefPtr(const RefPtr
<T
>& aSmartPtr
)
91 : mRawPtr(aSmartPtr
.mRawPtr
)
95 ConstRemovingRefPtrTraits
<T
>::AddRef(mRawPtr
);
99 RefPtr(RefPtr
<T
>&& aRefPtr
) : mRawPtr(aRefPtr
.mRawPtr
) {
100 aRefPtr
.mRawPtr
= nullptr;
103 // construct from a raw pointer (of the right type)
105 MOZ_IMPLICIT
RefPtr(T
* aRawPtr
) : mRawPtr(aRawPtr
) {
107 ConstRemovingRefPtrTraits
<T
>::AddRef(mRawPtr
);
111 MOZ_IMPLICIT
RefPtr(decltype(nullptr)) : mRawPtr(nullptr) {}
113 template <typename I
>
114 MOZ_IMPLICIT
RefPtr(already_AddRefed
<I
>& aSmartPtr
)
115 : mRawPtr(aSmartPtr
.take())
116 // construct from |already_AddRefed|
119 template <typename I
>
120 MOZ_IMPLICIT
RefPtr(already_AddRefed
<I
>&& aSmartPtr
)
121 : mRawPtr(aSmartPtr
.take())
122 // construct from |otherRefPtr.forget()|
125 template <typename I
>
126 MOZ_IMPLICIT
RefPtr(const RefPtr
<I
>& aSmartPtr
)
127 : mRawPtr(aSmartPtr
.get())
128 // copy-construct from a smart pointer with a related pointer type
131 ConstRemovingRefPtrTraits
<T
>::AddRef(mRawPtr
);
135 template <typename I
>
136 MOZ_IMPLICIT
RefPtr(RefPtr
<I
>&& aSmartPtr
)
137 : mRawPtr(aSmartPtr
.forget().take())
138 // construct from |Move(RefPtr<SomeSubclassOfT>)|.
141 MOZ_IMPLICIT
RefPtr(const nsQueryReferent
& aHelper
);
142 MOZ_IMPLICIT
RefPtr(const nsCOMPtr_helper
& aHelper
);
144 MOZ_IMPLICIT
RefPtr(const mozilla::mscom::AgileReference
& aAgileRef
);
145 #endif // defined(XP_WIN)
147 // Defined in OwningNonNull.h
149 MOZ_IMPLICIT
RefPtr(const mozilla::OwningNonNull
<U
>& aOther
);
151 // Defined in StaticLocalPtr.h
153 MOZ_IMPLICIT
RefPtr(const mozilla::StaticLocalRefPtr
<U
>& aOther
);
155 // Defined in StaticPtr.h
157 MOZ_IMPLICIT
RefPtr(const mozilla::StaticRefPtr
<U
>& aOther
);
159 // Assignment operators
161 RefPtr
<T
>& operator=(decltype(nullptr)) {
162 assign_assuming_AddRef(nullptr);
166 RefPtr
<T
>& operator=(const RefPtr
<T
>& aRhs
)
167 // copy assignment operator
169 assign_with_AddRef(aRhs
.mRawPtr
);
173 template <typename I
>
174 RefPtr
<T
>& operator=(const RefPtr
<I
>& aRhs
)
175 // assign from an RefPtr of a related pointer type
177 assign_with_AddRef(aRhs
.get());
181 RefPtr
<T
>& operator=(T
* aRhs
)
182 // assign from a raw pointer (of the right type)
184 assign_with_AddRef(aRhs
);
188 template <typename I
>
189 RefPtr
<T
>& operator=(already_AddRefed
<I
>& aRhs
)
190 // assign from |already_AddRefed|
192 assign_assuming_AddRef(aRhs
.take());
196 template <typename I
>
197 RefPtr
<T
>& operator=(already_AddRefed
<I
>&& aRhs
)
198 // assign from |otherRefPtr.forget()|
200 assign_assuming_AddRef(aRhs
.take());
204 RefPtr
<T
>& operator=(const nsQueryReferent
& aQueryReferent
);
205 RefPtr
<T
>& operator=(const nsCOMPtr_helper
& aHelper
);
207 RefPtr
<T
>& operator=(const mozilla::mscom::AgileReference
& aAgileRef
);
208 #endif // defined(XP_WIN)
210 RefPtr
<T
>& operator=(RefPtr
<T
>&& aRefPtr
) {
211 assign_assuming_AddRef(aRefPtr
.forget().take());
215 // Defined in OwningNonNull.h
217 RefPtr
<T
>& operator=(const mozilla::OwningNonNull
<U
>& aOther
);
219 // Defined in StaticLocalPtr.h
221 RefPtr
<T
>& operator=(const mozilla::StaticLocalRefPtr
<U
>& aOther
);
223 // Defined in StaticPtr.h
225 RefPtr
<T
>& operator=(const mozilla::StaticRefPtr
<U
>& aOther
);
227 // Other pointer operators
229 void swap(RefPtr
<T
>& aRhs
)
230 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
232 T
* temp
= aRhs
.mRawPtr
;
233 aRhs
.mRawPtr
= mRawPtr
;
238 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
245 already_AddRefed
<T
> MOZ_MAY_CALL_AFTER_MUST_RETURN
forget()
246 // return the value of mRawPtr and null out mRawPtr. Useful for
247 // already_AddRefed return values.
251 return already_AddRefed
<T
>(temp
);
254 template <typename I
>
255 void forget(I
** aRhs
)
256 // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
257 // Useful to avoid unnecessary AddRef/Release pairs with "out"
258 // parameters where aRhs bay be a T** or an I** where I is a base class
261 MOZ_ASSERT(aRhs
, "Null pointer passed to forget!");
266 void forget(nsISupports
** aRhs
) {
267 MOZ_ASSERT(aRhs
, "Null pointer passed to forget!");
268 *aRhs
= ToSupports(mRawPtr
);
274 Prefer the implicit conversion provided automatically by |operator T*()
275 const|. Use |get()| to resolve ambiguity or to get a castable pointer.
278 return const_cast<T
*>(mRawPtr
);
283 ...makes an |RefPtr| act like its underlying raw pointer type whenever it
284 is used in a context where a raw pointer is expected. It is this operator
285 that makes an |RefPtr| substitutable for a raw pointer.
287 Prefer the implicit use of this operator to calling |get()|, except where
288 necessary to resolve ambiguity.
294 // Don't allow implicit conversion of temporary RefPtr to raw pointer,
295 // because the refcount might be one and the pointer will immediately become
297 operator T
*() const&& = delete;
299 // These are needed to avoid the deleted operator above. XXX Why is operator!
300 // needed separately? Shouldn't the compiler prefer using the non-deleted
301 // operator bool instead of the deleted operator T*?
302 explicit operator bool() const { return !!mRawPtr
; }
303 bool operator!() const { return !mRawPtr
; }
305 T
* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
{
306 MOZ_ASSERT(mRawPtr
!= nullptr,
307 "You can't dereference a NULL RefPtr with operator->().");
311 template <typename R
, typename
... Args
>
313 typedef R (T::*member_function
)(Args
...);
315 member_function mFunction
;
318 Proxy(T
* aRawPtr
, member_function aFunction
)
319 : mRawPtr(aRawPtr
), mFunction(aFunction
) {}
320 template <typename
... ActualArgs
>
321 R
operator()(ActualArgs
&&... aArgs
) {
322 return ((*mRawPtr
).*mFunction
)(std::forward
<ActualArgs
>(aArgs
)...);
326 template <typename R
, typename
... Args
>
327 Proxy
<R
, Args
...> operator->*(R (T::*aFptr
)(Args
...)) const {
328 MOZ_ASSERT(mRawPtr
!= nullptr,
329 "You can't dereference a NULL RefPtr with operator->*().");
330 return Proxy
<R
, Args
...>(get(), aFptr
);
333 RefPtr
<T
>* get_address()
334 // This is not intended to be used by clients. See |address_of|
340 const RefPtr
<T
>* get_address() const
341 // This is not intended to be used by clients. See |address_of|
348 T
& operator*() const {
349 MOZ_ASSERT(mRawPtr
!= nullptr,
350 "You can't dereference a NULL RefPtr with operator*().");
354 T
** StartAssignment() {
355 assign_assuming_AddRef(nullptr);
356 return reinterpret_cast<T
**>(&mRawPtr
);
360 // This helper class makes |RefPtr<const T>| possible by casting away
361 // the constness from the pointer when calling AddRef() and Release().
363 // This is necessary because AddRef() and Release() implementations can't
364 // generally expected to be const themselves (without heavy use of |mutable|
365 // and |const_cast| in their own implementations).
367 // This should be sound because while |RefPtr<const T>| provides a
368 // const view of an object, the object itself should not be const (it
369 // would have to be allocated as |new const T| or similar to be const).
371 struct ConstRemovingRefPtrTraits
{
372 static void AddRef(U
* aPtr
) { mozilla::RefPtrTraits
<U
>::AddRef(aPtr
); }
373 static void Release(U
* aPtr
) { mozilla::RefPtrTraits
<U
>::Release(aPtr
); }
376 struct ConstRemovingRefPtrTraits
<const U
> {
377 static void AddRef(const U
* aPtr
) {
378 mozilla::RefPtrTraits
<U
>::AddRef(const_cast<U
*>(aPtr
));
380 static void Release(const U
* aPtr
) {
381 mozilla::RefPtrTraits
<U
>::Release(const_cast<U
*>(aPtr
));
386 class nsCycleCollectionTraversalCallback
;
387 template <typename T
>
388 void CycleCollectionNoteChild(nsCycleCollectionTraversalCallback
& aCallback
,
389 T
* aChild
, const char* aName
, uint32_t aFlags
);
391 template <typename T
>
392 inline void ImplCycleCollectionUnlink(RefPtr
<T
>& aField
) {
396 template <typename T
>
397 inline void ImplCycleCollectionTraverse(
398 nsCycleCollectionTraversalCallback
& aCallback
, RefPtr
<T
>& aField
,
399 const char* aName
, uint32_t aFlags
= 0) {
400 CycleCollectionNoteChild(aCallback
, aField
.get(), aName
, aFlags
);
404 inline RefPtr
<T
>* address_of(RefPtr
<T
>& aPtr
) {
405 return aPtr
.get_address();
409 inline const RefPtr
<T
>* address_of(const RefPtr
<T
>& aPtr
) {
410 return aPtr
.get_address();
414 class RefPtrGetterAddRefs
418 This class is designed to be used for anonymous temporary objects in the
419 argument list of calls that return COM interface pointers, e.g.,
422 ...->GetAddRefedPointer(getter_AddRefs(fooP))
424 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
426 When initialized with a |RefPtr|, as in the example above, it returns
427 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
428 outer call (|GetAddRefedPointer| in this case) can fill in.
430 This type should be a nested class inside |RefPtr<T>|.
434 explicit RefPtrGetterAddRefs(RefPtr
<T
>& aSmartPtr
)
435 : mTargetSmartPtr(aSmartPtr
) {
436 // nothing else to do
440 return reinterpret_cast<void**>(mTargetSmartPtr
.StartAssignment());
443 operator T
**() { return mTargetSmartPtr
.StartAssignment(); }
445 T
*& operator*() { return *(mTargetSmartPtr
.StartAssignment()); }
448 RefPtr
<T
>& mTargetSmartPtr
;
452 inline RefPtrGetterAddRefs
<T
> getter_AddRefs(RefPtr
<T
>& aSmartPtr
)
454 Used around a |RefPtr| when
455 ...makes the class |RefPtrGetterAddRefs<T>| invisible.
458 return RefPtrGetterAddRefs
<T
>(aSmartPtr
);
461 // Comparing two |RefPtr|s
463 template <class T
, class U
>
464 inline bool operator==(const RefPtr
<T
>& aLhs
, const RefPtr
<U
>& aRhs
) {
465 return static_cast<const T
*>(aLhs
.get()) == static_cast<const U
*>(aRhs
.get());
468 template <class T
, class U
>
469 inline bool operator!=(const RefPtr
<T
>& aLhs
, const RefPtr
<U
>& aRhs
) {
470 return static_cast<const T
*>(aLhs
.get()) != static_cast<const U
*>(aRhs
.get());
473 // Comparing an |RefPtr| to a raw pointer
475 template <class T
, class U
>
476 inline bool operator==(const RefPtr
<T
>& aLhs
, const U
* aRhs
) {
477 return static_cast<const T
*>(aLhs
.get()) == static_cast<const U
*>(aRhs
);
480 template <class T
, class U
>
481 inline bool operator==(const U
* aLhs
, const RefPtr
<T
>& aRhs
) {
482 return static_cast<const U
*>(aLhs
) == static_cast<const T
*>(aRhs
.get());
485 template <class T
, class U
>
486 inline bool operator!=(const RefPtr
<T
>& aLhs
, const U
* aRhs
) {
487 return static_cast<const T
*>(aLhs
.get()) != static_cast<const U
*>(aRhs
);
490 template <class T
, class U
>
491 inline bool operator!=(const U
* aLhs
, const RefPtr
<T
>& aRhs
) {
492 return static_cast<const U
*>(aLhs
) != static_cast<const T
*>(aRhs
.get());
495 template <class T
, class U
>
496 inline bool operator==(const RefPtr
<T
>& aLhs
, U
* aRhs
) {
497 return static_cast<const T
*>(aLhs
.get()) == const_cast<const U
*>(aRhs
);
500 template <class T
, class U
>
501 inline bool operator==(U
* aLhs
, const RefPtr
<T
>& aRhs
) {
502 return const_cast<const U
*>(aLhs
) == static_cast<const T
*>(aRhs
.get());
505 template <class T
, class U
>
506 inline bool operator!=(const RefPtr
<T
>& aLhs
, U
* aRhs
) {
507 return static_cast<const T
*>(aLhs
.get()) != const_cast<const U
*>(aRhs
);
510 template <class T
, class U
>
511 inline bool operator!=(U
* aLhs
, const RefPtr
<T
>& aRhs
) {
512 return const_cast<const U
*>(aLhs
) != static_cast<const T
*>(aRhs
.get());
515 // Comparing an |RefPtr| to |nullptr|
518 inline bool operator==(const RefPtr
<T
>& aLhs
, decltype(nullptr)) {
519 return aLhs
.get() == nullptr;
523 inline bool operator==(decltype(nullptr), const RefPtr
<T
>& aRhs
) {
524 return nullptr == aRhs
.get();
528 inline bool operator!=(const RefPtr
<T
>& aLhs
, decltype(nullptr)) {
529 return aLhs
.get() != nullptr;
533 inline bool operator!=(decltype(nullptr), const RefPtr
<T
>& aRhs
) {
534 return nullptr != aRhs
.get();
540 std::ostream
& operator<<(std::ostream
& aOut
, const RefPtr
<T
>& aObj
) {
541 return mozilla::DebugValue(aOut
, aObj
.get());
544 /*****************************************************************************/
547 inline already_AddRefed
<T
> do_AddRef(T
* aObj
) {
553 inline already_AddRefed
<T
> do_AddRef(const RefPtr
<T
>& aObj
) {
561 * Helper function to be able to conveniently write things like:
563 * already_AddRefed<T>
566 * return MakeAndAddRef<T>(...);
569 template <typename T
, typename
... Args
>
570 already_AddRefed
<T
> MakeAndAddRef(Args
&&... aArgs
) {
571 RefPtr
<T
> p(new T(std::forward
<Args
>(aArgs
)...));
576 * Helper function to be able to conveniently write things like:
579 * MakeRefPtr<ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>>(
580 * mOnSuccess, mOnFailure, *error, mWindowID);
582 template <typename T
, typename
... Args
>
583 RefPtr
<T
> MakeRefPtr(Args
&&... aArgs
) {
584 RefPtr
<T
> p(new T(std::forward
<Args
>(aArgs
)...));
588 } // namespace mozilla
590 #endif /* mozilla_RefPtr_h */