Line data Source code
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 nsCOMPtr_h___
8 : #define nsCOMPtr_h___
9 :
10 : /*
11 : * Having problems?
12 : *
13 : * See the User Manual at:
14 : * http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
15 : *
16 : *
17 : * nsCOMPtr
18 : * better than a raw pointer
19 : * for owning objects
20 : * -- scc
21 : */
22 :
23 : #include "mozilla/AlreadyAddRefed.h"
24 : #include "mozilla/Assertions.h"
25 : #include "mozilla/Attributes.h"
26 : #include "mozilla/Move.h"
27 : #include "mozilla/TypeTraits.h"
28 :
29 : #include "nsDebug.h" // for |NS_ASSERTION|
30 : #include "nsISupportsUtils.h" // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
31 : #include "mozilla/RefPtr.h"
32 :
33 : #include "nsCycleCollectionNoteChild.h"
34 :
35 :
36 : /*
37 : * WARNING: This file defines several macros for internal use only. These
38 : * macros begin with the prefix |NSCAP_|. Do not use these macros in your own
39 : * code. They are for internal use only for cross-platform compatibility, and
40 : * are subject to change without notice.
41 : */
42 :
43 :
44 : #ifdef _MSC_VER
45 : // Under VC++, we win by inlining StartAssignment.
46 : #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
47 :
48 : // Also under VC++, at the highest warning level, we are overwhelmed with
49 : // warnings about (unused) inline functions being removed. This is to be
50 : // expected with templates, so we disable the warning.
51 : #pragma warning( disable: 4514 )
52 : #endif
53 :
54 : #define NSCAP_FEATURE_USE_BASE
55 :
56 : #ifdef DEBUG
57 : #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
58 : #undef NSCAP_FEATURE_USE_BASE
59 : #endif
60 :
61 : #ifdef __GNUC__
62 : // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
63 : // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
64 : // don't reorder instructions based on aliasing assumptions for
65 : // this variable. Fortunately, gcc versions < 3.3 do not do any
66 : // optimizations that break nsCOMPtr.
67 :
68 : #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
69 : #else
70 : #define NS_MAY_ALIAS_PTR(t) t*
71 : #endif
72 :
73 : #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
74 : #define NSCAP_FEATURE_USE_BASE
75 : #endif
76 :
77 : /*
78 : * The following three macros (NSCAP_ADDREF, NSCAP_RELEASE, and
79 : * NSCAP_LOG_ASSIGNMENT) allow external clients the ability to add logging or
80 : * other interesting debug facilities. In fact, if you want |nsCOMPtr| to
81 : * participate in the standard logging facility, you provide
82 : * (e.g., in "nsISupportsImpl.h") suitable definitions
83 : *
84 : * #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
85 : * #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
86 : */
87 :
88 : #ifndef NSCAP_ADDREF
89 : #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
90 : #endif
91 :
92 : #ifndef NSCAP_RELEASE
93 : #define NSCAP_RELEASE(this, ptr) (ptr)->Release()
94 : #endif
95 :
96 : // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
97 : #ifdef NSCAP_LOG_ASSIGNMENT
98 : // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we
99 : // know to instantiate |~nsGetterAddRefs| in turn to note the external
100 : // assignment into the |nsCOMPtr|.
101 : #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
102 : #else
103 : // ...otherwise, just strip it out of the code
104 : #define NSCAP_LOG_ASSIGNMENT(this, ptr)
105 : #endif
106 :
107 : #ifndef NSCAP_LOG_RELEASE
108 : #define NSCAP_LOG_RELEASE(this, ptr)
109 : #endif
110 :
111 : namespace mozilla {
112 : template<class T> class OwningNonNull;
113 : } // namespace mozilla
114 :
115 : template<class T>
116 : inline already_AddRefed<T>
117 100990 : dont_AddRef(T* aRawPtr)
118 : {
119 100990 : return already_AddRefed<T>(aRawPtr);
120 : }
121 :
122 : template<class T>
123 : inline already_AddRefed<T>&&
124 : dont_AddRef(already_AddRefed<T>&& aAlreadyAddRefedPtr)
125 : {
126 : return mozilla::Move(aAlreadyAddRefedPtr);
127 : }
128 :
129 :
130 : /*
131 : * An nsCOMPtr_helper transforms commonly called getters into typesafe forms
132 : * that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
133 : * Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
134 : *
135 : * Here are the rules for a helper:
136 : * - it implements |operator()| to produce an interface pointer
137 : * - (except for its name) |operator()| is a valid [XP]COM `getter'
138 : * - the interface pointer that it returns is already |AddRef()|ed (as from
139 : * any good getter)
140 : * - it matches the type requested with the supplied |nsIID| argument
141 : * - its constructor provides an optional |nsresult*| that |operator()| can
142 : * fill in with an error when it is executed
143 : *
144 : * See |class nsGetInterface| for an example.
145 : */
146 36629 : class MOZ_STACK_CLASS nsCOMPtr_helper
147 : {
148 : public:
149 : virtual nsresult NS_FASTCALL operator()(const nsIID&, void**) const = 0;
150 : };
151 :
152 : /*
153 : * nsQueryInterface could have been implemented as an nsCOMPtr_helper to avoid
154 : * adding specialized machinery in nsCOMPtr, but do_QueryInterface is called
155 : * often enough that the codesize savings are big enough to warrant the
156 : * specialcasing.
157 : */
158 : class MOZ_STACK_CLASS nsQueryInterface final
159 : {
160 : public:
161 : explicit
162 482875 : nsQueryInterface(nsISupports* aRawPtr) : mRawPtr(aRawPtr) {}
163 :
164 : nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
165 :
166 : private:
167 : nsISupports* MOZ_OWNING_REF mRawPtr;
168 : };
169 :
170 : class nsQueryInterfaceWithError final
171 : {
172 : public:
173 6384 : nsQueryInterfaceWithError(nsISupports* aRawPtr, nsresult* aError)
174 6384 : : mRawPtr(aRawPtr)
175 6384 : , mErrorPtr(aError)
176 : {
177 6384 : }
178 :
179 : nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
180 :
181 : private:
182 : nsISupports* MOZ_OWNING_REF mRawPtr;
183 : nsresult* mErrorPtr;
184 : };
185 :
186 : inline nsQueryInterface
187 479174 : do_QueryInterface(nsISupports* aRawPtr)
188 : {
189 479174 : return nsQueryInterface(aRawPtr);
190 : }
191 :
192 : inline nsQueryInterfaceWithError
193 6384 : do_QueryInterface(nsISupports* aRawPtr, nsresult* aError)
194 : {
195 6384 : return nsQueryInterfaceWithError(aRawPtr, aError);
196 : }
197 :
198 : template<class T>
199 : inline void
200 : do_QueryInterface(already_AddRefed<T>&)
201 : {
202 : // This signature exists solely to _stop_ you from doing the bad thing.
203 : // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
204 : // someone else is an automatic leak. See bug 8221.
205 : }
206 :
207 : template<class T>
208 : inline void
209 : do_QueryInterface(already_AddRefed<T>&, nsresult*)
210 : {
211 : // This signature exists solely to _stop_ you from doing the bad thing.
212 : // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
213 : // someone else is an automatic leak. See bug 8221.
214 : }
215 :
216 :
217 : ////////////////////////////////////////////////////////////////////////////
218 : // Using servicemanager with COMPtrs
219 : class nsGetServiceByCID final
220 : {
221 : public:
222 15 : explicit nsGetServiceByCID(const nsCID& aCID) : mCID(aCID) {}
223 :
224 : nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
225 :
226 : private:
227 : const nsCID& mCID;
228 : };
229 :
230 : class nsGetServiceByCIDWithError final
231 : {
232 : public:
233 77 : nsGetServiceByCIDWithError(const nsCID& aCID, nsresult* aErrorPtr)
234 77 : : mCID(aCID)
235 77 : , mErrorPtr(aErrorPtr)
236 : {
237 77 : }
238 :
239 : nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
240 :
241 : private:
242 : const nsCID& mCID;
243 : nsresult* mErrorPtr;
244 : };
245 :
246 : class nsGetServiceByContractID final
247 : {
248 : public:
249 3701 : explicit nsGetServiceByContractID(const char* aContractID)
250 3701 : : mContractID(aContractID)
251 : {
252 3701 : }
253 :
254 : nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
255 :
256 : private:
257 : const char* mContractID;
258 : };
259 :
260 : class nsGetServiceByContractIDWithError final
261 : {
262 : public:
263 555 : nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
264 555 : : mContractID(aContractID)
265 555 : , mErrorPtr(aErrorPtr)
266 : {
267 555 : }
268 :
269 : nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
270 :
271 : private:
272 : const char* mContractID;
273 : nsresult* mErrorPtr;
274 : };
275 :
276 : /**
277 : * Factors implementation for all template versions of nsCOMPtr.
278 : *
279 : * Here's the way people normally do things like this:
280 : *
281 : * template<class T> class Foo { ... };
282 : * template<> class Foo<void*> { ... };
283 : * template<class T> class Foo<T*> : private Foo<void*> { ... };
284 : */
285 : class nsCOMPtr_base
286 : {
287 : public:
288 43296 : explicit nsCOMPtr_base(nsISupports* aRawPtr = nullptr) : mRawPtr(aRawPtr) {}
289 :
290 27122 : NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base()
291 27122 : {
292 27122 : NSCAP_LOG_RELEASE(this, mRawPtr);
293 27122 : if (mRawPtr) {
294 7853 : NSCAP_RELEASE(this, mRawPtr);
295 : }
296 27122 : }
297 :
298 : void NS_FASTCALL
299 : assign_with_AddRef(nsISupports*);
300 : void NS_FASTCALL
301 : assign_from_qi(const nsQueryInterface, const nsIID&);
302 : void NS_FASTCALL
303 : assign_from_qi_with_error(const nsQueryInterfaceWithError&, const nsIID&);
304 : void NS_FASTCALL
305 : assign_from_gs_cid(const nsGetServiceByCID, const nsIID&);
306 : void NS_FASTCALL
307 : assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError&, const nsIID&);
308 : void NS_FASTCALL
309 : assign_from_gs_contractid(const nsGetServiceByContractID, const nsIID&);
310 : void NS_FASTCALL
311 : assign_from_gs_contractid_with_error(const nsGetServiceByContractIDWithError&,
312 : const nsIID&);
313 : void NS_FASTCALL
314 : assign_from_helper(const nsCOMPtr_helper&, const nsIID&);
315 : void** NS_FASTCALL
316 : begin_assignment();
317 :
318 : protected:
319 : NS_MAY_ALIAS_PTR(nsISupports) MOZ_OWNING_REF mRawPtr;
320 :
321 30136 : void assign_assuming_AddRef(nsISupports* aNewPtr)
322 : {
323 : // |AddRef()|ing the new value (before entering this function) before
324 : // |Release()|ing the old lets us safely ignore the self-assignment case.
325 : // We must, however, be careful only to |Release()| _after_ doing the
326 : // assignment, in case the |Release()| leads to our _own_ destruction,
327 : // which would, in turn, cause an incorrect second |Release()| of our old
328 : // pointer. Thank <waterson@netscape.com> for discovering this.
329 30136 : nsISupports* oldPtr = mRawPtr;
330 30136 : mRawPtr = aNewPtr;
331 30136 : NSCAP_LOG_ASSIGNMENT(this, aNewPtr);
332 30136 : NSCAP_LOG_RELEASE(this, oldPtr);
333 30136 : if (oldPtr) {
334 2549 : NSCAP_RELEASE(this, oldPtr);
335 : }
336 30136 : }
337 : };
338 :
339 : // template<class T> class nsGetterAddRefs;
340 :
341 : // Helper for assert_validity method
342 : template<class T>
343 : char (&TestForIID(decltype(&NS_GET_TEMPLATE_IID(T))))[2];
344 : template<class T>
345 : char TestForIID(...);
346 :
347 : template<class T>
348 : class nsCOMPtr final
349 : #ifdef NSCAP_FEATURE_USE_BASE
350 : : private nsCOMPtr_base
351 : #endif
352 : {
353 :
354 : #ifdef NSCAP_FEATURE_USE_BASE
355 : #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
356 : #else
357 : #define NSCAP_CTOR_BASE(x) mRawPtr(x)
358 :
359 : private:
360 : void assign_with_AddRef(nsISupports*);
361 : void assign_from_qi(const nsQueryInterface, const nsIID&);
362 : void assign_from_qi_with_error(const nsQueryInterfaceWithError&, const nsIID&);
363 : void assign_from_gs_cid(const nsGetServiceByCID, const nsIID&);
364 : void assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError&,
365 : const nsIID&);
366 : void assign_from_gs_contractid(const nsGetServiceByContractID, const nsIID&);
367 : void assign_from_gs_contractid_with_error(
368 : const nsGetServiceByContractIDWithError&, const nsIID&);
369 : void assign_from_helper(const nsCOMPtr_helper&, const nsIID&);
370 : void** begin_assignment();
371 :
372 812111 : void assign_assuming_AddRef(T* aNewPtr)
373 : {
374 812111 : T* oldPtr = mRawPtr;
375 812111 : mRawPtr = aNewPtr;
376 812111 : NSCAP_LOG_ASSIGNMENT(this, aNewPtr);
377 812113 : NSCAP_LOG_RELEASE(this, oldPtr);
378 812113 : if (oldPtr) {
379 33767 : NSCAP_RELEASE(this, oldPtr);
380 : }
381 812113 : }
382 :
383 : private:
384 : T* MOZ_OWNING_REF mRawPtr;
385 : #endif
386 :
387 1165866 : void assert_validity()
388 : {
389 : static_assert(1 < sizeof(TestForIID<T>(nullptr)), "nsCOMPtr only works "
390 : "for types with IIDs. Either use RefPtr; add an IID to "
391 : "your type with NS_DECLARE_STATIC_IID_ACCESSOR/"
392 : "NS_DEFINE_STATIC_IID_ACCESSOR; or make the nsCOMPtr point "
393 : "to a base class with an IID.");
394 1165866 : }
395 :
396 : public:
397 : typedef T element_type;
398 :
399 : #ifndef NSCAP_FEATURE_USE_BASE
400 1071326 : ~nsCOMPtr()
401 : {
402 1071326 : NSCAP_LOG_RELEASE(this, mRawPtr);
403 1071344 : if (mRawPtr) {
404 663623 : NSCAP_RELEASE(this, mRawPtr);
405 : }
406 1071348 : }
407 : #endif
408 :
409 : #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
410 699973 : void Assert_NoQueryNeeded()
411 : {
412 699973 : if (mRawPtr) {
413 766420 : nsCOMPtr<T> query_result(do_QueryInterface(mRawPtr));
414 383213 : NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
415 : }
416 699981 : }
417 :
418 : #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
419 : #else
420 : #define NSCAP_ASSERT_NO_QUERY_NEEDED()
421 : #endif
422 :
423 :
424 : // Constructors
425 :
426 304899 : nsCOMPtr()
427 304899 : : NSCAP_CTOR_BASE(nullptr)
428 : {
429 304899 : assert_validity();
430 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
431 304899 : }
432 :
433 36180 : MOZ_IMPLICIT nsCOMPtr(decltype(nullptr))
434 36180 : : NSCAP_CTOR_BASE(nullptr)
435 : {
436 36180 : assert_validity();
437 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
438 36180 : }
439 :
440 19402 : nsCOMPtr(const nsCOMPtr<T>& aSmartPtr)
441 19402 : : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
442 : {
443 19402 : assert_validity();
444 19402 : if (mRawPtr) {
445 13221 : NSCAP_ADDREF(this, mRawPtr);
446 : }
447 19402 : NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
448 19402 : }
449 :
450 634 : nsCOMPtr(nsCOMPtr<T>&& aSmartPtr)
451 634 : : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
452 : {
453 634 : assert_validity();
454 634 : aSmartPtr.mRawPtr = nullptr;
455 634 : NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
456 634 : NSCAP_ASSERT_NO_QUERY_NEEDED();
457 634 : }
458 :
459 272338 : MOZ_IMPLICIT nsCOMPtr(T* aRawPtr)
460 272338 : : NSCAP_CTOR_BASE(aRawPtr)
461 : {
462 272338 : assert_validity();
463 272338 : if (mRawPtr) {
464 129906 : NSCAP_ADDREF(this, mRawPtr);
465 : }
466 272338 : NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
467 272338 : NSCAP_ASSERT_NO_QUERY_NEEDED();
468 272337 : }
469 :
470 4622 : MOZ_IMPLICIT nsCOMPtr(already_AddRefed<T>& aSmartPtr)
471 4622 : : NSCAP_CTOR_BASE(aSmartPtr.take())
472 : {
473 4622 : assert_validity();
474 4622 : NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
475 4622 : NSCAP_ASSERT_NO_QUERY_NEEDED();
476 4621 : }
477 :
478 : // Construct from |otherComPtr.forget()|.
479 56155 : MOZ_IMPLICIT nsCOMPtr(already_AddRefed<T>&& aSmartPtr)
480 56155 : : NSCAP_CTOR_BASE(aSmartPtr.take())
481 : {
482 56155 : assert_validity();
483 56155 : NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
484 56155 : NSCAP_ASSERT_NO_QUERY_NEEDED();
485 56157 : }
486 :
487 : // Construct from |already_AddRefed|.
488 : template<typename U>
489 2 : MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>& aSmartPtr)
490 2 : : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
491 : {
492 2 : assert_validity();
493 : // But make sure that U actually inherits from T.
494 : static_assert(mozilla::IsBaseOf<T, U>::value,
495 : "U is not a subclass of T");
496 2 : NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
497 2 : NSCAP_ASSERT_NO_QUERY_NEEDED();
498 2 : }
499 :
500 : // Construct from |otherComPtr.forget()|.
501 : template<typename U>
502 3076 : MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>&& aSmartPtr)
503 3076 : : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
504 : {
505 3076 : assert_validity();
506 : // But make sure that U actually inherits from T.
507 : static_assert(mozilla::IsBaseOf<T, U>::value,
508 : "U is not a subclass of T");
509 3076 : NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
510 3076 : NSCAP_ASSERT_NO_QUERY_NEEDED();
511 3076 : }
512 :
513 : // Construct from |do_QueryInterface(expr)|.
514 453891 : MOZ_IMPLICIT nsCOMPtr(const nsQueryInterface aQI)
515 453891 : : NSCAP_CTOR_BASE(nullptr)
516 : {
517 453891 : assert_validity();
518 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
519 453890 : assign_from_qi(aQI, NS_GET_TEMPLATE_IID(T));
520 453898 : }
521 :
522 : // Construct from |do_QueryInterface(expr, &rv)|.
523 3288 : MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceWithError& aQI)
524 3288 : : NSCAP_CTOR_BASE(nullptr)
525 : {
526 3288 : assert_validity();
527 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
528 3288 : assign_from_qi_with_error(aQI, NS_GET_TEMPLATE_IID(T));
529 3288 : }
530 :
531 : // Construct from |do_GetService(cid_expr)|.
532 11 : MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS)
533 11 : : NSCAP_CTOR_BASE(nullptr)
534 : {
535 11 : assert_validity();
536 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
537 11 : assign_from_gs_cid(aGS, NS_GET_TEMPLATE_IID(T));
538 11 : }
539 :
540 : // Construct from |do_GetService(cid_expr, &rv)|.
541 76 : MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS)
542 76 : : NSCAP_CTOR_BASE(nullptr)
543 : {
544 76 : assert_validity();
545 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
546 76 : assign_from_gs_cid_with_error(aGS, NS_GET_TEMPLATE_IID(T));
547 76 : }
548 :
549 : // Construct from |do_GetService(contractid_expr)|.
550 3186 : MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS)
551 3186 : : NSCAP_CTOR_BASE(nullptr)
552 : {
553 3186 : assert_validity();
554 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
555 3186 : assign_from_gs_contractid(aGS, NS_GET_TEMPLATE_IID(T));
556 3186 : }
557 :
558 : // Construct from |do_GetService(contractid_expr, &rv)|.
559 455 : MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS)
560 455 : : NSCAP_CTOR_BASE(nullptr)
561 : {
562 455 : assert_validity();
563 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
564 455 : assign_from_gs_contractid_with_error(aGS, NS_GET_TEMPLATE_IID(T));
565 455 : }
566 :
567 : // And finally, anything else we might need to construct from can exploit the
568 : // nsCOMPtr_helper facility.
569 7631 : MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper)
570 7631 : : NSCAP_CTOR_BASE(nullptr)
571 : {
572 7631 : assert_validity();
573 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
574 7631 : assign_from_helper(aHelper, NS_GET_TEMPLATE_IID(T));
575 7631 : NSCAP_ASSERT_NO_QUERY_NEEDED();
576 7631 : }
577 :
578 : // Defined in OwningNonNull.h
579 : template<class U>
580 : MOZ_IMPLICIT nsCOMPtr(const mozilla::OwningNonNull<U>& aOther);
581 :
582 :
583 : // Assignment operators
584 :
585 19223 : nsCOMPtr<T>& operator=(const nsCOMPtr<T>& aRhs)
586 : {
587 19223 : assign_with_AddRef(aRhs.mRawPtr);
588 19223 : return *this;
589 : }
590 :
591 132362 : nsCOMPtr<T>& operator=(T* aRhs)
592 : {
593 132362 : assign_with_AddRef(aRhs);
594 132362 : NSCAP_ASSERT_NO_QUERY_NEEDED();
595 132362 : return *this;
596 : }
597 :
598 35227 : nsCOMPtr<T>& operator=(decltype(nullptr))
599 : {
600 35227 : assign_assuming_AddRef(nullptr);
601 35227 : return *this;
602 : }
603 :
604 : // Assign from |already_AddRefed|.
605 : template<typename U>
606 43 : nsCOMPtr<T>& operator=(already_AddRefed<U>& aRhs)
607 : {
608 : // Make sure that U actually inherits from T
609 : static_assert(mozilla::IsBaseOf<T, U>::value,
610 : "U is not a subclass of T");
611 43 : assign_assuming_AddRef(static_cast<T*>(aRhs.take()));
612 43 : NSCAP_ASSERT_NO_QUERY_NEEDED();
613 43 : return *this;
614 : }
615 :
616 : // Assign from |otherComPtr.forget()|.
617 : template<typename U>
618 31693 : nsCOMPtr<T>& operator=(already_AddRefed<U>&& aRhs)
619 : {
620 : // Make sure that U actually inherits from T
621 : static_assert(mozilla::IsBaseOf<T, U>::value,
622 : "U is not a subclass of T");
623 31693 : assign_assuming_AddRef(static_cast<T*>(aRhs.take()));
624 31693 : NSCAP_ASSERT_NO_QUERY_NEEDED();
625 31693 : return *this;
626 : }
627 :
628 : // Assign from |do_QueryInterface(expr)|.
629 18611 : nsCOMPtr<T>& operator=(const nsQueryInterface aRhs)
630 : {
631 18611 : assign_from_qi(aRhs, NS_GET_TEMPLATE_IID(T));
632 18611 : return *this;
633 : }
634 :
635 : // Assign from |do_QueryInterface(expr, &rv)|.
636 3093 : nsCOMPtr<T>& operator=(const nsQueryInterfaceWithError& aRhs)
637 : {
638 3093 : assign_from_qi_with_error(aRhs, NS_GET_TEMPLATE_IID(T));
639 3093 : return *this;
640 : }
641 :
642 : // Assign from |do_GetService(cid_expr)|.
643 4 : nsCOMPtr<T>& operator=(const nsGetServiceByCID aRhs)
644 : {
645 4 : assign_from_gs_cid(aRhs, NS_GET_TEMPLATE_IID(T));
646 4 : return *this;
647 : }
648 :
649 : // Assign from |do_GetService(cid_expr, &rv)|.
650 1 : nsCOMPtr<T>& operator=(const nsGetServiceByCIDWithError& aRhs)
651 : {
652 1 : assign_from_gs_cid_with_error(aRhs, NS_GET_TEMPLATE_IID(T));
653 1 : return *this;
654 : }
655 :
656 : // Assign from |do_GetService(contractid_expr)|.
657 471 : nsCOMPtr<T>& operator=(const nsGetServiceByContractID aRhs)
658 : {
659 471 : assign_from_gs_contractid(aRhs, NS_GET_TEMPLATE_IID(T));
660 471 : return *this;
661 : }
662 :
663 : // Assign from |do_GetService(contractid_expr, &rv)|.
664 65 : nsCOMPtr<T>& operator=(const nsGetServiceByContractIDWithError& aRhs)
665 : {
666 65 : assign_from_gs_contractid_with_error(aRhs, NS_GET_TEMPLATE_IID(T));
667 65 : return *this;
668 : }
669 :
670 : // And finally, anything else we might need to assign from can exploit the
671 : // nsCOMPtr_helper facility.
672 907 : nsCOMPtr<T>& operator=(const nsCOMPtr_helper& aRhs)
673 : {
674 907 : assign_from_helper(aRhs, NS_GET_TEMPLATE_IID(T));
675 907 : NSCAP_ASSERT_NO_QUERY_NEEDED();
676 907 : return *this;
677 : }
678 :
679 : // Defined in OwningNonNull.h
680 : template<class U>
681 : nsCOMPtr<T>& operator=(const mozilla::OwningNonNull<U>& aOther);
682 :
683 : // Exchange ownership with |aRhs|; can save a pair of refcount operations.
684 4404 : void swap(nsCOMPtr<T>& aRhs)
685 : {
686 : #ifdef NSCAP_FEATURE_USE_BASE
687 : nsISupports* temp = aRhs.mRawPtr;
688 : #else
689 4404 : T* temp = aRhs.mRawPtr;
690 : #endif
691 4404 : NSCAP_LOG_ASSIGNMENT(&aRhs, mRawPtr);
692 4404 : NSCAP_LOG_ASSIGNMENT(this, temp);
693 4404 : NSCAP_LOG_RELEASE(this, mRawPtr);
694 4404 : NSCAP_LOG_RELEASE(&aRhs, temp);
695 4404 : aRhs.mRawPtr = mRawPtr;
696 4404 : mRawPtr = temp;
697 : // |aRhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
698 4404 : }
699 :
700 : // Exchange ownership with |aRhs|; can save a pair of refcount operations.
701 88656 : void swap(T*& aRhs)
702 : {
703 : #ifdef NSCAP_FEATURE_USE_BASE
704 : nsISupports* temp = aRhs;
705 : #else
706 88656 : T* temp = aRhs;
707 : #endif
708 88656 : NSCAP_LOG_ASSIGNMENT(this, temp);
709 88657 : NSCAP_LOG_RELEASE(this, mRawPtr);
710 88656 : aRhs = reinterpret_cast<T*>(mRawPtr);
711 88656 : mRawPtr = temp;
712 88656 : NSCAP_ASSERT_NO_QUERY_NEEDED();
713 88656 : }
714 :
715 :
716 : // Other pointer operators
717 :
718 : // Return the value of mRawPtr and null out mRawPtr. Useful for
719 : // already_AddRefed return values.
720 85520 : already_AddRefed<T> MOZ_MAY_CALL_AFTER_MUST_RETURN forget()
721 : {
722 85520 : T* temp = nullptr;
723 85520 : swap(temp);
724 85522 : return already_AddRefed<T>(temp);
725 : }
726 :
727 : // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
728 : // Useful to avoid unnecessary AddRef/Release pairs with "out" parameters
729 : // where aRhs bay be a T** or an I** where I is a base class of T.
730 : template<typename I>
731 26881 : void forget(I** aRhs)
732 : {
733 26881 : NS_ASSERTION(aRhs, "Null pointer passed to forget!");
734 26881 : NSCAP_LOG_RELEASE(this, mRawPtr);
735 26881 : *aRhs = get();
736 26881 : mRawPtr = nullptr;
737 26881 : }
738 :
739 : // Prefer the implicit conversion provided automatically by
740 : // |operator T*() const|. Use |get()| to resolve ambiguity or to get a
741 : // castable pointer.
742 2062604 : T* get() const { return reinterpret_cast<T*>(mRawPtr); }
743 :
744 : // Makes an nsCOMPtr act like its underlying raw pointer type whenever it is
745 : // used in a context where a raw pointer is expected. It is this operator
746 : // that makes an nsCOMPtr substitutable for a raw pointer.
747 : //
748 : // Prefer the implicit use of this operator to calling |get()|, except where
749 : // necessary to resolve ambiguity.
750 706438 : operator T*() const & { return get(); }
751 :
752 : // Don't allow implicit conversion of temporary nsCOMPtr to raw pointer,
753 : // because the refcount might be one and the pointer will immediately become
754 : // invalid.
755 : operator T*() const && = delete;
756 :
757 : // Needed to avoid the deleted operator above
758 2005054 : explicit operator bool() const { return !!mRawPtr; }
759 :
760 387392 : T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
761 : {
762 387392 : MOZ_ASSERT(mRawPtr != nullptr,
763 : "You can't dereference a NULL nsCOMPtr with operator->().");
764 387392 : return get();
765 : }
766 :
767 : // These are not intended to be used by clients. See |address_of| below.
768 74104 : nsCOMPtr<T>* get_address() { return this; }
769 : const nsCOMPtr<T>* get_address() const { return this; }
770 :
771 : public:
772 346 : T& operator*() const
773 : {
774 346 : MOZ_ASSERT(mRawPtr != nullptr,
775 : "You can't dereference a NULL nsCOMPtr with operator*().");
776 346 : return *get();
777 : }
778 :
779 101865 : T** StartAssignment()
780 : {
781 : #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
782 101865 : return reinterpret_cast<T**>(begin_assignment());
783 : #else
784 : assign_assuming_AddRef(nullptr);
785 : return reinterpret_cast<T**>(&mRawPtr);
786 : #endif
787 : }
788 : };
789 :
790 :
791 : /*
792 : * Specializing nsCOMPtr for nsISupports allows us to use nsCOMPtr<nsISupports>
793 : * the same way people use nsISupports* and void*, i.e., as a `catch-all'
794 : * pointing to any valid [XP]COM interface. Otherwise, an nsCOMPtr<nsISupports>
795 : * would only be able to point to the single [XP]COM-correct nsISupports
796 : * instance within an object; extra querying ensues. Clients need to be able to
797 : * pass around arbitrary interface pointers, without hassles, through
798 : * intermediary code that doesn't know the exact type.
799 : */
800 : template<>
801 27122 : class nsCOMPtr<nsISupports>
802 : : private nsCOMPtr_base
803 : {
804 : public:
805 : typedef nsISupports element_type;
806 :
807 : // Constructors
808 :
809 37148 : nsCOMPtr()
810 37148 : : nsCOMPtr_base(nullptr)
811 : {
812 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
813 37148 : }
814 :
815 62 : MOZ_IMPLICIT nsCOMPtr(decltype(nullptr))
816 62 : : nsCOMPtr_base(nullptr)
817 : {
818 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
819 62 : }
820 :
821 283 : nsCOMPtr(const nsCOMPtr<nsISupports>& aSmartPtr)
822 283 : : nsCOMPtr_base(aSmartPtr.mRawPtr)
823 : {
824 283 : if (mRawPtr) {
825 262 : NSCAP_ADDREF(this, mRawPtr);
826 : }
827 283 : NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
828 283 : }
829 :
830 2926 : MOZ_IMPLICIT nsCOMPtr(nsISupports* aRawPtr)
831 2926 : : nsCOMPtr_base(aRawPtr)
832 : {
833 2926 : if (mRawPtr) {
834 2839 : NSCAP_ADDREF(this, mRawPtr);
835 : }
836 2926 : NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
837 2926 : }
838 :
839 : // Construct from |already_AddRefed|.
840 0 : MOZ_IMPLICIT nsCOMPtr(already_AddRefed<nsISupports>& aSmartPtr)
841 0 : : nsCOMPtr_base(aSmartPtr.take())
842 : {
843 0 : NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
844 0 : }
845 :
846 : // Construct from |otherComPtr.forget()|.
847 608 : MOZ_IMPLICIT nsCOMPtr(already_AddRefed<nsISupports>&& aSmartPtr)
848 608 : : nsCOMPtr_base(aSmartPtr.take())
849 : {
850 608 : NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
851 608 : }
852 :
853 : // Construct from |do_QueryInterface(expr)|.
854 2145 : MOZ_IMPLICIT nsCOMPtr(const nsQueryInterface aQI)
855 2145 : : nsCOMPtr_base(nullptr)
856 : {
857 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
858 2145 : assign_from_qi(aQI, NS_GET_IID(nsISupports));
859 2145 : }
860 :
861 : // Construct from |do_QueryInterface(expr, &rv)|.
862 0 : MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceWithError& aQI)
863 0 : : nsCOMPtr_base(nullptr)
864 : {
865 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
866 0 : assign_from_qi_with_error(aQI, NS_GET_IID(nsISupports));
867 0 : }
868 :
869 : // Construct from |do_GetService(cid_expr)|.
870 : MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS)
871 : : nsCOMPtr_base(nullptr)
872 : {
873 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
874 : assign_from_gs_cid(aGS, NS_GET_IID(nsISupports));
875 : }
876 :
877 : // Construct from |do_GetService(cid_expr, &rv)|.
878 : MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS)
879 : : nsCOMPtr_base(nullptr)
880 : {
881 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
882 : assign_from_gs_cid_with_error(aGS, NS_GET_IID(nsISupports));
883 : }
884 :
885 : // Construct from |do_GetService(contractid_expr)|.
886 44 : MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS)
887 44 : : nsCOMPtr_base(nullptr)
888 : {
889 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
890 44 : assign_from_gs_contractid(aGS, NS_GET_IID(nsISupports));
891 44 : }
892 :
893 : // Construct from |do_GetService(contractid_expr, &rv)|.
894 19 : MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS)
895 19 : : nsCOMPtr_base(nullptr)
896 : {
897 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
898 19 : assign_from_gs_contractid_with_error(aGS, NS_GET_IID(nsISupports));
899 19 : }
900 :
901 : // And finally, anything else we might need to construct from can exploit
902 : // the |nsCOMPtr_helper| facility
903 61 : MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper)
904 61 : : nsCOMPtr_base(nullptr)
905 : {
906 : NSCAP_LOG_ASSIGNMENT(this, nullptr);
907 61 : assign_from_helper(aHelper, NS_GET_IID(nsISupports));
908 61 : }
909 :
910 :
911 : // Assignment operators
912 :
913 3649 : nsCOMPtr<nsISupports>& operator=(const nsCOMPtr<nsISupports>& aRhs)
914 : {
915 3649 : assign_with_AddRef(aRhs.mRawPtr);
916 3649 : return *this;
917 : }
918 :
919 2673 : nsCOMPtr<nsISupports>& operator=(nsISupports* aRhs)
920 : {
921 2673 : assign_with_AddRef(aRhs);
922 2673 : return *this;
923 : }
924 :
925 2695 : nsCOMPtr<nsISupports>& operator=(decltype(nullptr))
926 : {
927 2695 : assign_assuming_AddRef(nullptr);
928 2695 : return *this;
929 : }
930 :
931 : // Assign from |already_AddRefed|.
932 5721 : nsCOMPtr<nsISupports>& operator=(already_AddRefed<nsISupports>& aRhs)
933 : {
934 5721 : assign_assuming_AddRef(aRhs.take());
935 5721 : return *this;
936 : }
937 :
938 : // Assign from |otherComPtr.forget()|.
939 348 : nsCOMPtr<nsISupports>& operator=(already_AddRefed<nsISupports>&& aRhs)
940 : {
941 348 : assign_assuming_AddRef(aRhs.take());
942 348 : return *this;
943 : }
944 :
945 : // Assign from |do_QueryInterface(expr)|.
946 8278 : nsCOMPtr<nsISupports>& operator=(const nsQueryInterface aRhs)
947 : {
948 8278 : assign_from_qi(aRhs, NS_GET_IID(nsISupports));
949 8278 : return *this;
950 : }
951 :
952 : // Assign from |do_QueryInterface(expr, &rv)|.
953 0 : nsCOMPtr<nsISupports>& operator=(const nsQueryInterfaceWithError& aRhs)
954 : {
955 0 : assign_from_qi_with_error(aRhs, NS_GET_IID(nsISupports));
956 0 : return *this;
957 : }
958 :
959 : // Assign from |do_GetService(cid_expr)|.
960 : nsCOMPtr<nsISupports>& operator=(const nsGetServiceByCID aRhs)
961 : {
962 : assign_from_gs_cid(aRhs, NS_GET_IID(nsISupports));
963 : return *this;
964 : }
965 :
966 : // Assign from |do_GetService(cid_expr, &rv)|.
967 : nsCOMPtr<nsISupports>& operator=(const nsGetServiceByCIDWithError& aRhs)
968 : {
969 : assign_from_gs_cid_with_error(aRhs, NS_GET_IID(nsISupports));
970 : return *this;
971 : }
972 :
973 : // Assign from |do_GetService(contractid_expr)|.
974 : nsCOMPtr<nsISupports>& operator=(const nsGetServiceByContractID aRhs)
975 : {
976 : assign_from_gs_contractid(aRhs, NS_GET_IID(nsISupports));
977 : return *this;
978 : }
979 :
980 : // Assign from |do_GetService(contractid_expr, &rv)|.
981 13 : nsCOMPtr<nsISupports>& operator=(const nsGetServiceByContractIDWithError& aRhs)
982 : {
983 13 : assign_from_gs_contractid_with_error(aRhs, NS_GET_IID(nsISupports));
984 14 : return *this;
985 : }
986 :
987 : // And finally, anything else we might need to assign from can exploit the
988 : // nsCOMPtr_helper facility
989 151 : nsCOMPtr<nsISupports>& operator=(const nsCOMPtr_helper& aRhs)
990 : {
991 151 : assign_from_helper(aRhs, NS_GET_IID(nsISupports));
992 151 : return *this;
993 : }
994 :
995 : // Exchange ownership with |aRhs|; can save a pair of refcount operations.
996 0 : void swap(nsCOMPtr<nsISupports>& aRhs)
997 : {
998 0 : nsISupports* temp = aRhs.mRawPtr;
999 0 : NSCAP_LOG_ASSIGNMENT(&aRhs, mRawPtr);
1000 0 : NSCAP_LOG_ASSIGNMENT(this, temp);
1001 0 : NSCAP_LOG_RELEASE(this, mRawPtr);
1002 0 : NSCAP_LOG_RELEASE(&aRhs, temp);
1003 0 : aRhs.mRawPtr = mRawPtr;
1004 0 : mRawPtr = temp;
1005 0 : }
1006 :
1007 : // Exchange ownership with |aRhs|; can save a pair of refcount operations.
1008 6611 : void swap(nsISupports*& aRhs)
1009 : {
1010 6611 : nsISupports* temp = aRhs;
1011 6611 : NSCAP_LOG_ASSIGNMENT(this, temp);
1012 6611 : NSCAP_LOG_RELEASE(this, mRawPtr);
1013 6611 : aRhs = mRawPtr;
1014 6611 : mRawPtr = temp;
1015 6611 : }
1016 :
1017 : // Return the value of mRawPtr and null out mRawPtr. Useful for
1018 : // already_AddRefed return values.
1019 6611 : already_AddRefed<nsISupports> forget()
1020 : {
1021 6611 : nsISupports* temp = nullptr;
1022 6611 : swap(temp);
1023 6611 : return already_AddRefed<nsISupports>(temp);
1024 : }
1025 :
1026 : // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
1027 : // Useful to avoid unnecessary AddRef/Release pairs with "out"
1028 : // parameters.
1029 0 : void forget(nsISupports** aRhs)
1030 : {
1031 0 : NS_ASSERTION(aRhs, "Null pointer passed to forget!");
1032 0 : *aRhs = nullptr;
1033 0 : swap(*aRhs);
1034 0 : }
1035 :
1036 : // Other pointer operators
1037 :
1038 : // Prefer the implicit conversion provided automatically by
1039 : // |operator nsISupports*() const|. Use |get()| to resolve ambiguity or to
1040 : // get a castable pointer.
1041 81248 : nsISupports* get() const { return reinterpret_cast<nsISupports*>(mRawPtr); }
1042 :
1043 : // Makes an nsCOMPtr act like its underlying raw pointer type whenever it is
1044 : // used in a context where a raw pointer is expected. It is this operator
1045 : // that makes an nsCOMPtr substitutable for a raw pointer.
1046 : //
1047 : // Prefer the implicit use of this operator to calling |get()|, except where
1048 : // necessary to resolve ambiguity/
1049 60601 : operator nsISupports* () const { return get(); }
1050 :
1051 5387 : nsISupports* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
1052 : {
1053 5387 : MOZ_ASSERT(mRawPtr != nullptr,
1054 : "You can't dereference a NULL nsCOMPtr with operator->().");
1055 5387 : return get();
1056 : }
1057 :
1058 : // These are not intended to be used by clients. See |address_of| below.
1059 4114 : nsCOMPtr<nsISupports>* get_address() { return this; }
1060 : const nsCOMPtr<nsISupports>* get_address() const { return this; }
1061 :
1062 : public:
1063 :
1064 : nsISupports& operator*() const
1065 : {
1066 : MOZ_ASSERT(mRawPtr != nullptr,
1067 : "You can't dereference a NULL nsCOMPtr with operator*().");
1068 : return *get();
1069 : }
1070 :
1071 4344 : nsISupports** StartAssignment()
1072 : {
1073 : #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
1074 4344 : return reinterpret_cast<nsISupports**>(begin_assignment());
1075 : #else
1076 : assign_assuming_AddRef(nullptr);
1077 : return reinterpret_cast<nsISupports**>(&mRawPtr);
1078 : #endif
1079 : }
1080 : };
1081 :
1082 : template<typename T>
1083 : inline void
1084 3 : ImplCycleCollectionUnlink(nsCOMPtr<T>& aField)
1085 : {
1086 3 : aField = nullptr;
1087 3 : }
1088 :
1089 : template<typename T>
1090 : inline void
1091 4457 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
1092 : nsCOMPtr<T>& aField,
1093 : const char* aName,
1094 : uint32_t aFlags = 0)
1095 : {
1096 4457 : CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
1097 4457 : }
1098 :
1099 : #ifndef NSCAP_FEATURE_USE_BASE
1100 : template<class T>
1101 : void
1102 151585 : nsCOMPtr<T>::assign_with_AddRef(nsISupports* aRawPtr)
1103 : {
1104 151585 : if (aRawPtr) {
1105 102986 : NSCAP_ADDREF(this, aRawPtr);
1106 : }
1107 151585 : assign_assuming_AddRef(reinterpret_cast<T*>(aRawPtr));
1108 151585 : }
1109 :
1110 : template<class T>
1111 : void
1112 472507 : nsCOMPtr<T>::assign_from_qi(const nsQueryInterface aQI, const nsIID& aIID)
1113 : {
1114 : void* newRawPtr;
1115 472507 : if (NS_FAILED(aQI(aIID, &newRawPtr))) {
1116 40469 : newRawPtr = nullptr;
1117 : }
1118 472515 : assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1119 472515 : }
1120 :
1121 : template<class T>
1122 : void
1123 6381 : nsCOMPtr<T>::assign_from_qi_with_error(const nsQueryInterfaceWithError& aQI,
1124 : const nsIID& aIID)
1125 : {
1126 : void* newRawPtr;
1127 6381 : if (NS_FAILED(aQI(aIID, &newRawPtr))) {
1128 1102 : newRawPtr = nullptr;
1129 : }
1130 6381 : assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1131 6381 : }
1132 :
1133 : template<class T>
1134 : void
1135 15 : nsCOMPtr<T>::assign_from_gs_cid(const nsGetServiceByCID aGS, const nsIID& aIID)
1136 : {
1137 : void* newRawPtr;
1138 15 : if (NS_FAILED(aGS(aIID, &newRawPtr))) {
1139 0 : newRawPtr = nullptr;
1140 : }
1141 15 : assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1142 15 : }
1143 :
1144 : template<class T>
1145 : void
1146 77 : nsCOMPtr<T>::assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError& aGS,
1147 : const nsIID& aIID)
1148 : {
1149 : void* newRawPtr;
1150 77 : if (NS_FAILED(aGS(aIID, &newRawPtr))) {
1151 0 : newRawPtr = nullptr;
1152 : }
1153 77 : assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1154 77 : }
1155 :
1156 : template<class T>
1157 : void
1158 3657 : nsCOMPtr<T>::assign_from_gs_contractid(const nsGetServiceByContractID aGS,
1159 : const nsIID& aIID)
1160 : {
1161 : void* newRawPtr;
1162 3657 : if (NS_FAILED(aGS(aIID, &newRawPtr))) {
1163 11 : newRawPtr = nullptr;
1164 : }
1165 3657 : assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1166 3657 : }
1167 :
1168 : template<class T>
1169 : void
1170 520 : nsCOMPtr<T>::assign_from_gs_contractid_with_error(
1171 : const nsGetServiceByContractIDWithError& aGS, const nsIID& aIID)
1172 : {
1173 : void* newRawPtr;
1174 520 : if (NS_FAILED(aGS(aIID, &newRawPtr))) {
1175 2 : newRawPtr = nullptr;
1176 : }
1177 520 : assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1178 520 : }
1179 :
1180 : template<class T>
1181 : void
1182 8538 : nsCOMPtr<T>::assign_from_helper(const nsCOMPtr_helper& helper, const nsIID& aIID)
1183 : {
1184 : void* newRawPtr;
1185 8538 : if (NS_FAILED(helper(aIID, &newRawPtr))) {
1186 1653 : newRawPtr = nullptr;
1187 : }
1188 8538 : assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1189 8538 : }
1190 :
1191 : template<class T>
1192 : void**
1193 101865 : nsCOMPtr<T>::begin_assignment()
1194 : {
1195 101865 : assign_assuming_AddRef(nullptr);
1196 : union
1197 : {
1198 : T** mT;
1199 : void** mVoid;
1200 : } result;
1201 101865 : result.mT = &mRawPtr;
1202 101865 : return result.mVoid;
1203 : }
1204 : #endif
1205 :
1206 : template<class T>
1207 : inline nsCOMPtr<T>*
1208 78218 : address_of(nsCOMPtr<T>& aPtr)
1209 : {
1210 78218 : return aPtr.get_address();
1211 : }
1212 :
1213 : template<class T>
1214 : inline const nsCOMPtr<T>*
1215 : address_of(const nsCOMPtr<T>& aPtr)
1216 : {
1217 : return aPtr.get_address();
1218 : }
1219 :
1220 : /**
1221 : * This class is designed to be used for anonymous temporary objects in the
1222 : * argument list of calls that return COM interface pointers, e.g.,
1223 : *
1224 : * nsCOMPtr<IFoo> fooP;
1225 : * ...->QueryInterface(iid, getter_AddRefs(fooP))
1226 : *
1227 : * DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
1228 : *
1229 : * When initialized with a |nsCOMPtr|, as in the example above, it returns
1230 : * a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call
1231 : * (|QueryInterface| in this case) can fill in.
1232 : *
1233 : * This type should be a nested class inside |nsCOMPtr<T>|.
1234 : */
1235 : template<class T>
1236 : class nsGetterAddRefs
1237 : {
1238 : public:
1239 101865 : explicit nsGetterAddRefs(nsCOMPtr<T>& aSmartPtr)
1240 101865 : : mTargetSmartPtr(aSmartPtr)
1241 : {
1242 101865 : }
1243 :
1244 : #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
1245 101839 : ~nsGetterAddRefs()
1246 : {
1247 : #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1248 101839 : NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void*>(address_of(mTargetSmartPtr)),
1249 : mTargetSmartPtr.get());
1250 : #endif
1251 :
1252 : #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
1253 101838 : mTargetSmartPtr.Assert_NoQueryNeeded();
1254 : #endif
1255 101839 : }
1256 : #endif
1257 :
1258 1446 : operator void**()
1259 : {
1260 1446 : return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1261 : }
1262 :
1263 100419 : operator T**() { return mTargetSmartPtr.StartAssignment(); }
1264 0 : T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); }
1265 :
1266 : private:
1267 : nsCOMPtr<T>& mTargetSmartPtr;
1268 : };
1269 :
1270 :
1271 : template<>
1272 : class nsGetterAddRefs<nsISupports>
1273 : {
1274 : public:
1275 4344 : explicit nsGetterAddRefs(nsCOMPtr<nsISupports>& aSmartPtr)
1276 4344 : : mTargetSmartPtr(aSmartPtr)
1277 : {
1278 4344 : }
1279 :
1280 : #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1281 4344 : ~nsGetterAddRefs()
1282 4344 : {
1283 4344 : NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void*>(address_of(mTargetSmartPtr)),
1284 4114 : mTargetSmartPtr.get());
1285 4344 : }
1286 : #endif
1287 :
1288 1355 : operator void**()
1289 : {
1290 1355 : return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1291 : }
1292 :
1293 2989 : operator nsISupports**() { return mTargetSmartPtr.StartAssignment(); }
1294 : nsISupports*& operator*() { return *(mTargetSmartPtr.StartAssignment()); }
1295 :
1296 : private:
1297 : nsCOMPtr<nsISupports>& mTargetSmartPtr;
1298 : };
1299 :
1300 : template<class T>
1301 : inline nsGetterAddRefs<T>
1302 106209 : getter_AddRefs(nsCOMPtr<T>& aSmartPtr)
1303 : {
1304 106209 : return nsGetterAddRefs<T>(aSmartPtr);
1305 : }
1306 :
1307 : template<class T, class DestinationType>
1308 : inline nsresult
1309 59 : CallQueryInterface(T* aSource, nsGetterAddRefs<DestinationType> aDestination)
1310 : {
1311 59 : return CallQueryInterface(aSource,
1312 59 : static_cast<DestinationType**>(aDestination));
1313 : }
1314 :
1315 :
1316 : // Comparing two |nsCOMPtr|s
1317 :
1318 : template<class T, class U>
1319 : inline bool
1320 17700 : operator==(const nsCOMPtr<T>& aLhs, const nsCOMPtr<U>& aRhs)
1321 : {
1322 17700 : return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
1323 : }
1324 :
1325 :
1326 : template<class T, class U>
1327 : inline bool
1328 24399 : operator!=(const nsCOMPtr<T>& aLhs, const nsCOMPtr<U>& aRhs)
1329 : {
1330 24399 : return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
1331 : }
1332 :
1333 :
1334 : // Comparing an |nsCOMPtr| to a raw pointer
1335 :
1336 : template<class T, class U>
1337 : inline bool
1338 3281 : operator==(const nsCOMPtr<T>& aLhs, const U* aRhs)
1339 : {
1340 3281 : return static_cast<const T*>(aLhs.get()) == aRhs;
1341 : }
1342 :
1343 : template<class T, class U>
1344 : inline bool
1345 2448 : operator==(const U* aLhs, const nsCOMPtr<T>& aRhs)
1346 : {
1347 2448 : return aLhs == static_cast<const T*>(aRhs.get());
1348 : }
1349 :
1350 : template<class T, class U>
1351 : inline bool
1352 : operator!=(const nsCOMPtr<T>& aLhs, const U* aRhs)
1353 : {
1354 : return static_cast<const T*>(aLhs.get()) != aRhs;
1355 : }
1356 :
1357 : template<class T, class U>
1358 : inline bool
1359 : operator!=(const U* aLhs, const nsCOMPtr<T>& aRhs)
1360 : {
1361 : return aLhs != static_cast<const T*>(aRhs.get());
1362 : }
1363 :
1364 : template<class T, class U>
1365 : inline bool
1366 153153 : operator==(const nsCOMPtr<T>& aLhs, U* aRhs)
1367 : {
1368 153153 : return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
1369 : }
1370 :
1371 : template<class T, class U>
1372 : inline bool
1373 13937 : operator==(U* aLhs, const nsCOMPtr<T>& aRhs)
1374 : {
1375 13937 : return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
1376 : }
1377 :
1378 : template<class T, class U>
1379 : inline bool
1380 67756 : operator!=(const nsCOMPtr<T>& aLhs, U* aRhs)
1381 : {
1382 67756 : return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
1383 : }
1384 :
1385 : template<class T, class U>
1386 : inline bool
1387 2701 : operator!=(U* aLhs, const nsCOMPtr<T>& aRhs)
1388 : {
1389 2701 : return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
1390 : }
1391 :
1392 :
1393 :
1394 : // Comparing an |nsCOMPtr| to |nullptr|
1395 :
1396 : template<class T>
1397 : inline bool
1398 6232 : operator==(const nsCOMPtr<T>& aLhs, decltype(nullptr))
1399 : {
1400 6232 : return aLhs.get() == nullptr;
1401 : }
1402 :
1403 : template<class T>
1404 : inline bool
1405 3 : operator==(decltype(nullptr), const nsCOMPtr<T>& aRhs)
1406 : {
1407 3 : return nullptr == aRhs.get();
1408 : }
1409 :
1410 : template<class T>
1411 : inline bool
1412 2054 : operator!=(const nsCOMPtr<T>& aLhs, decltype(nullptr))
1413 : {
1414 2054 : return aLhs.get() != nullptr;
1415 : }
1416 :
1417 : template<class T>
1418 : inline bool
1419 9117 : operator!=(decltype(nullptr), const nsCOMPtr<T>& aRhs)
1420 : {
1421 9117 : return nullptr != aRhs.get();
1422 : }
1423 :
1424 :
1425 : // Comparing any two [XP]COM objects for identity
1426 :
1427 : inline bool
1428 178 : SameCOMIdentity(nsISupports* aLhs, nsISupports* aRhs)
1429 : {
1430 356 : return nsCOMPtr<nsISupports>(do_QueryInterface(aLhs)) ==
1431 534 : nsCOMPtr<nsISupports>(do_QueryInterface(aRhs));
1432 : }
1433 :
1434 :
1435 :
1436 : template<class SourceType, class DestinationType>
1437 : inline nsresult
1438 4478 : CallQueryInterface(nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr)
1439 : {
1440 4478 : return CallQueryInterface(aSourcePtr.get(), aDestPtr);
1441 : }
1442 :
1443 : template <class T>
1444 27869 : RefPtr<T>::RefPtr(const nsCOMPtr_helper& aHelper)
1445 : {
1446 : void* newRawPtr;
1447 27869 : if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
1448 5845 : newRawPtr = nullptr;
1449 : }
1450 27869 : mRawPtr = static_cast<T*>(newRawPtr);
1451 27869 : }
1452 :
1453 : template <class T>
1454 : RefPtr<T>&
1455 6 : RefPtr<T>::operator=(const nsCOMPtr_helper& aHelper)
1456 : {
1457 : void* newRawPtr;
1458 6 : if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
1459 0 : newRawPtr = nullptr;
1460 : }
1461 6 : assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1462 6 : return *this;
1463 : }
1464 :
1465 : #endif // !defined(nsCOMPtr_h___)
|