Line data Source code
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/. */
5 :
6 : #ifndef nsMaybeWeakPtr_h_
7 : #define nsMaybeWeakPtr_h_
8 :
9 : #include "mozilla/Attributes.h"
10 : #include "nsCOMPtr.h"
11 : #include "nsWeakReference.h"
12 : #include "nsTArray.h"
13 : #include "nsCycleCollectionNoteChild.h"
14 :
15 : // nsMaybeWeakPtr is a helper object to hold a strong-or-weak reference
16 : // to the template class. It's pretty minimal, but sufficient.
17 :
18 : template<class T>
19 4 : class nsMaybeWeakPtr
20 : {
21 : public:
22 9 : MOZ_IMPLICIT nsMaybeWeakPtr(nsISupports* aRef) : mPtr(aRef) {}
23 0 : MOZ_IMPLICIT nsMaybeWeakPtr(const nsCOMPtr<nsIWeakReference>& aRef) : mPtr(aRef) {}
24 : MOZ_IMPLICIT nsMaybeWeakPtr(const nsCOMPtr<T>& aRef) : mPtr(aRef) {}
25 :
26 4 : bool operator==(const nsMaybeWeakPtr<T> &other) const {
27 4 : return mPtr == other.mPtr;
28 : }
29 :
30 0 : nsISupports* GetRawValue() const { return mPtr.get(); }
31 :
32 : const nsCOMPtr<T> GetValue() const;
33 :
34 : private:
35 : nsCOMPtr<nsISupports> mPtr;
36 : };
37 :
38 : // nsMaybeWeakPtrArray is an array of MaybeWeakPtr objects, that knows how to
39 : // grab a weak reference to a given object if requested. It only allows a
40 : // given object to appear in the array once.
41 :
42 : template<class T>
43 2 : class nsMaybeWeakPtrArray : public nsTArray<nsMaybeWeakPtr<T>>
44 : {
45 : typedef nsTArray<nsMaybeWeakPtr<T>> MaybeWeakArray;
46 :
47 : public:
48 5 : nsresult AppendWeakElement(T* aElement, bool aOwnsWeak)
49 : {
50 10 : nsCOMPtr<nsISupports> ref;
51 5 : if (aOwnsWeak) {
52 3 : ref = do_GetWeakReference(aElement);
53 : } else {
54 2 : ref = aElement;
55 : }
56 :
57 5 : if (MaybeWeakArray::Contains(ref.get())) {
58 0 : return NS_ERROR_INVALID_ARG;
59 : }
60 5 : if (!MaybeWeakArray::AppendElement(ref)) {
61 0 : return NS_ERROR_OUT_OF_MEMORY;
62 : }
63 5 : return NS_OK;
64 : }
65 :
66 0 : nsresult RemoveWeakElement(T* aElement)
67 : {
68 0 : if (MaybeWeakArray::RemoveElement(aElement)) {
69 0 : return NS_OK;
70 : }
71 :
72 : // Don't use do_GetWeakReference; it should only be called if we know
73 : // the object supports weak references.
74 0 : nsCOMPtr<nsISupportsWeakReference> supWeakRef = do_QueryInterface(aElement);
75 0 : NS_ENSURE_TRUE(supWeakRef, NS_ERROR_INVALID_ARG);
76 :
77 0 : nsCOMPtr<nsIWeakReference> weakRef;
78 0 : nsresult rv = supWeakRef->GetWeakReference(getter_AddRefs(weakRef));
79 0 : NS_ENSURE_SUCCESS(rv, rv);
80 :
81 0 : if (MaybeWeakArray::RemoveElement(weakRef)) {
82 0 : return NS_OK;
83 : }
84 :
85 0 : return NS_ERROR_INVALID_ARG;
86 : }
87 : };
88 :
89 : template<class T>
90 : const nsCOMPtr<T>
91 9 : nsMaybeWeakPtr<T>::GetValue() const
92 : {
93 9 : if (!mPtr) {
94 0 : return nullptr;
95 : }
96 :
97 : nsresult rv;
98 18 : nsCOMPtr<T> ref = do_QueryInterface(mPtr, &rv);
99 9 : if (NS_SUCCEEDED(rv)) {
100 0 : return ref;
101 : }
102 :
103 18 : nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(mPtr);
104 9 : if (weakRef) {
105 9 : ref = do_QueryReferent(weakRef, &rv);
106 9 : if (NS_SUCCEEDED(rv)) {
107 9 : return ref;
108 : }
109 : }
110 :
111 0 : return nullptr;
112 : }
113 :
114 : template <typename T>
115 : inline void
116 0 : ImplCycleCollectionUnlink(nsMaybeWeakPtrArray<T>& aField)
117 : {
118 0 : aField.Clear();
119 0 : }
120 :
121 : template <typename E>
122 : inline void
123 0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
124 : nsMaybeWeakPtrArray<E>& aField,
125 : const char* aName,
126 : uint32_t aFlags = 0)
127 : {
128 0 : aFlags |= CycleCollectionEdgeNameArrayFlag;
129 0 : size_t length = aField.Length();
130 0 : for (size_t i = 0; i < length; ++i) {
131 0 : CycleCollectionNoteChild(aCallback, aField[i].GetRawValue(), aName, aFlags);
132 : }
133 0 : }
134 :
135 : // Call a method on each element in the array, but only if the element is
136 : // non-null.
137 :
138 : #define ENUMERATE_WEAKARRAY(array, type, method) \
139 : for (uint32_t array_idx = 0; array_idx < array.Length(); ++array_idx) { \
140 : const nsCOMPtr<type> &e = array.ElementAt(array_idx).GetValue(); \
141 : if (e) \
142 : e->method; \
143 : }
144 :
145 : #endif
|