Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; 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 nsCOMPtr_h___
7 #define nsCOMPtr_h___
9 /*
10 Having problems?
12 See the User Manual at:
13 http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
16 nsCOMPtr
17 better than a raw pointer
18 for owning objects
19 -- scc
20 */
22 #include "mozilla/Attributes.h"
23 #include "mozilla/TypeTraits.h"
24 #include "mozilla/Assertions.h"
25 #include "mozilla/NullPtr.h"
26 #include "mozilla/Move.h"
28 #include "nsDebug.h" // for |NS_ABORT_IF_FALSE|, |NS_ASSERTION|
29 #include "nsISupportsUtils.h" // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
30 #include "nscore.h" // for |NS_COM_GLUE|
32 #include "nsCycleCollectionNoteChild.h"
35 /*
36 WARNING:
37 This file defines several macros for internal use only. These macros begin with the
38 prefix |NSCAP_|. Do not use these macros in your own code. They are for internal use
39 only for cross-platform compatibility, and are subject to change without notice.
40 */
43 #ifdef _MSC_VER
44 #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
45 // under VC++, we win by inlining StartAssignment
47 // Also under VC++, at the highest warning level, we are overwhelmed with warnings
48 // about (unused) inline functions being removed. This is to be expected with
49 // templates, so we disable the warning.
50 #pragma warning( disable: 4514 )
51 #endif
53 #define NSCAP_FEATURE_USE_BASE
55 #ifdef DEBUG
56 #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
57 #undef NSCAP_FEATURE_USE_BASE
58 //#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
59 #endif
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.
68 #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
69 #else
70 #define NS_MAY_ALIAS_PTR(t) t*
71 #endif
73 #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
74 #define NSCAP_FEATURE_USE_BASE
75 #endif
77 /*
78 The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
79 allow external clients the ability to add logging or other interesting debug facilities.
80 In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
81 provide (e.g., in "nsISupportsImpl.h") suitable definitions
83 #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
84 #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
85 */
87 #ifndef NSCAP_ADDREF
88 #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
89 #endif
91 #ifndef NSCAP_RELEASE
92 #define NSCAP_RELEASE(this, ptr) (ptr)->Release()
93 #endif
95 // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
96 #ifdef NSCAP_LOG_ASSIGNMENT
97 // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
98 // to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
99 // the |nsCOMPtr|.
100 #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
101 #else
102 // ...otherwise, just strip it out of the code
103 #define NSCAP_LOG_ASSIGNMENT(this, ptr)
104 #endif
106 #ifndef NSCAP_LOG_RELEASE
107 #define NSCAP_LOG_RELEASE(this, ptr)
108 #endif
110 namespace mozilla {
112 struct unused_t;
114 } // namespace mozilla
116 template <class T>
117 struct already_AddRefed
118 /*
119 ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
120 |AddRef|ing it. You might want to use this as a return type from a function
121 that produces an already |AddRef|ed pointer as a result.
123 See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
125 This type should be a nested class inside |nsCOMPtr<T>|.
127 Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
128 avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
129 case, and perhaps worth the savings in time and space that its specific
130 implementation affords over the more general solution offered by
131 |nsCOMPtr_helper|.
132 */
133 {
134 /*
135 * Prohibit all one-argument overloads but already_AddRefed(T*) and
136 * already_AddRefed(decltype(nullptr)), and funnel the nullptr case through
137 * the T* constructor.
138 */
139 template<typename N>
140 already_AddRefed(N,
141 typename mozilla::EnableIf<mozilla::IsNullPointer<N>::value,
142 int>::Type dummy = 0)
143 : mRawPtr(nullptr)
144 {
145 // nothing else to do here
146 }
148 already_AddRefed( T* aRawPtr )
149 : mRawPtr(aRawPtr)
150 {
151 // nothing else to do here
152 }
154 // Disallowed. Use move semantics instead.
155 already_AddRefed(const already_AddRefed<T>& aOther) MOZ_DELETE;
157 already_AddRefed(already_AddRefed<T>&& aOther)
158 : mRawPtr(aOther.take())
159 {
160 // nothing else to do here
161 }
163 ~already_AddRefed()
164 {
165 MOZ_ASSERT(!mRawPtr);
166 }
168 // Specialize the unused operator<< for already_AddRefed, to allow
169 // nsCOMPtr<nsIFoo> foo;
170 // unused << foo.forget();
171 friend void operator<<(const mozilla::unused_t& unused,
172 const already_AddRefed<T>& rhs)
173 {
174 auto mutableAlreadyAddRefed = const_cast<already_AddRefed<T>*>(&rhs);
175 unused << mutableAlreadyAddRefed->take();
176 }
178 MOZ_WARN_UNUSED_RESULT T* take()
179 {
180 T* rawPtr = mRawPtr;
181 mRawPtr = nullptr;
182 return rawPtr;
183 }
185 /**
186 * This helper is useful in cases like
187 *
188 * already_AddRefed<BaseClass>
189 * Foo()
190 * {
191 * nsRefPtr<SubClass> x = ...;
192 * return x.forget();
193 * }
194 *
195 * The autoconversion allows one to omit the idiom
196 *
197 * nsRefPtr<BaseClass> y = x.forget();
198 * return y.forget();
199 */
200 template<class U>
201 operator already_AddRefed<U>()
202 {
203 U* tmp = mRawPtr;
204 mRawPtr = nullptr;
205 return already_AddRefed<U>(tmp);
206 }
208 /**
209 * This helper provides a static_cast replacement for already_AddRefed, so
210 * if you have
211 *
212 * already_AddRefed<Parent> F();
213 *
214 * you can write
215 *
216 * already_AddRefed<Child>
217 * G()
218 * {
219 * return F().downcast<Child>();
220 * }
221 *
222 * instead of
223 *
224 * return dont_AddRef(static_cast<Child*>(F().get()));
225 */
226 template<class U>
227 already_AddRefed<U> downcast()
228 {
229 U* tmp = static_cast<U*>(mRawPtr);
230 mRawPtr = nullptr;
231 return already_AddRefed<U>(tmp);
232 }
234 private:
235 T* mRawPtr;
236 };
238 template <class T>
239 inline
240 already_AddRefed<T>
241 dont_AddRef( T* aRawPtr )
242 {
243 return already_AddRefed<T>(aRawPtr);
244 }
246 template <class T>
247 inline
248 already_AddRefed<T>&&
249 dont_AddRef( already_AddRefed<T>&& aAlreadyAddRefedPtr )
250 {
251 return mozilla::Move(aAlreadyAddRefedPtr);
252 }
256 class nsCOMPtr_helper
257 /*
258 An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
259 that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
260 Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
262 Here are the rules for a helper:
263 - it implements |operator()| to produce an interface pointer
264 - (except for its name) |operator()| is a valid [XP]COM `getter'
265 - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
266 - it matches the type requested with the supplied |nsIID| argument
267 - its constructor provides an optional |nsresult*| that |operator()| can fill
268 in with an error when it is executed
270 See |class nsGetInterface| for an example.
271 */
272 {
273 public:
274 virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
275 };
277 /*
278 |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
279 avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
280 is called often enough that the codesize savings are big enough to
281 warrant the specialcasing.
282 */
284 class
285 NS_COM_GLUE
286 MOZ_STACK_CLASS
287 nsQueryInterface MOZ_FINAL
288 {
289 public:
290 explicit
291 nsQueryInterface( nsISupports* aRawPtr )
292 : mRawPtr(aRawPtr)
293 {
294 // nothing else to do here
295 }
297 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
299 private:
300 nsISupports* mRawPtr;
301 };
303 class NS_COM_GLUE nsQueryInterfaceWithError
304 {
305 public:
306 nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
307 : mRawPtr(aRawPtr),
308 mErrorPtr(error)
309 {
310 // nothing else to do here
311 }
313 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
315 private:
316 nsISupports* mRawPtr;
317 nsresult* mErrorPtr;
318 };
320 inline
321 nsQueryInterface
322 do_QueryInterface( nsISupports* aRawPtr )
323 {
324 return nsQueryInterface(aRawPtr);
325 }
327 inline
328 nsQueryInterfaceWithError
329 do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
330 {
331 return nsQueryInterfaceWithError(aRawPtr, error);
332 }
334 template <class T>
335 inline
336 void
337 do_QueryInterface( already_AddRefed<T>& )
338 {
339 // This signature exists solely to _stop_ you from doing the bad thing.
340 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
341 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
342 }
344 template <class T>
345 inline
346 void
347 do_QueryInterface( already_AddRefed<T>&, nsresult* )
348 {
349 // This signature exists solely to _stop_ you from doing the bad thing.
350 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
351 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
352 }
355 ////////////////////////////////////////////////////////////////////////////
356 // Using servicemanager with COMPtrs
357 class NS_COM_GLUE nsGetServiceByCID
358 {
359 public:
360 explicit nsGetServiceByCID(const nsCID& aCID)
361 : mCID(aCID)
362 {
363 // nothing else to do
364 }
366 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
368 private:
369 const nsCID& mCID;
370 };
372 class NS_COM_GLUE nsGetServiceByCIDWithError
373 {
374 public:
375 nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
376 : mCID(aCID),
377 mErrorPtr(aErrorPtr)
378 {
379 // nothing else to do
380 }
382 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
384 private:
385 const nsCID& mCID;
386 nsresult* mErrorPtr;
387 };
389 class NS_COM_GLUE nsGetServiceByContractID
390 {
391 public:
392 explicit nsGetServiceByContractID(const char* aContractID)
393 : mContractID(aContractID)
394 {
395 // nothing else to do
396 }
398 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
400 private:
401 const char* mContractID;
402 };
404 class NS_COM_GLUE nsGetServiceByContractIDWithError
405 {
406 public:
407 nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
408 : mContractID(aContractID),
409 mErrorPtr(aErrorPtr)
410 {
411 // nothing else to do
412 }
414 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
416 private:
417 const char* mContractID;
418 nsresult* mErrorPtr;
419 };
421 class
422 nsCOMPtr_base
423 /*
424 ...factors implementation for all template versions of |nsCOMPtr|.
426 This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
427 because unlike the
429 Here's the way people normally do things like this
431 template <class T> class Foo { ... };
432 template <> class Foo<void*> { ... };
433 template <class T> class Foo<T*> : private Foo<void*> { ... };
434 */
435 {
436 public:
438 nsCOMPtr_base( nsISupports* rawPtr = 0 )
439 : mRawPtr(rawPtr)
440 {
441 // nothing else to do here
442 }
444 NS_COM_GLUE NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base()
445 {
446 NSCAP_LOG_RELEASE(this, mRawPtr);
447 if ( mRawPtr )
448 NSCAP_RELEASE(this, mRawPtr);
449 }
451 NS_COM_GLUE void NS_FASTCALL assign_with_AddRef( nsISupports* );
452 NS_COM_GLUE void NS_FASTCALL assign_from_qi( const nsQueryInterface, const nsIID& );
453 NS_COM_GLUE void NS_FASTCALL assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
454 NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
455 NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
456 NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
457 NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
458 NS_COM_GLUE void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
459 NS_COM_GLUE void** NS_FASTCALL begin_assignment();
461 protected:
462 NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
464 void
465 assign_assuming_AddRef( nsISupports* newPtr )
466 {
467 /*
468 |AddRef()|ing the new value (before entering this function) before
469 |Release()|ing the old lets us safely ignore the self-assignment case.
470 We must, however, be careful only to |Release()| _after_ doing the
471 assignment, in case the |Release()| leads to our _own_ destruction,
472 which would, in turn, cause an incorrect second |Release()| of our old
473 pointer. Thank <waterson@netscape.com> for discovering this.
474 */
475 nsISupports* oldPtr = mRawPtr;
476 mRawPtr = newPtr;
477 NSCAP_LOG_ASSIGNMENT(this, newPtr);
478 NSCAP_LOG_RELEASE(this, oldPtr);
479 if ( oldPtr )
480 NSCAP_RELEASE(this, oldPtr);
481 }
482 };
484 // template <class T> class nsGetterAddRefs;
486 template <class T>
487 class nsCOMPtr MOZ_FINAL
488 #ifdef NSCAP_FEATURE_USE_BASE
489 : private nsCOMPtr_base
490 #endif
491 {
493 #ifdef NSCAP_FEATURE_USE_BASE
494 #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
495 #else
496 #define NSCAP_CTOR_BASE(x) mRawPtr(x)
498 private:
499 void assign_with_AddRef( nsISupports* );
500 void assign_from_qi( const nsQueryInterface, const nsIID& );
501 void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
502 void assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
503 void assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
504 void assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
505 void assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
506 void assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
507 void** begin_assignment();
509 void
510 assign_assuming_AddRef( T* newPtr )
511 {
512 T* oldPtr = mRawPtr;
513 mRawPtr = newPtr;
514 NSCAP_LOG_ASSIGNMENT(this, newPtr);
515 NSCAP_LOG_RELEASE(this, oldPtr);
516 if ( oldPtr )
517 NSCAP_RELEASE(this, oldPtr);
518 }
520 private:
521 T* mRawPtr;
522 #endif
524 public:
525 typedef T element_type;
527 #ifndef NSCAP_FEATURE_USE_BASE
528 ~nsCOMPtr()
529 {
530 NSCAP_LOG_RELEASE(this, mRawPtr);
531 if ( mRawPtr )
532 NSCAP_RELEASE(this, mRawPtr);
533 }
534 #endif
536 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
537 void
538 Assert_NoQueryNeeded()
539 {
540 if ( mRawPtr )
541 {
542 nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
543 NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
544 }
545 }
547 #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
548 #else
549 #define NSCAP_ASSERT_NO_QUERY_NEEDED()
550 #endif
553 // Constructors
555 nsCOMPtr()
556 : NSCAP_CTOR_BASE(0)
557 // default constructor
558 {
559 NSCAP_LOG_ASSIGNMENT(this, 0);
560 }
562 nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
563 : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
564 // copy-constructor
565 {
566 if ( mRawPtr )
567 NSCAP_ADDREF(this, mRawPtr);
568 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
569 }
571 nsCOMPtr( T* aRawPtr )
572 : NSCAP_CTOR_BASE(aRawPtr)
573 // construct from a raw pointer (of the right type)
574 {
575 if ( mRawPtr )
576 NSCAP_ADDREF(this, mRawPtr);
577 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
578 NSCAP_ASSERT_NO_QUERY_NEEDED();
579 }
581 nsCOMPtr( already_AddRefed<T>& aSmartPtr )
582 : NSCAP_CTOR_BASE(aSmartPtr.take())
583 // construct from |already_AddRefed|
584 {
585 NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
586 NSCAP_ASSERT_NO_QUERY_NEEDED();
587 }
589 nsCOMPtr( already_AddRefed<T>&& aSmartPtr )
590 : NSCAP_CTOR_BASE(aSmartPtr.take())
591 // construct from |otherComPtr.forget()|
592 {
593 NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
594 NSCAP_ASSERT_NO_QUERY_NEEDED();
595 }
597 template<typename U>
598 nsCOMPtr( already_AddRefed<U>& aSmartPtr )
599 : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
600 // construct from |already_AddRefed|
601 {
602 // But make sure that U actually inherits from T
603 static_assert(mozilla::IsBaseOf<T, U>::value,
604 "U is not a subclass of T");
605 NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
606 NSCAP_ASSERT_NO_QUERY_NEEDED();
607 }
609 template<typename U>
610 nsCOMPtr( already_AddRefed<U>&& aSmartPtr )
611 : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
612 // construct from |otherComPtr.forget()|
613 {
614 // But make sure that U actually inherits from T
615 static_assert(mozilla::IsBaseOf<T, U>::value,
616 "U is not a subclass of T");
617 NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
618 NSCAP_ASSERT_NO_QUERY_NEEDED();
619 }
621 nsCOMPtr( const nsQueryInterface qi )
622 : NSCAP_CTOR_BASE(0)
623 // construct from |do_QueryInterface(expr)|
624 {
625 NSCAP_LOG_ASSIGNMENT(this, 0);
626 assign_from_qi(qi, NS_GET_TEMPLATE_IID(T));
627 }
629 nsCOMPtr( const nsQueryInterfaceWithError& qi )
630 : NSCAP_CTOR_BASE(0)
631 // construct from |do_QueryInterface(expr, &rv)|
632 {
633 NSCAP_LOG_ASSIGNMENT(this, 0);
634 assign_from_qi_with_error(qi, NS_GET_TEMPLATE_IID(T));
635 }
637 nsCOMPtr( const nsGetServiceByCID gs )
638 : NSCAP_CTOR_BASE(0)
639 // construct from |do_GetService(cid_expr)|
640 {
641 NSCAP_LOG_ASSIGNMENT(this, 0);
642 assign_from_gs_cid(gs, NS_GET_TEMPLATE_IID(T));
643 }
645 nsCOMPtr( const nsGetServiceByCIDWithError& gs )
646 : NSCAP_CTOR_BASE(0)
647 // construct from |do_GetService(cid_expr, &rv)|
648 {
649 NSCAP_LOG_ASSIGNMENT(this, 0);
650 assign_from_gs_cid_with_error(gs, NS_GET_TEMPLATE_IID(T));
651 }
653 nsCOMPtr( const nsGetServiceByContractID gs )
654 : NSCAP_CTOR_BASE(0)
655 // construct from |do_GetService(contractid_expr)|
656 {
657 NSCAP_LOG_ASSIGNMENT(this, 0);
658 assign_from_gs_contractid(gs, NS_GET_TEMPLATE_IID(T));
659 }
661 nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
662 : NSCAP_CTOR_BASE(0)
663 // construct from |do_GetService(contractid_expr, &rv)|
664 {
665 NSCAP_LOG_ASSIGNMENT(this, 0);
666 assign_from_gs_contractid_with_error(gs, NS_GET_TEMPLATE_IID(T));
667 }
669 nsCOMPtr( const nsCOMPtr_helper& helper )
670 : NSCAP_CTOR_BASE(0)
671 // ...and finally, anything else we might need to construct from
672 // can exploit the |nsCOMPtr_helper| facility
673 {
674 NSCAP_LOG_ASSIGNMENT(this, 0);
675 assign_from_helper(helper, NS_GET_TEMPLATE_IID(T));
676 NSCAP_ASSERT_NO_QUERY_NEEDED();
677 }
680 // Assignment operators
682 nsCOMPtr<T>&
683 operator=( const nsCOMPtr<T>& rhs )
684 // copy assignment operator
685 {
686 assign_with_AddRef(rhs.mRawPtr);
687 return *this;
688 }
690 nsCOMPtr<T>&
691 operator=( T* rhs )
692 // assign from a raw pointer (of the right type)
693 {
694 assign_with_AddRef(rhs);
695 NSCAP_ASSERT_NO_QUERY_NEEDED();
696 return *this;
697 }
699 template<typename U>
700 nsCOMPtr<T>&
701 operator=( already_AddRefed<U>& rhs )
702 // assign from |already_AddRefed|
703 {
704 // Make sure that U actually inherits from T
705 static_assert(mozilla::IsBaseOf<T, U>::value,
706 "U is not a subclass of T");
707 assign_assuming_AddRef(static_cast<T*>(rhs.take()));
708 NSCAP_ASSERT_NO_QUERY_NEEDED();
709 return *this;
710 }
712 template<typename U>
713 nsCOMPtr<T>&
714 operator=( already_AddRefed<U>&& rhs )
715 // assign from |otherComPtr.forget()|
716 {
717 // Make sure that U actually inherits from T
718 static_assert(mozilla::IsBaseOf<T, U>::value,
719 "U is not a subclass of T");
720 assign_assuming_AddRef(static_cast<T*>(rhs.take()));
721 NSCAP_ASSERT_NO_QUERY_NEEDED();
722 return *this;
723 }
725 nsCOMPtr<T>&
726 operator=( const nsQueryInterface rhs )
727 // assign from |do_QueryInterface(expr)|
728 {
729 assign_from_qi(rhs, NS_GET_TEMPLATE_IID(T));
730 return *this;
731 }
733 nsCOMPtr<T>&
734 operator=( const nsQueryInterfaceWithError& rhs )
735 // assign from |do_QueryInterface(expr, &rv)|
736 {
737 assign_from_qi_with_error(rhs, NS_GET_TEMPLATE_IID(T));
738 return *this;
739 }
741 nsCOMPtr<T>&
742 operator=( const nsGetServiceByCID rhs )
743 // assign from |do_GetService(cid_expr)|
744 {
745 assign_from_gs_cid(rhs, NS_GET_TEMPLATE_IID(T));
746 return *this;
747 }
749 nsCOMPtr<T>&
750 operator=( const nsGetServiceByCIDWithError& rhs )
751 // assign from |do_GetService(cid_expr, &rv)|
752 {
753 assign_from_gs_cid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
754 return *this;
755 }
757 nsCOMPtr<T>&
758 operator=( const nsGetServiceByContractID rhs )
759 // assign from |do_GetService(contractid_expr)|
760 {
761 assign_from_gs_contractid(rhs, NS_GET_TEMPLATE_IID(T));
762 return *this;
763 }
765 nsCOMPtr<T>&
766 operator=( const nsGetServiceByContractIDWithError& rhs )
767 // assign from |do_GetService(contractid_expr, &rv)|
768 {
769 assign_from_gs_contractid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
770 return *this;
771 }
773 nsCOMPtr<T>&
774 operator=( const nsCOMPtr_helper& rhs )
775 // ...and finally, anything else we might need to assign from
776 // can exploit the |nsCOMPtr_helper| facility.
777 {
778 assign_from_helper(rhs, NS_GET_TEMPLATE_IID(T));
779 NSCAP_ASSERT_NO_QUERY_NEEDED();
780 return *this;
781 }
783 void
784 swap( nsCOMPtr<T>& rhs )
785 // ...exchange ownership with |rhs|; can save a pair of refcount operations
786 {
787 #ifdef NSCAP_FEATURE_USE_BASE
788 nsISupports* temp = rhs.mRawPtr;
789 #else
790 T* temp = rhs.mRawPtr;
791 #endif
792 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
793 NSCAP_LOG_ASSIGNMENT(this, temp);
794 NSCAP_LOG_RELEASE(this, mRawPtr);
795 NSCAP_LOG_RELEASE(&rhs, temp);
796 rhs.mRawPtr = mRawPtr;
797 mRawPtr = temp;
798 // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
799 }
801 void
802 swap( T*& rhs )
803 // ...exchange ownership with |rhs|; can save a pair of refcount operations
804 {
805 #ifdef NSCAP_FEATURE_USE_BASE
806 nsISupports* temp = rhs;
807 #else
808 T* temp = rhs;
809 #endif
810 NSCAP_LOG_ASSIGNMENT(this, temp);
811 NSCAP_LOG_RELEASE(this, mRawPtr);
812 rhs = reinterpret_cast<T*>(mRawPtr);
813 mRawPtr = temp;
814 NSCAP_ASSERT_NO_QUERY_NEEDED();
815 }
818 // Other pointer operators
820 already_AddRefed<T>
821 forget()
822 // return the value of mRawPtr and null out mRawPtr. Useful for
823 // already_AddRefed return values.
824 {
825 T* temp = 0;
826 swap(temp);
827 return already_AddRefed<T>(temp);
828 }
830 template <typename I>
831 void
832 forget( I** rhs )
833 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
834 // Useful to avoid unnecessary AddRef/Release pairs with "out"
835 // parameters where rhs bay be a T** or an I** where I is a base class
836 // of T.
837 {
838 NS_ASSERTION(rhs, "Null pointer passed to forget!");
839 NSCAP_LOG_RELEASE(this, mRawPtr);
840 *rhs = get();
841 mRawPtr = 0;
842 }
844 T*
845 get() const
846 /*
847 Prefer the implicit conversion provided automatically by |operator T*() const|.
848 Use |get()| to resolve ambiguity or to get a castable pointer.
849 */
850 {
851 return reinterpret_cast<T*>(mRawPtr);
852 }
854 operator T*() const
855 /*
856 ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it
857 is used in a context where a raw pointer is expected. It is this operator
858 that makes an |nsCOMPtr| substitutable for a raw pointer.
860 Prefer the implicit use of this operator to calling |get()|, except where
861 necessary to resolve ambiguity.
862 */
863 {
864 return get();
865 }
867 T*
868 operator->() const
869 {
870 NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
871 return get();
872 }
874 nsCOMPtr<T>*
875 get_address()
876 // This is not intended to be used by clients. See |address_of|
877 // below.
878 {
879 return this;
880 }
882 const nsCOMPtr<T>*
883 get_address() const
884 // This is not intended to be used by clients. See |address_of|
885 // below.
886 {
887 return this;
888 }
890 public:
891 T&
892 operator*() const
893 {
894 NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
895 return *get();
896 }
898 T**
899 StartAssignment()
900 {
901 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
902 return reinterpret_cast<T**>(begin_assignment());
903 #else
904 assign_assuming_AddRef(0);
905 return reinterpret_cast<T**>(&mRawPtr);
906 #endif
907 }
908 };
912 /*
913 Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
914 same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
915 to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able
916 to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
917 querying ensues. Clients need to be able to pass around arbitrary interface pointers,
918 without hassles, through intermediary code that doesn't know the exact type.
919 */
921 template <>
922 class nsCOMPtr<nsISupports>
923 : private nsCOMPtr_base
924 {
925 public:
926 typedef nsISupports element_type;
928 // Constructors
930 nsCOMPtr()
931 : nsCOMPtr_base(0)
932 // default constructor
933 {
934 NSCAP_LOG_ASSIGNMENT(this, 0);
935 }
937 nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
938 : nsCOMPtr_base(aSmartPtr.mRawPtr)
939 // copy constructor
940 {
941 if ( mRawPtr )
942 NSCAP_ADDREF(this, mRawPtr);
943 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
944 }
946 nsCOMPtr( nsISupports* aRawPtr )
947 : nsCOMPtr_base(aRawPtr)
948 // construct from a raw pointer (of the right type)
949 {
950 if ( mRawPtr )
951 NSCAP_ADDREF(this, mRawPtr);
952 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
953 }
955 nsCOMPtr( already_AddRefed<nsISupports>& aSmartPtr )
956 : nsCOMPtr_base(aSmartPtr.take())
957 // construct from |already_AddRefed|
958 {
959 NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
960 }
962 nsCOMPtr( already_AddRefed<nsISupports>&& aSmartPtr )
963 : nsCOMPtr_base(aSmartPtr.take())
964 // construct from |otherComPtr.forget()|
965 {
966 NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
967 }
969 nsCOMPtr( const nsQueryInterface qi )
970 : nsCOMPtr_base(0)
971 // assign from |do_QueryInterface(expr)|
972 {
973 NSCAP_LOG_ASSIGNMENT(this, 0);
974 assign_from_qi(qi, NS_GET_IID(nsISupports));
975 }
977 nsCOMPtr( const nsQueryInterfaceWithError& qi )
978 : nsCOMPtr_base(0)
979 // assign from |do_QueryInterface(expr, &rv)|
980 {
981 NSCAP_LOG_ASSIGNMENT(this, 0);
982 assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
983 }
985 nsCOMPtr( const nsGetServiceByCID gs )
986 : nsCOMPtr_base(0)
987 // assign from |do_GetService(cid_expr)|
988 {
989 NSCAP_LOG_ASSIGNMENT(this, 0);
990 assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
991 }
993 nsCOMPtr( const nsGetServiceByCIDWithError& gs )
994 : nsCOMPtr_base(0)
995 // assign from |do_GetService(cid_expr, &rv)|
996 {
997 NSCAP_LOG_ASSIGNMENT(this, 0);
998 assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
999 }
1001 nsCOMPtr( const nsGetServiceByContractID gs )
1002 : nsCOMPtr_base(0)
1003 // assign from |do_GetService(contractid_expr)|
1004 {
1005 NSCAP_LOG_ASSIGNMENT(this, 0);
1006 assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
1007 }
1009 nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
1010 : nsCOMPtr_base(0)
1011 // assign from |do_GetService(contractid_expr, &rv)|
1012 {
1013 NSCAP_LOG_ASSIGNMENT(this, 0);
1014 assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
1015 }
1017 nsCOMPtr( const nsCOMPtr_helper& helper )
1018 : nsCOMPtr_base(0)
1019 // ...and finally, anything else we might need to construct from
1020 // can exploit the |nsCOMPtr_helper| facility
1021 {
1022 NSCAP_LOG_ASSIGNMENT(this, 0);
1023 assign_from_helper(helper, NS_GET_IID(nsISupports));
1024 }
1027 // Assignment operators
1029 nsCOMPtr<nsISupports>&
1030 operator=( const nsCOMPtr<nsISupports>& rhs )
1031 // copy assignment operator
1032 {
1033 assign_with_AddRef(rhs.mRawPtr);
1034 return *this;
1035 }
1037 nsCOMPtr<nsISupports>&
1038 operator=( nsISupports* rhs )
1039 // assign from a raw pointer (of the right type)
1040 {
1041 assign_with_AddRef(rhs);
1042 return *this;
1043 }
1045 nsCOMPtr<nsISupports>&
1046 operator=( already_AddRefed<nsISupports>& rhs )
1047 // assign from |already_AddRefed|
1048 {
1049 assign_assuming_AddRef(rhs.take());
1050 return *this;
1051 }
1053 nsCOMPtr<nsISupports>&
1054 operator=( already_AddRefed<nsISupports>&& rhs )
1055 // assign from |otherComPtr.forget()|
1056 {
1057 assign_assuming_AddRef(rhs.take());
1058 return *this;
1059 }
1061 nsCOMPtr<nsISupports>&
1062 operator=( const nsQueryInterface rhs )
1063 // assign from |do_QueryInterface(expr)|
1064 {
1065 assign_from_qi(rhs, NS_GET_IID(nsISupports));
1066 return *this;
1067 }
1069 nsCOMPtr<nsISupports>&
1070 operator=( const nsQueryInterfaceWithError& rhs )
1071 // assign from |do_QueryInterface(expr, &rv)|
1072 {
1073 assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
1074 return *this;
1075 }
1077 nsCOMPtr<nsISupports>&
1078 operator=( const nsGetServiceByCID rhs )
1079 // assign from |do_GetService(cid_expr)|
1080 {
1081 assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
1082 return *this;
1083 }
1085 nsCOMPtr<nsISupports>&
1086 operator=( const nsGetServiceByCIDWithError& rhs )
1087 // assign from |do_GetService(cid_expr, &rv)|
1088 {
1089 assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
1090 return *this;
1091 }
1093 nsCOMPtr<nsISupports>&
1094 operator=( const nsGetServiceByContractID rhs )
1095 // assign from |do_GetService(contractid_expr)|
1096 {
1097 assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
1098 return *this;
1099 }
1101 nsCOMPtr<nsISupports>&
1102 operator=( const nsGetServiceByContractIDWithError& rhs )
1103 // assign from |do_GetService(contractid_expr, &rv)|
1104 {
1105 assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
1106 return *this;
1107 }
1109 nsCOMPtr<nsISupports>&
1110 operator=( const nsCOMPtr_helper& rhs )
1111 // ...and finally, anything else we might need to assign from
1112 // can exploit the |nsCOMPtr_helper| facility.
1113 {
1114 assign_from_helper(rhs, NS_GET_IID(nsISupports));
1115 return *this;
1116 }
1118 void
1119 swap( nsCOMPtr<nsISupports>& rhs )
1120 // ...exchange ownership with |rhs|; can save a pair of refcount operations
1121 {
1122 nsISupports* temp = rhs.mRawPtr;
1123 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
1124 NSCAP_LOG_ASSIGNMENT(this, temp);
1125 NSCAP_LOG_RELEASE(this, mRawPtr);
1126 NSCAP_LOG_RELEASE(&rhs, temp);
1127 rhs.mRawPtr = mRawPtr;
1128 mRawPtr = temp;
1129 }
1131 void
1132 swap( nsISupports*& rhs )
1133 // ...exchange ownership with |rhs|; can save a pair of refcount operations
1134 {
1135 nsISupports* temp = rhs;
1136 NSCAP_LOG_ASSIGNMENT(this, temp);
1137 NSCAP_LOG_RELEASE(this, mRawPtr);
1138 rhs = mRawPtr;
1139 mRawPtr = temp;
1140 }
1142 already_AddRefed<nsISupports>
1143 forget()
1144 // return the value of mRawPtr and null out mRawPtr. Useful for
1145 // already_AddRefed return values.
1146 {
1147 nsISupports* temp = 0;
1148 swap(temp);
1149 return already_AddRefed<nsISupports>(temp);
1150 }
1152 void
1153 forget( nsISupports** rhs )
1154 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
1155 // Useful to avoid unnecessary AddRef/Release pairs with "out"
1156 // parameters.
1157 {
1158 NS_ASSERTION(rhs, "Null pointer passed to forget!");
1159 *rhs = 0;
1160 swap(*rhs);
1161 }
1163 // Other pointer operators
1165 nsISupports*
1166 get() const
1167 /*
1168 Prefer the implicit conversion provided automatically by
1169 |operator nsISupports*() const|.
1170 Use |get()| to resolve ambiguity or to get a castable pointer.
1171 */
1172 {
1173 return reinterpret_cast<nsISupports*>(mRawPtr);
1174 }
1176 operator nsISupports*() const
1177 /*
1178 ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it
1179 is used in a context where a raw pointer is expected. It is this operator
1180 that makes an |nsCOMPtr| substitutable for a raw pointer.
1182 Prefer the implicit use of this operator to calling |get()|, except where
1183 necessary to resolve ambiguity.
1184 */
1185 {
1186 return get();
1187 }
1189 nsISupports*
1190 operator->() const
1191 {
1192 NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
1193 return get();
1194 }
1196 nsCOMPtr<nsISupports>*
1197 get_address()
1198 // This is not intended to be used by clients. See |address_of|
1199 // below.
1200 {
1201 return this;
1202 }
1204 const nsCOMPtr<nsISupports>*
1205 get_address() const
1206 // This is not intended to be used by clients. See |address_of|
1207 // below.
1208 {
1209 return this;
1210 }
1212 public:
1214 nsISupports&
1215 operator*() const
1216 {
1217 NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
1218 return *get();
1219 }
1221 nsISupports**
1222 StartAssignment()
1223 {
1224 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
1225 return reinterpret_cast<nsISupports**>(begin_assignment());
1226 #else
1227 assign_assuming_AddRef(0);
1228 return reinterpret_cast<nsISupports**>(&mRawPtr);
1229 #endif
1230 }
1231 };
1233 template <typename T>
1234 inline void
1235 ImplCycleCollectionUnlink(nsCOMPtr<T>& aField)
1236 {
1237 aField = nullptr;
1238 }
1240 template <typename T>
1241 inline void
1242 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
1243 nsCOMPtr<T>& aField,
1244 const char* aName,
1245 uint32_t aFlags = 0)
1246 {
1247 CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
1248 }
1250 #ifndef NSCAP_FEATURE_USE_BASE
1251 template <class T>
1252 void
1253 nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
1254 {
1255 if ( rawPtr )
1256 NSCAP_ADDREF(this, rawPtr);
1257 assign_assuming_AddRef(reinterpret_cast<T*>(rawPtr));
1258 }
1260 template <class T>
1261 void
1262 nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
1263 {
1264 void* newRawPtr;
1265 if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
1266 newRawPtr = 0;
1267 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1268 }
1270 template <class T>
1271 void
1272 nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
1273 {
1274 void* newRawPtr;
1275 if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
1276 newRawPtr = 0;
1277 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1278 }
1280 template <class T>
1281 void
1282 nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
1283 {
1284 void* newRawPtr;
1285 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1286 newRawPtr = 0;
1287 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1288 }
1290 template <class T>
1291 void
1292 nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
1293 {
1294 void* newRawPtr;
1295 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1296 newRawPtr = 0;
1297 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1298 }
1300 template <class T>
1301 void
1302 nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
1303 {
1304 void* newRawPtr;
1305 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1306 newRawPtr = 0;
1307 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1308 }
1310 template <class T>
1311 void
1312 nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
1313 {
1314 void* newRawPtr;
1315 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1316 newRawPtr = 0;
1317 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1318 }
1320 template <class T>
1321 void
1322 nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
1323 {
1324 void* newRawPtr;
1325 if ( NS_FAILED( helper(aIID, &newRawPtr) ) )
1326 newRawPtr = 0;
1327 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1328 }
1330 template <class T>
1331 void**
1332 nsCOMPtr<T>::begin_assignment()
1333 {
1334 assign_assuming_AddRef(0);
1335 union { T** mT; void** mVoid; } result;
1336 result.mT = &mRawPtr;
1337 return result.mVoid;
1338 }
1339 #endif
1341 template <class T>
1342 inline
1343 nsCOMPtr<T>*
1344 address_of( nsCOMPtr<T>& aPtr )
1345 {
1346 return aPtr.get_address();
1347 }
1349 template <class T>
1350 inline
1351 const nsCOMPtr<T>*
1352 address_of( const nsCOMPtr<T>& aPtr )
1353 {
1354 return aPtr.get_address();
1355 }
1357 template <class T>
1358 class nsGetterAddRefs
1359 /*
1360 ...
1362 This class is designed to be used for anonymous temporary objects in the
1363 argument list of calls that return COM interface pointers, e.g.,
1365 nsCOMPtr<IFoo> fooP;
1366 ...->QueryInterface(iid, getter_AddRefs(fooP))
1368 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
1370 When initialized with a |nsCOMPtr|, as in the example above, it returns
1371 a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
1372 case) can fill in.
1374 This type should be a nested class inside |nsCOMPtr<T>|.
1375 */
1376 {
1377 public:
1378 explicit
1379 nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
1380 : mTargetSmartPtr(aSmartPtr)
1381 {
1382 // nothing else to do
1383 }
1385 #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
1386 ~nsGetterAddRefs()
1387 {
1388 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1389 NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
1390 #endif
1392 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
1393 mTargetSmartPtr.Assert_NoQueryNeeded();
1394 #endif
1395 }
1396 #endif
1398 operator void**()
1399 {
1400 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1401 }
1402 operator T**()
1403 {
1404 return mTargetSmartPtr.StartAssignment();
1405 }
1407 T*&
1408 operator*()
1409 {
1410 return *(mTargetSmartPtr.StartAssignment());
1411 }
1413 private:
1414 nsCOMPtr<T>& mTargetSmartPtr;
1415 };
1418 template <>
1419 class nsGetterAddRefs<nsISupports>
1420 {
1421 public:
1422 explicit
1423 nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
1424 : mTargetSmartPtr(aSmartPtr)
1425 {
1426 // nothing else to do
1427 }
1429 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1430 ~nsGetterAddRefs()
1431 {
1432 NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
1433 }
1434 #endif
1436 operator void**()
1437 {
1438 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1439 }
1441 operator nsISupports**()
1442 {
1443 return mTargetSmartPtr.StartAssignment();
1444 }
1446 nsISupports*&
1447 operator*()
1448 {
1449 return *(mTargetSmartPtr.StartAssignment());
1450 }
1452 private:
1453 nsCOMPtr<nsISupports>& mTargetSmartPtr;
1454 };
1457 template <class T>
1458 inline
1459 nsGetterAddRefs<T>
1460 getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
1461 /*
1462 Used around a |nsCOMPtr| when
1463 ...makes the class |nsGetterAddRefs<T>| invisible.
1464 */
1465 {
1466 return nsGetterAddRefs<T>(aSmartPtr);
1467 }
1469 template <class T, class DestinationType>
1470 inline
1471 nsresult
1472 CallQueryInterface( T* aSource, nsGetterAddRefs<DestinationType> aDestination )
1473 {
1474 return CallQueryInterface(aSource,
1475 static_cast<DestinationType**>(aDestination));
1476 }
1479 // Comparing two |nsCOMPtr|s
1481 template <class T, class U>
1482 inline
1483 bool
1484 operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1485 {
1486 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
1487 }
1490 template <class T, class U>
1491 inline
1492 bool
1493 operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1494 {
1495 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
1496 }
1499 // Comparing an |nsCOMPtr| to a raw pointer
1501 template <class T, class U>
1502 inline
1503 bool
1504 operator==( const nsCOMPtr<T>& lhs, const U* rhs )
1505 {
1506 return static_cast<const T*>(lhs.get()) == rhs;
1507 }
1509 template <class T, class U>
1510 inline
1511 bool
1512 operator==( const U* lhs, const nsCOMPtr<T>& rhs )
1513 {
1514 return lhs == static_cast<const T*>(rhs.get());
1515 }
1517 template <class T, class U>
1518 inline
1519 bool
1520 operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
1521 {
1522 return static_cast<const T*>(lhs.get()) != rhs;
1523 }
1525 template <class T, class U>
1526 inline
1527 bool
1528 operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
1529 {
1530 return lhs != static_cast<const T*>(rhs.get());
1531 }
1533 // To avoid ambiguities caused by the presence of builtin |operator==|s
1534 // creating a situation where one of the |operator==| defined above
1535 // has a better conversion for one argument and the builtin has a
1536 // better conversion for the other argument, define additional
1537 // |operator==| without the |const| on the raw pointer.
1538 // See bug 65664 for details.
1540 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1541 template <class T, class U>
1542 inline
1543 bool
1544 operator==( const nsCOMPtr<T>& lhs, U* rhs )
1545 {
1546 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
1547 }
1549 template <class T, class U>
1550 inline
1551 bool
1552 operator==( U* lhs, const nsCOMPtr<T>& rhs )
1553 {
1554 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
1555 }
1557 template <class T, class U>
1558 inline
1559 bool
1560 operator!=( const nsCOMPtr<T>& lhs, U* rhs )
1561 {
1562 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
1563 }
1565 template <class T, class U>
1566 inline
1567 bool
1568 operator!=( U* lhs, const nsCOMPtr<T>& rhs )
1569 {
1570 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
1571 }
1572 #endif
1576 // Comparing an |nsCOMPtr| to |0|
1578 class NSCAP_Zero;
1580 template <class T>
1581 inline
1582 bool
1583 operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1584 // specifically to allow |smartPtr == 0|
1585 {
1586 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
1587 }
1589 template <class T>
1590 inline
1591 bool
1592 operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1593 // specifically to allow |0 == smartPtr|
1594 {
1595 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
1596 }
1598 template <class T>
1599 inline
1600 bool
1601 operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1602 // specifically to allow |smartPtr != 0|
1603 {
1604 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
1605 }
1607 template <class T>
1608 inline
1609 bool
1610 operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1611 // specifically to allow |0 != smartPtr|
1612 {
1613 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
1614 }
1617 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
1619 // We need to explicitly define comparison operators for `int'
1620 // because the compiler is lame.
1622 template <class T>
1623 inline
1624 bool
1625 operator==( const nsCOMPtr<T>& lhs, int rhs )
1626 // specifically to allow |smartPtr == 0|
1627 {
1628 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
1629 }
1631 template <class T>
1632 inline
1633 bool
1634 operator==( int lhs, const nsCOMPtr<T>& rhs )
1635 // specifically to allow |0 == smartPtr|
1636 {
1637 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
1638 }
1640 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
1642 // Comparing any two [XP]COM objects for identity
1644 inline
1645 bool
1646 SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
1647 {
1648 return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
1649 }
1653 template <class SourceType, class DestinationType>
1654 inline
1655 nsresult
1656 CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
1657 {
1658 return CallQueryInterface(aSourcePtr.get(), aDestPtr);
1659 }
1661 #endif // !defined(nsCOMPtr_h___)