/work/obj-fuzz/dist/include/nsAgg.h
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #ifndef nsAgg_h___ |
8 | | #define nsAgg_h___ |
9 | | |
10 | | #include "nsISupports.h" |
11 | | #include "nsCycleCollectionParticipant.h" |
12 | | |
13 | | |
14 | | //////////////////////////////////////////////////////////////////////////////// |
15 | | |
16 | | // Put NS_DECL_AGGREGATED or NS_DECL_CYCLE_COLLECTING_AGGREGATED in your class's |
17 | | // declaration. |
18 | | #define NS_DECL_AGGREGATED \ |
19 | | NS_DECL_ISUPPORTS \ |
20 | | NS_DECL_AGGREGATED_HELPER |
21 | | |
22 | | #define NS_DECL_CYCLE_COLLECTING_AGGREGATED \ |
23 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS \ |
24 | | NS_DECL_AGGREGATED_HELPER |
25 | | |
26 | | #define NS_DECL_AGGREGATED_HELPER \ |
27 | | public: \ |
28 | | \ |
29 | | /** \ |
30 | | * Returns the nsISupports pointer of the inner object (aka the \ |
31 | | * aggregatee). This pointer is really only useful to the outer object \ |
32 | | * (aka the aggregator), which can use it to hold on to the inner \ |
33 | | * object. Anything else wants the nsISupports pointer of the outer \ |
34 | | * object (gotten by QI'ing inner or outer to nsISupports). This method \ |
35 | | * returns a non-addrefed pointer. \ |
36 | | * @return the nsISupports pointer of the inner object \ |
37 | | */ \ |
38 | 3 | nsISupports* InnerObject(void) { return &fAggregated; } \ Unexecuted instantiation: nsProperties::InnerObject() mozilla::net::nsLoadGroup::InnerObject() Line | Count | Source | 38 | 3 | nsISupports* InnerObject(void) { return &fAggregated; } \ |
|
39 | | \ |
40 | | /** \ |
41 | | * Returns true if this object is part of an aggregated object. \ |
42 | | */ \ |
43 | 0 | bool IsPartOfAggregated(void) { return fOuter != InnerObject(); } \ Unexecuted instantiation: nsProperties::IsPartOfAggregated() Unexecuted instantiation: mozilla::net::nsLoadGroup::IsPartOfAggregated() |
44 | | \ |
45 | | private: \ |
46 | | \ |
47 | | /* You must implement this operation instead of the nsISupports */ \ |
48 | | /* methods. */ \ |
49 | | nsresult \ |
50 | | AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr); \ |
51 | | \ |
52 | | class Internal : public nsISupports { \ |
53 | | public: \ |
54 | | \ |
55 | 3 | Internal() {} \ Unexecuted instantiation: nsProperties::Internal::Internal() mozilla::net::nsLoadGroup::Internal::Internal() Line | Count | Source | 55 | 3 | Internal() {} \ |
|
56 | | \ |
57 | | NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr) \ |
58 | | override; \ |
59 | | NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override; \ |
60 | | NS_IMETHOD_(MozExternalRefCountType) Release(void) override; \ |
61 | | \ |
62 | | NS_DECL_OWNINGTHREAD \ |
63 | | }; \ |
64 | | \ |
65 | | friend class Internal; \ |
66 | | \ |
67 | | nsISupports* MOZ_UNSAFE_REF("fOuter can either point to fAggregated " \ |
68 | | "or to an outer object, and the safety " \ |
69 | | "of this reference depends on the exact " \ |
70 | | "lifetime semantics of the AddRef/Release " \ |
71 | | "functions created by these macros.") \ |
72 | | fOuter; \ |
73 | | Internal fAggregated; \ |
74 | | \ |
75 | | public: \ |
76 | | |
77 | | #define NS_DECL_AGGREGATED_CYCLE_COLLECTION_CLASS(_class) \ |
78 | | class NS_CYCLE_COLLECTION_INNERCLASS \ |
79 | | : public nsXPCOMCycleCollectionParticipant \ |
80 | | { \ |
81 | | public: \ |
82 | | constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false) \ |
83 | | : nsXPCOMCycleCollectionParticipant(aSkip) {} \ |
84 | | \ |
85 | | NS_IMETHOD_(void) Unlink(void *p) override; \ |
86 | | NS_IMETHOD TraverseNative(void *p, nsCycleCollectionTraversalCallback &cb)\ |
87 | | override; \ |
88 | | NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(_class) \ |
89 | | NS_IMETHOD_(void) DeleteCycleCollectable(void* p) override \ |
90 | | { \ |
91 | | NS_CYCLE_COLLECTION_CLASSNAME(_class):: \ |
92 | | Downcast(static_cast<nsISupports*>(p))->DeleteCycleCollectable(); \ |
93 | | } \ |
94 | | static _class* Downcast(nsISupports* s) \ |
95 | | { \ |
96 | | return (_class*)((char*)(s) - offsetof(_class, fAggregated)); \ |
97 | | } \ |
98 | | static nsISupports* Upcast(_class *p) \ |
99 | | { \ |
100 | | return p->InnerObject(); \ |
101 | | } \ |
102 | | static nsXPCOMCycleCollectionParticipant* GetParticipant() \ |
103 | | { \ |
104 | | return &_class::NS_CYCLE_COLLECTION_INNERNAME; \ |
105 | | } \ |
106 | | }; \ |
107 | | NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class); \ |
108 | | static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; |
109 | | |
110 | | // Put this in your class's constructor: |
111 | | #define NS_INIT_AGGREGATED(outer) \ |
112 | 3 | do { \ |
113 | 3 | fOuter = outer ? outer : &fAggregated; \ |
114 | 3 | } while(0) |
115 | | |
116 | | |
117 | | // Put this in your class's implementation file: |
118 | | #define NS_IMPL_AGGREGATED(_class) \ |
119 | | \ |
120 | | NS_IMPL_AGGREGATED_HELPER(_class) \ |
121 | | \ |
122 | | NS_IMETHODIMP_(MozExternalRefCountType) \ |
123 | 9 | _class::Internal::AddRef(void) \ |
124 | 9 | { \ |
125 | 9 | _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \ |
126 | 9 | MOZ_ASSERT(int32_t(agg->mRefCnt) >= 0, "illegal refcnt"); \ |
127 | 9 | NS_ASSERT_OWNINGTHREAD(_class); \ |
128 | 9 | ++agg->mRefCnt; \ |
129 | 9 | NS_LOG_ADDREF(this, agg->mRefCnt, #_class, sizeof(*this)); \ |
130 | 9 | return agg->mRefCnt; \ |
131 | 9 | } \ Unexecuted instantiation: nsProperties::Internal::AddRef() mozilla::net::nsLoadGroup::Internal::AddRef() Line | Count | Source | 123 | 9 | _class::Internal::AddRef(void) \ | 124 | 9 | { \ | 125 | 9 | _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \ | 126 | 9 | MOZ_ASSERT(int32_t(agg->mRefCnt) >= 0, "illegal refcnt"); \ | 127 | 9 | NS_ASSERT_OWNINGTHREAD(_class); \ | 128 | 9 | ++agg->mRefCnt; \ | 129 | 9 | NS_LOG_ADDREF(this, agg->mRefCnt, #_class, sizeof(*this)); \ | 130 | 9 | return agg->mRefCnt; \ | 131 | 9 | } \ |
|
132 | | \ |
133 | | NS_IMETHODIMP_(MozExternalRefCountType) \ |
134 | 6 | _class::Internal::Release(void) \ |
135 | 6 | { \ |
136 | 6 | _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \ |
137 | 6 | MOZ_ASSERT(int32_t(agg->mRefCnt) > 0, "dup release"); \ |
138 | 6 | NS_ASSERT_OWNINGTHREAD(_class); \ |
139 | 6 | --agg->mRefCnt; \ |
140 | 6 | NS_LOG_RELEASE(this, agg->mRefCnt, #_class); \ |
141 | 6 | if (agg->mRefCnt == 0) { \ |
142 | 0 | agg->mRefCnt = 1; /* stabilize */ \ |
143 | 0 | delete agg; \ |
144 | 0 | return 0; \ |
145 | 0 | } \ |
146 | 6 | return agg->mRefCnt; \ |
147 | 6 | } \ Unexecuted instantiation: nsProperties::Internal::Release() mozilla::net::nsLoadGroup::Internal::Release() Line | Count | Source | 134 | 6 | _class::Internal::Release(void) \ | 135 | 6 | { \ | 136 | 6 | _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \ | 137 | 6 | MOZ_ASSERT(int32_t(agg->mRefCnt) > 0, "dup release"); \ | 138 | 6 | NS_ASSERT_OWNINGTHREAD(_class); \ | 139 | 6 | --agg->mRefCnt; \ | 140 | 6 | NS_LOG_RELEASE(this, agg->mRefCnt, #_class); \ | 141 | 6 | if (agg->mRefCnt == 0) { \ | 142 | 0 | agg->mRefCnt = 1; /* stabilize */ \ | 143 | 0 | delete agg; \ | 144 | 0 | return 0; \ | 145 | 0 | } \ | 146 | 6 | return agg->mRefCnt; \ | 147 | 6 | } \ |
|
148 | | |
149 | | #define NS_IMPL_CYCLE_COLLECTING_AGGREGATED(_class) \ |
150 | | \ |
151 | | NS_IMPL_AGGREGATED_HELPER(_class) \ |
152 | | \ |
153 | | NS_IMETHODIMP_(MozExternalRefCountType) \ |
154 | | _class::Internal::AddRef(void) \ |
155 | | { \ |
156 | | _class* agg = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Downcast(this); \ |
157 | | MOZ_ASSERT(int32_t(agg->mRefCnt) >= 0, "illegal refcnt"); \ |
158 | | NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class); \ |
159 | | nsrefcnt count = agg->mRefCnt.incr(this); \ |
160 | | NS_LOG_ADDREF(this, count, #_class, sizeof(*agg)); \ |
161 | | return count; \ |
162 | | } \ |
163 | | NS_IMETHODIMP_(MozExternalRefCountType) \ |
164 | | _class::Internal::Release(void) \ |
165 | | { \ |
166 | | _class* agg = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Downcast(this); \ |
167 | | MOZ_ASSERT(int32_t(agg->mRefCnt) > 0, "dup release"); \ |
168 | | NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class); \ |
169 | | nsrefcnt count = agg->mRefCnt.decr(this); \ |
170 | | NS_LOG_RELEASE(this, count, #_class); \ |
171 | | return count; \ |
172 | | } \ |
173 | | NS_IMETHODIMP_(void) \ |
174 | | _class::DeleteCycleCollectable(void) \ |
175 | | { \ |
176 | | delete this; \ |
177 | | } |
178 | | |
179 | | #define NS_IMPL_AGGREGATED_HELPER(_class) \ |
180 | | NS_IMETHODIMP \ |
181 | 0 | _class::QueryInterface(const nsIID& aIID, void** aInstancePtr) \ |
182 | 0 | { \ |
183 | 0 | return fOuter->QueryInterface(aIID, aInstancePtr); \ |
184 | 0 | } \ Unexecuted instantiation: nsProperties::QueryInterface(nsID const&, void**) Unexecuted instantiation: mozilla::net::nsLoadGroup::QueryInterface(nsID const&, void**) |
185 | | \ |
186 | | NS_IMETHODIMP_(MozExternalRefCountType) \ |
187 | 6 | _class::AddRef(void) \ |
188 | 6 | { \ |
189 | 6 | return fOuter->AddRef(); \ |
190 | 6 | } \ Unexecuted instantiation: nsProperties::AddRef() mozilla::net::nsLoadGroup::AddRef() Line | Count | Source | 187 | 6 | _class::AddRef(void) \ | 188 | 6 | { \ | 189 | 6 | return fOuter->AddRef(); \ | 190 | 6 | } \ |
|
191 | | \ |
192 | | NS_IMETHODIMP_(MozExternalRefCountType) \ |
193 | 3 | _class::Release(void) \ |
194 | 3 | { \ |
195 | 3 | return fOuter->Release(); \ |
196 | 3 | } \ Unexecuted instantiation: nsProperties::Release() mozilla::net::nsLoadGroup::Release() Line | Count | Source | 193 | 3 | _class::Release(void) \ | 194 | 3 | { \ | 195 | 3 | return fOuter->Release(); \ | 196 | 3 | } \ |
|
197 | | \ |
198 | | NS_IMETHODIMP \ |
199 | 3 | _class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr) \ |
200 | 3 | { \ |
201 | 3 | _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \ |
202 | 3 | return agg->AggregatedQueryInterface(aIID, aInstancePtr); \ |
203 | 3 | } \ Unexecuted instantiation: nsProperties::Internal::QueryInterface(nsID const&, void**) mozilla::net::nsLoadGroup::Internal::QueryInterface(nsID const&, void**) Line | Count | Source | 199 | 3 | _class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr) \ | 200 | 3 | { \ | 201 | 3 | _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \ | 202 | 3 | return agg->AggregatedQueryInterface(aIID, aInstancePtr); \ | 203 | 3 | } \ |
|
204 | | |
205 | | /** |
206 | | * To make aggregated objects participate in cycle collection we need to enable |
207 | | * the outer object (aggregator) to traverse/unlink the objects held by the |
208 | | * inner object (the aggregatee). We can't just make the inner object QI'able to |
209 | | * NS_CYCLECOLLECTIONPARTICIPANT_IID, we don't want to return the inner object's |
210 | | * nsCycleCollectionParticipant for the outer object (which will happen if the |
211 | | * outer object doesn't participate in cycle collection itself). |
212 | | * NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID enables the outer object to get |
213 | | * the inner objects nsCycleCollectionParticipant. |
214 | | * |
215 | | * There are three cases: |
216 | | * - No aggregation |
217 | | * QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will return the inner |
218 | | * object's nsCycleCollectionParticipant. |
219 | | * |
220 | | * - Aggregation and outer object does not participate in cycle collection |
221 | | * QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will not return anything. |
222 | | * |
223 | | * - Aggregation and outer object does participate in cycle collection |
224 | | * QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will return the outer |
225 | | * object's nsCycleCollectionParticipant. The outer object's |
226 | | * nsCycleCollectionParticipant can then QI the inner object to |
227 | | * NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID to get the inner object's |
228 | | * nsCycleCollectionParticipant, which it can use to traverse/unlink the |
229 | | * objects reachable from the inner object. |
230 | | */ |
231 | | #define NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID \ |
232 | | { \ |
233 | | 0x32889b7e, \ |
234 | | 0xe4fe, \ |
235 | | 0x43f4, \ |
236 | | { 0x85, 0x31, 0xb5, 0x28, 0x23, 0xa2, 0xe9, 0xfc } \ |
237 | | } |
238 | | |
239 | | /** |
240 | | * Just holds the IID so NS_GET_IID works. |
241 | | */ |
242 | | class nsAggregatedCycleCollectionParticipant |
243 | | { |
244 | | public: |
245 | | NS_DECLARE_STATIC_IID_ACCESSOR(NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID) |
246 | | }; |
247 | | |
248 | | NS_DEFINE_STATIC_IID_ACCESSOR(nsAggregatedCycleCollectionParticipant, |
249 | | NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID) |
250 | | |
251 | | // for use with QI macros in nsISupportsUtils.h: |
252 | | |
253 | | #define NS_INTERFACE_MAP_BEGIN_AGGREGATED(_class) \ |
254 | 3 | NS_IMPL_AGGREGATED_QUERY_HEAD(_class) |
255 | | |
256 | | #define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \ |
257 | | if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \ |
258 | | *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \ |
259 | | return NS_OK; \ |
260 | | } else |
261 | | |
262 | | #define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class) \ |
263 | | NS_IMPL_QUERY_CYCLE_COLLECTION(_class) |
264 | | |
265 | | #define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) \ |
266 | | if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ) { \ |
267 | | *aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \ |
268 | | return NS_OK; \ |
269 | | } else |
270 | | |
271 | | #define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class) \ |
272 | | NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) |
273 | | |
274 | | #define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION_AGGREGATED(_class) \ |
275 | | NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class) \ |
276 | | NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class) |
277 | | |
278 | | #define NS_IMPL_AGGREGATED_QUERY_HEAD(_class) \ |
279 | | nsresult \ |
280 | 3 | _class::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr) \ |
281 | 3 | { \ |
282 | 3 | NS_ASSERTION(aInstancePtr, \ |
283 | 3 | "AggregatedQueryInterface requires a non-NULL result ptr!"); \ |
284 | 3 | if ( !aInstancePtr ) \ |
285 | 3 | return NS_ERROR_NULL_POINTER; \ |
286 | 3 | nsISupports* foundInterface; \ |
287 | 3 | if ( aIID.Equals(NS_GET_IID(nsISupports)) ) \ |
288 | 3 | foundInterface = InnerObject(); \ |
289 | 3 | else |
290 | | |
291 | | #define NS_IMPL_AGGREGATED_QUERY_CYCLE_COLLECTION(_class) \ |
292 | | if (aIID.Equals(IsPartOfAggregated() ? \ |
293 | | NS_GET_IID(nsCycleCollectionParticipant) : \ |
294 | | NS_GET_IID(nsAggregatedCycleCollectionParticipant))) \ |
295 | | foundInterface = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \ |
296 | | else |
297 | | |
298 | | #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_AGGREGATED(_class) \ |
299 | | NS_IMETHODIMP \ |
300 | | NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraverseNative \ |
301 | | (void *p, nsCycleCollectionTraversalCallback &cb) \ |
302 | | { \ |
303 | | nsISupports *s = static_cast<nsISupports*>(p); \ |
304 | | MOZ_ASSERT(CheckForRightISupports(s), \ |
305 | | "not the nsISupports pointer we expect"); \ |
306 | | _class *tmp = static_cast<_class*>(Downcast(s)); \ |
307 | | if (!tmp->IsPartOfAggregated()) \ |
308 | | NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get()) |
309 | | |
310 | | #define NS_GENERIC_AGGREGATED_CONSTRUCTOR(_InstanceClass) \ |
311 | | static nsresult \ |
312 | | _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ |
313 | | void **aResult) \ |
314 | | { \ |
315 | | *aResult = nullptr; \ |
316 | | if (NS_WARN_IF(aOuter && !aIID.Equals(NS_GET_IID(nsISupports)))) \ |
317 | | return NS_ERROR_INVALID_ARG; \ |
318 | | \ |
319 | | RefPtr<_InstanceClass> inst = new _InstanceClass(aOuter); \ |
320 | | if (!inst) { \ |
321 | | return NS_ERROR_OUT_OF_MEMORY; \ |
322 | | } \ |
323 | | \ |
324 | | nsISupports* inner = inst->InnerObject(); \ |
325 | | nsresult rv = inner->QueryInterface(aIID, aResult); \ |
326 | | \ |
327 | | return rv; \ |
328 | | } \ |
329 | | |
330 | | #define NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(_InstanceClass, _InitMethod) \ |
331 | | static nsresult \ |
332 | | _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ |
333 | 3 | void **aResult) \ |
334 | 3 | { \ |
335 | 3 | *aResult = nullptr; \ |
336 | 3 | if (NS_WARN_IF(aOuter && !aIID.Equals(NS_GET_IID(nsISupports)))) \ |
337 | 3 | return NS_ERROR_INVALID_ARG; \ |
338 | 3 | \ |
339 | 3 | RefPtr<_InstanceClass> inst = new _InstanceClass(aOuter); \ |
340 | 3 | if (!inst) { \ |
341 | 0 | return NS_ERROR_OUT_OF_MEMORY; \ |
342 | 0 | } \ |
343 | 3 | \ |
344 | 3 | nsISupports* inner = inst->InnerObject(); \ |
345 | 3 | NS_ADDREF(inner); \ |
346 | 3 | nsresult rv = inst->_InitMethod(); \ |
347 | 3 | if (NS_SUCCEEDED(rv)) { \ |
348 | 3 | rv = inner->QueryInterface(aIID, aResult); \ |
349 | 3 | } \ |
350 | 3 | NS_RELEASE(inner); \ |
351 | 3 | \ |
352 | 3 | return rv; \ |
353 | 3 | } \ |
354 | | |
355 | | #endif /* nsAgg_h___ */ |