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"
11 #include "nsIWeakReferenceUtils.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.
19 class nsMaybeWeakPtr
{
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
) {
32 nsMaybeWeakPtr
<T
>& operator=(const nsCOMPtr
<nsIWeakReference
>& aRef
) {
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;
48 nsCOMPtr
<nsISupports
> mPtr
;
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.
57 class nsMaybeWeakPtrArray
: public CopyableTArray
<nsMaybeWeakPtr
<T
>> {
58 typedef nsTArray
<nsMaybeWeakPtr
<T
>> MaybeWeakArray
;
60 nsresult
SetMaybeWeakPtr(nsMaybeWeakPtr
<T
>& aRef
, T
* aElement
,
65 aRef
= do_GetWeakReference(aElement
, &rv
);
74 nsresult
AppendWeakElement(T
* aElement
, bool aOwnsWeak
) {
75 nsMaybeWeakPtr
<T
> ref
;
76 MOZ_TRY(SetMaybeWeakPtr(ref
, aElement
, aOwnsWeak
));
78 MaybeWeakArray::AppendElement(ref
);
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
);
94 nsresult
RemoveWeakElement(T
* aElement
) {
95 if (MaybeWeakArray::RemoveElement(aElement
)) {
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
);
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
)) {
114 return NS_ERROR_INVALID_ARG
;
119 const nsCOMPtr
<T
> nsMaybeWeakPtr
<T
>::GetValue() const {
128 nsCOMPtr
<nsIWeakReference
> weakRef
= do_QueryInterface(mPtr
);
130 ref
= do_QueryReferent(weakRef
, &rv
);
131 if (NS_SUCCEEDED(rv
)) {
136 ref
= do_QueryInterface(mPtr
, &rv
);
137 if (NS_SUCCEEDED(rv
)) {
145 template <typename T
>
146 inline void ImplCycleCollectionUnlink(nsMaybeWeakPtrArray
<T
>& aField
) {
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
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(); \