Bug 1690340 - Part 4: Insert the "Page Source" before the "Extensions for Developers...
[gecko.git] / xpcom / base / nsMaybeWeakPtr.h
blob165a8c23c1825817517e01e6a58b227137d8a3f0
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsMaybeWeakPtr_h_
7 #define nsMaybeWeakPtr_h_
9 #include "mozilla/Attributes.h"
10 #include "nsCOMPtr.h"
11 #include "nsIWeakReferenceUtils.h"
12 #include "nsTArray.h"
13 #include "nsCycleCollectionNoteChild.h"
15 // nsMaybeWeakPtr is a helper object to hold a strong-or-weak reference
16 // to the template class. It's pretty minimal, but sufficient.
18 template <class T>
19 class nsMaybeWeakPtr {
20 public:
21 nsMaybeWeakPtr() = default;
22 MOZ_IMPLICIT nsMaybeWeakPtr(T* aRef) : mPtr(aRef), mWeak(false) {}
23 MOZ_IMPLICIT nsMaybeWeakPtr(const nsCOMPtr<nsIWeakReference>& aRef)
24 : mPtr(aRef), mWeak(true) {}
26 nsMaybeWeakPtr<T>& operator=(T* aRef) {
27 mPtr = aRef;
28 mWeak = false;
29 return *this;
32 nsMaybeWeakPtr<T>& operator=(const nsCOMPtr<nsIWeakReference>& aRef) {
33 mPtr = aRef;
34 mWeak = true;
35 return *this;
38 bool operator==(const nsMaybeWeakPtr<T>& other) const {
39 return mPtr == other.mPtr;
42 nsISupports* GetRawValue() const { return mPtr.get(); }
43 bool IsWeak() const { return mWeak; }
45 const nsCOMPtr<T> GetValue() const;
47 private:
48 nsCOMPtr<nsISupports> mPtr;
49 bool mWeak;
52 // nsMaybeWeakPtrArray is an array of MaybeWeakPtr objects, that knows how to
53 // grab a weak reference to a given object if requested. It only allows a
54 // given object to appear in the array once.
56 template <class T>
57 class nsMaybeWeakPtrArray : public CopyableTArray<nsMaybeWeakPtr<T>> {
58 typedef nsTArray<nsMaybeWeakPtr<T>> MaybeWeakArray;
60 nsresult SetMaybeWeakPtr(nsMaybeWeakPtr<T>& aRef, T* aElement,
61 bool aOwnsWeak) {
62 nsresult rv = NS_OK;
64 if (aOwnsWeak) {
65 aRef = do_GetWeakReference(aElement, &rv);
66 } else {
67 aRef = aElement;
70 return rv;
73 public:
74 nsresult AppendWeakElement(T* aElement, bool aOwnsWeak) {
75 nsMaybeWeakPtr<T> ref;
76 MOZ_TRY(SetMaybeWeakPtr(ref, aElement, aOwnsWeak));
78 MaybeWeakArray::AppendElement(ref);
79 return NS_OK;
82 nsresult AppendWeakElementUnlessExists(T* aElement, bool aOwnsWeak) {
83 nsMaybeWeakPtr<T> ref;
84 MOZ_TRY(SetMaybeWeakPtr(ref, aElement, aOwnsWeak));
86 if (MaybeWeakArray::Contains(ref)) {
87 return NS_ERROR_INVALID_ARG;
90 MaybeWeakArray::AppendElement(ref);
91 return NS_OK;
94 nsresult RemoveWeakElement(T* aElement) {
95 if (MaybeWeakArray::RemoveElement(aElement)) {
96 return NS_OK;
99 // Don't use do_GetWeakReference; it should only be called if we know
100 // the object supports weak references.
101 nsCOMPtr<nsISupportsWeakReference> supWeakRef = do_QueryInterface(aElement);
102 if (!supWeakRef) {
103 return NS_ERROR_INVALID_ARG;
106 nsCOMPtr<nsIWeakReference> weakRef;
107 nsresult rv = supWeakRef->GetWeakReference(getter_AddRefs(weakRef));
108 NS_ENSURE_SUCCESS(rv, rv);
110 if (MaybeWeakArray::RemoveElement(weakRef)) {
111 return NS_OK;
114 return NS_ERROR_INVALID_ARG;
118 template <class T>
119 const nsCOMPtr<T> nsMaybeWeakPtr<T>::GetValue() const {
120 if (!mPtr) {
121 return nullptr;
124 nsCOMPtr<T> ref;
125 nsresult rv;
127 if (mWeak) {
128 nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(mPtr);
129 if (weakRef) {
130 ref = do_QueryReferent(weakRef, &rv);
131 if (NS_SUCCEEDED(rv)) {
132 return ref;
135 } else {
136 ref = do_QueryInterface(mPtr, &rv);
137 if (NS_SUCCEEDED(rv)) {
138 return ref;
142 return nullptr;
145 template <typename T>
146 inline void ImplCycleCollectionUnlink(nsMaybeWeakPtrArray<T>& aField) {
147 aField.Clear();
150 template <typename E>
151 inline void ImplCycleCollectionTraverse(
152 nsCycleCollectionTraversalCallback& aCallback,
153 nsMaybeWeakPtrArray<E>& aField, const char* aName, uint32_t aFlags = 0) {
154 aFlags |= CycleCollectionEdgeNameArrayFlag;
155 size_t length = aField.Length();
156 for (size_t i = 0; i < length; ++i) {
157 CycleCollectionNoteChild(aCallback, aField[i].GetRawValue(), aName, aFlags);
161 // Call a method on each element in the array, but only if the element is
162 // non-null.
164 #define ENUMERATE_WEAKARRAY(array, type, method) \
165 for (uint32_t array_idx = 0; array_idx < array.Length(); ++array_idx) { \
166 const nsCOMPtr<type>& e = array.ElementAt(array_idx).GetValue(); \
167 if (e) e->method; \
170 #endif