Bug 1507750 - Compare the flexbox state for any changes before updating on reflows...
[gecko.git] / mfbt / RefPtr.h
blobe0b05f1a3e628a283ceb0f1610eead641d43152b
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;
20 class nsISupports;
22 namespace mozilla {
23 template<class T> class OwningNonNull;
24 template<class T> class StaticRefPtr;
25 #if defined(XP_WIN)
26 namespace mscom {
27 class AgileReference;
28 } // namespace mscom
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-
39 // qualified type.
40 template<class U>
41 struct RefPtrTraits
43 static void AddRef(U* aPtr) {
44 aPtr->AddRef();
46 static void Release(U* aPtr) {
47 aPtr->Release();
51 } // namespace mozilla
53 template <class T>
54 class MOZ_IS_REFPTR RefPtr
56 private:
57 void
58 assign_with_AddRef(T* aRawPtr)
60 if (aRawPtr) {
61 ConstRemovingRefPtrTraits<T>::AddRef(aRawPtr);
63 assign_assuming_AddRef(aRawPtr);
66 void
67 assign_assuming_AddRef(T* aNewPtr)
69 T* oldPtr = mRawPtr;
70 mRawPtr = aNewPtr;
71 if (oldPtr) {
72 ConstRemovingRefPtrTraits<T>::Release(oldPtr);
76 private:
77 T* MOZ_OWNING_REF mRawPtr;
79 public:
80 typedef T element_type;
82 ~RefPtr()
84 if (mRawPtr) {
85 ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
89 // Constructors
91 RefPtr()
92 : mRawPtr(nullptr)
93 // default constructor
97 RefPtr(const RefPtr<T>& aSmartPtr)
98 : mRawPtr(aSmartPtr.mRawPtr)
99 // copy-constructor
101 if (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)
115 : mRawPtr(aRawPtr)
117 if (mRawPtr) {
118 ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
122 MOZ_IMPLICIT RefPtr(decltype(nullptr))
123 : mRawPtr(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
146 if (mRawPtr) {
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);
160 #if defined(XP_WIN)
161 MOZ_IMPLICIT RefPtr(const mozilla::mscom::AgileReference& aAgileRef);
162 #endif // defined(XP_WIN)
164 // Defined in OwningNonNull.h
165 template<class U>
166 MOZ_IMPLICIT RefPtr(const mozilla::OwningNonNull<U>& aOther);
168 // Defined in StaticPtr.h
169 template<class U>
170 MOZ_IMPLICIT RefPtr(const mozilla::StaticRefPtr<U>& aOther);
172 // Assignment operators
174 RefPtr<T>&
175 operator=(decltype(nullptr))
177 assign_assuming_AddRef(nullptr);
178 return *this;
181 RefPtr<T>&
182 operator=(const RefPtr<T>& aRhs)
183 // copy assignment operator
185 assign_with_AddRef(aRhs.mRawPtr);
186 return *this;
189 template <typename I>
190 RefPtr<T>&
191 operator=(const RefPtr<I>& aRhs)
192 // assign from an RefPtr of a related pointer type
194 assign_with_AddRef(aRhs.get());
195 return *this;
198 RefPtr<T>&
199 operator=(T* aRhs)
200 // assign from a raw pointer (of the right type)
202 assign_with_AddRef(aRhs);
203 return *this;
206 template <typename I>
207 RefPtr<T>&
208 operator=(already_AddRefed<I>& aRhs)
209 // assign from |already_AddRefed|
211 assign_assuming_AddRef(aRhs.take());
212 return *this;
215 template <typename I>
216 RefPtr<T>&
217 operator=(already_AddRefed<I> && aRhs)
218 // assign from |otherRefPtr.forget()|
220 assign_assuming_AddRef(aRhs.take());
221 return *this;
224 RefPtr<T>& operator=(const nsQueryReferent& aQueryReferent);
225 RefPtr<T>& operator=(const nsCOMPtr_helper& aHelper);
226 #if defined(XP_WIN)
227 RefPtr<T>& operator=(const mozilla::mscom::AgileReference& aAgileRef);
228 #endif // defined(XP_WIN)
230 RefPtr<T>&
231 operator=(RefPtr<T> && aRefPtr)
233 assign_assuming_AddRef(aRefPtr.mRawPtr);
234 aRefPtr.mRawPtr = nullptr;
235 return *this;
238 // Defined in OwningNonNull.h
239 template<class U>
240 RefPtr<T>&
241 operator=(const mozilla::OwningNonNull<U>& aOther);
243 // Defined in StaticPtr.h
244 template<class U>
245 RefPtr<T>&
246 operator=(const mozilla::StaticRefPtr<U>& aOther);
248 // Other pointer operators
250 void
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;
256 mRawPtr = temp;
259 void
260 swap(T*& aRhs)
261 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
263 T* temp = aRhs;
264 aRhs = mRawPtr;
265 mRawPtr = temp;
268 already_AddRefed<T>
269 MOZ_MAY_CALL_AFTER_MUST_RETURN
270 forget()
271 // return the value of mRawPtr and null out mRawPtr. Useful for
272 // already_AddRefed return values.
274 T* temp = nullptr;
275 swap(temp);
276 return already_AddRefed<T>(temp);
279 template <typename I>
280 void
281 forget(I** aRhs)
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
285 // of T.
287 MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
288 *aRhs = mRawPtr;
289 mRawPtr = nullptr;
292 void
293 forget(nsISupports** aRhs)
295 MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
296 *aRhs = ToSupports(mRawPtr);
297 mRawPtr = nullptr;
301 get() const
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.
320 return get();
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
325 // invalid.
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->().");
339 return get();
342 template <typename R, typename... Args>
343 class Proxy
345 typedef R (T::*member_function)(Args...);
346 T* mRawPtr;
347 member_function mFunction;
348 public:
349 Proxy(T* aRawPtr, member_function aFunction)
350 : mRawPtr(aRawPtr),
351 mFunction(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);
369 RefPtr<T>*
370 get_address()
371 // This is not intended to be used by clients. See |address_of|
372 // below.
374 return this;
377 const RefPtr<T>*
378 get_address() const
379 // This is not intended to be used by clients. See |address_of|
380 // below.
382 return this;
385 public:
387 operator*() const
389 MOZ_ASSERT(mRawPtr != nullptr,
390 "You can't dereference a NULL RefPtr with operator*().");
391 return *get();
395 StartAssignment()
397 assign_assuming_AddRef(nullptr);
398 return reinterpret_cast<T**>(&mRawPtr);
400 private:
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).
411 template<class U>
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);
421 template<class U>
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>
435 void
436 CycleCollectionNoteChild(nsCycleCollectionTraversalCallback& aCallback,
437 T* aChild, const char* aName, uint32_t aFlags);
439 template <typename T>
440 inline void
441 ImplCycleCollectionUnlink(RefPtr<T>& aField)
443 aField = nullptr;
446 template <typename T>
447 inline void
448 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
449 RefPtr<T>& aField,
450 const char* aName,
451 uint32_t aFlags = 0)
453 CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
456 template <class T>
457 inline RefPtr<T>*
458 address_of(RefPtr<T>& aPtr)
460 return aPtr.get_address();
463 template <class T>
464 inline const RefPtr<T>*
465 address_of(const RefPtr<T>& aPtr)
467 return aPtr.get_address();
470 template <class T>
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.,
478 RefPtr<IFoo> fooP;
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>|.
490 public:
491 explicit
492 RefPtrGetterAddRefs(RefPtr<T>& aSmartPtr)
493 : mTargetSmartPtr(aSmartPtr)
495 // nothing else to do
498 operator void**()
500 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
503 operator T**()
505 return mTargetSmartPtr.StartAssignment();
509 operator*()
511 return *(mTargetSmartPtr.StartAssignment());
514 private:
515 RefPtr<T>& mTargetSmartPtr;
518 template <class T>
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>
533 inline bool
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>
541 inline bool
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>
551 inline bool
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>
558 inline bool
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>
565 inline bool
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>
572 inline bool
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>
579 inline bool
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>
586 inline bool
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>
593 inline bool
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>
600 inline bool
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|
608 template <class T>
609 inline bool
610 operator==(const RefPtr<T>& aLhs, decltype(nullptr))
612 return aLhs.get() == nullptr;
615 template <class T>
616 inline bool
617 operator==(decltype(nullptr), const RefPtr<T>& aRhs)
619 return nullptr == aRhs.get();
622 template <class T>
623 inline bool
624 operator!=(const RefPtr<T>& aLhs, decltype(nullptr))
626 return aLhs.get() != nullptr;
629 template <class T>
630 inline bool
631 operator!=(decltype(nullptr), const RefPtr<T>& aRhs)
633 return nullptr != aRhs.get();
636 /*****************************************************************************/
638 template <class T>
639 inline already_AddRefed<T>
640 do_AddRef(T* aObj)
642 RefPtr<T> ref(aObj);
643 return ref.forget();
646 template <class T>
647 inline already_AddRefed<T>
648 do_AddRef(const RefPtr<T>& aObj)
650 RefPtr<T> ref(aObj);
651 return ref.forget();
654 namespace mozilla {
657 * Helper function to be able to conveniently write things like:
659 * already_AddRefed<T>
660 * f(...)
662 * return MakeAndAddRef<T>(...);
665 template<typename T, typename... Args>
666 already_AddRefed<T>
667 MakeAndAddRef(Args&&... aArgs)
669 RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
670 return p.forget();
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>
680 RefPtr<T>
681 MakeRefPtr(Args&&... aArgs)
683 RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
684 return p;
687 } // namespace mozilla
689 #endif /* mozilla_RefPtr_h */