Bug 438394 ? land workaround patch for unkillable hangs when loading VerifiedDownload...
[wine-gecko.git] / xpcom / glue / nsCOMPtr.h
blobf50d28ae9e877fe260e5eeb83836c57abcec811c
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Scott Collins <scc@mozilla.org> (original author)
24 * L. David Baron <dbaron@dbaron.org>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef nsCOMPtr_h___
41 #define nsCOMPtr_h___
44 Having problems?
46 See the User Manual at:
47 http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
50 nsCOMPtr
51 better than a raw pointer
52 for owning objects
53 -- scc
57 // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
58 #ifndef nsDebug_h___
59 #include "nsDebug.h"
60 // for |NS_PRECONDITION|
61 #endif
63 #ifndef nsISupportsUtils_h__
64 #include "nsISupportsUtils.h"
65 // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
66 #endif
68 #ifndef nscore_h___
69 #include "nscore.h"
70 // for |NS_COM_GLUE|
71 #endif
75 WARNING:
76 This file defines several macros for internal use only. These macros begin with the
77 prefix |NSCAP_|. Do not use these macros in your own code. They are for internal use
78 only for cross-platform compatibility, and are subject to change without notice.
82 #ifdef _MSC_VER
83 #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
84 // under VC++, we win by inlining StartAssignment
86 // Also under VC++, at the highest warning level, we are overwhelmed with warnings
87 // about (unused) inline functions being removed. This is to be expected with
88 // templates, so we disable the warning.
89 #pragma warning( disable: 4514 )
90 #endif
92 #define NSCAP_FEATURE_USE_BASE
94 #ifdef NS_DEBUG
95 #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
96 #undef NSCAP_FEATURE_USE_BASE
97 //#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
98 #endif
101 |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is
102 problematic on a select few of our platforms, e.g., QNX. Therefore, I'm providing
103 a mechanism by which these features can be explicitly disabled from the command-line.
106 #ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
107 #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
108 #endif
110 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
111 // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
112 // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
113 // don't reorder instructions based on aliasing assumptions for
114 // this variable. Fortunately, gcc versions < 3.3 do not do any
115 // optimizations that break nsCOMPtr.
117 #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
118 #else
119 #define NS_MAY_ALIAS_PTR(t) t*
120 #endif
122 #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
123 #define NSCAP_FEATURE_USE_BASE
124 #endif
127 #ifdef HAVE_CPP_BOOL
128 typedef bool NSCAP_BOOL;
129 #else
130 typedef PRBool NSCAP_BOOL;
131 #endif
137 The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
138 allow external clients the ability to add logging or other interesting debug facilities.
139 In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
140 provide (e.g., in "nsTraceRefcnt.h") suitable definitions
142 #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
143 #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
146 #ifndef NSCAP_ADDREF
147 #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
148 #endif
150 #ifndef NSCAP_RELEASE
151 #define NSCAP_RELEASE(this, ptr) (ptr)->Release()
152 #endif
154 // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
155 #ifdef NSCAP_LOG_ASSIGNMENT
156 // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
157 // to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
158 // the |nsCOMPtr|.
159 #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
160 #else
161 // ...otherwise, just strip it out of the code
162 #define NSCAP_LOG_ASSIGNMENT(this, ptr)
163 #endif
165 #ifndef NSCAP_LOG_RELEASE
166 #define NSCAP_LOG_RELEASE(this, ptr)
167 #endif
173 WARNING:
174 VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
175 in an order that satisfies:
177 nsDerivedSafe < nsCOMPtr
178 already_AddRefed < nsCOMPtr
179 nsCOMPtr < nsGetterAddRefs
181 The other compilers probably won't complain, so please don't reorder these
182 classes, on pain of breaking 4.2 compatibility.
186 template <class T>
187 class
188 NS_FINAL_CLASS
189 NS_STACK_CLASS
190 nsDerivedSafe : public T
192 No client should ever see or have to type the name of this class. It is the
193 artifact that makes it a compile-time error to call |AddRef| and |Release|
194 on a |nsCOMPtr|. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
196 See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
198 This type should be a nested class inside |nsCOMPtr<T>|.
201 private:
202 #ifdef HAVE_CPP_ACCESS_CHANGING_USING
203 using T::AddRef;
204 using T::Release;
205 #else
206 nsrefcnt AddRef(void);
207 nsrefcnt Release(void);
208 #endif
210 #if !defined(AIX) && !defined(IRIX)
211 void operator delete( void*, size_t ); // NOT TO BE IMPLEMENTED
212 // declaring |operator delete| private makes calling delete on an interface pointer a compile error
213 #endif
215 nsDerivedSafe<T>& operator=( const T& ); // NOT TO BE IMPLEMENTED
216 // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
219 Compiler warnings and errors: nsDerivedSafe operator=() hides inherited operator=().
220 If you see that, that means somebody checked in a [XP]COM interface class that declares an
221 |operator=()|, and that's _bad_. So bad, in fact, that this declaration exists explicitly
222 to stop people from doing it.
225 protected:
226 nsDerivedSafe(); // NOT TO BE IMPLEMENTED
228 This ctor exists to avoid compile errors and warnings about nsDeriviedSafe using the
229 default ctor but inheriting classes without an empty ctor. See bug 209667.
233 #if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMENTATIONS)
234 template <class T>
235 nsrefcnt
236 nsDerivedSafe<T>::AddRef()
238 return 0;
241 template <class T>
242 nsrefcnt
243 nsDerivedSafe<T>::Release()
245 return 0;
248 #endif
252 template <class T>
253 struct already_AddRefed
255 ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
256 |AddRef|ing it. You might want to use this as a return type from a function
257 that produces an already |AddRef|ed pointer as a result.
259 See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
261 This type should be a nested class inside |nsCOMPtr<T>|.
263 Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
264 avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
265 case, and perhaps worth the savings in time and space that its specific
266 implementation affords over the more general solution offered by
267 |nsCOMPtr_helper|.
270 already_AddRefed( T* aRawPtr )
271 : mRawPtr(aRawPtr)
273 // nothing else to do here
276 T* get() const { return mRawPtr; }
278 T* mRawPtr;
281 template <class T>
282 inline
283 const already_AddRefed<T>
284 getter_AddRefs( T* aRawPtr )
286 ...makes typing easier, because it deduces the template type, e.g.,
287 you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
290 return already_AddRefed<T>(aRawPtr);
293 template <class T>
294 inline
295 const already_AddRefed<T>
296 getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
298 return aAlreadyAddRefedPtr;
301 template <class T>
302 inline
303 const already_AddRefed<T>
304 dont_AddRef( T* aRawPtr )
306 return already_AddRefed<T>(aRawPtr);
309 template <class T>
310 inline
311 const already_AddRefed<T>
312 dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
314 return aAlreadyAddRefedPtr;
319 class nsCOMPtr_helper
321 An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
322 that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
323 Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
325 Here are the rules for a helper:
326 - it implements |operator()| to produce an interface pointer
327 - (except for its name) |operator()| is a valid [XP]COM `getter'
328 - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
329 - it matches the type requested with the supplied |nsIID| argument
330 - its constructor provides an optional |nsresult*| that |operator()| can fill
331 in with an error when it is executed
333 See |class nsGetInterface| for an example.
336 public:
337 virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
341 |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
342 avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
343 is called often enough that the codesize savings are big enough to
344 warrant the specialcasing.
347 class
348 NS_COM_GLUE
349 NS_STACK_CLASS
350 NS_FINAL_CLASS
351 nsQueryInterface
353 public:
354 explicit
355 nsQueryInterface( nsISupports* aRawPtr )
356 : mRawPtr(aRawPtr)
358 // nothing else to do here
361 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
363 private:
364 nsISupports* mRawPtr;
367 class NS_COM_GLUE nsQueryInterfaceWithError
369 public:
370 nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
371 : mRawPtr(aRawPtr),
372 mErrorPtr(error)
374 // nothing else to do here
377 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
379 private:
380 nsISupports* mRawPtr;
381 nsresult* mErrorPtr;
384 inline
385 nsQueryInterface
386 do_QueryInterface( nsISupports* aRawPtr )
388 return nsQueryInterface(aRawPtr);
391 inline
392 nsQueryInterfaceWithError
393 do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
395 return nsQueryInterfaceWithError(aRawPtr, error);
398 template <class T>
399 inline
400 void
401 do_QueryInterface( already_AddRefed<T>& )
403 // This signature exists solely to _stop_ you from doing the bad thing.
404 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
405 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
408 template <class T>
409 inline
410 void
411 do_QueryInterface( already_AddRefed<T>&, nsresult* )
413 // This signature exists solely to _stop_ you from doing the bad thing.
414 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
415 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
419 ////////////////////////////////////////////////////////////////////////////
420 // Using servicemanager with COMPtrs
421 class NS_COM_GLUE nsGetServiceByCID
423 public:
424 explicit nsGetServiceByCID(const nsCID& aCID)
425 : mCID(aCID)
427 // nothing else to do
430 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
432 private:
433 const nsCID& mCID;
436 class NS_COM_GLUE nsGetServiceByCIDWithError
438 public:
439 nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
440 : mCID(aCID),
441 mErrorPtr(aErrorPtr)
443 // nothing else to do
446 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
448 private:
449 const nsCID& mCID;
450 nsresult* mErrorPtr;
453 class NS_COM_GLUE nsGetServiceByContractID
455 public:
456 explicit nsGetServiceByContractID(const char* aContractID)
457 : mContractID(aContractID)
459 // nothing else to do
462 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
464 private:
465 const char* mContractID;
468 class NS_COM_GLUE nsGetServiceByContractIDWithError
470 public:
471 nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
472 : mContractID(aContractID),
473 mErrorPtr(aErrorPtr)
475 // nothing else to do
478 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
480 private:
481 const char* mContractID;
482 nsresult* mErrorPtr;
485 class
486 nsCOMPtr_base
488 ...factors implementation for all template versions of |nsCOMPtr|.
490 This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
491 because unlike the
493 Here's the way people normally do things like this
495 template <class T> class Foo { ... };
496 template <> class Foo<void*> { ... };
497 template <class T> class Foo<T*> : private Foo<void*> { ... };
500 public:
502 nsCOMPtr_base( nsISupports* rawPtr = 0 )
503 : mRawPtr(rawPtr)
505 // nothing else to do here
508 NS_COM_GLUE NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base();
510 NS_COM_GLUE void NS_FASTCALL assign_with_AddRef( nsISupports* );
511 NS_COM_GLUE void NS_FASTCALL assign_from_qi( const nsQueryInterface, const nsIID& );
512 NS_COM_GLUE void NS_FASTCALL assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
513 NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
514 NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
515 NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
516 NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
517 NS_COM_GLUE void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
518 NS_COM_GLUE void** NS_FASTCALL begin_assignment();
520 protected:
521 NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
523 void
524 assign_assuming_AddRef( nsISupports* newPtr )
527 |AddRef()|ing the new value (before entering this function) before
528 |Release()|ing the old lets us safely ignore the self-assignment case.
529 We must, however, be careful only to |Release()| _after_ doing the
530 assignment, in case the |Release()| leads to our _own_ destruction,
531 which would, in turn, cause an incorrect second |Release()| of our old
532 pointer. Thank <waterson@netscape.com> for discovering this.
534 nsISupports* oldPtr = mRawPtr;
535 mRawPtr = newPtr;
536 NSCAP_LOG_ASSIGNMENT(this, newPtr);
537 NSCAP_LOG_RELEASE(this, oldPtr);
538 if ( oldPtr )
539 NSCAP_RELEASE(this, oldPtr);
543 // template <class T> class nsGetterAddRefs;
545 template <class T>
546 class
547 NS_FINAL_CLASS
548 nsCOMPtr
549 #ifdef NSCAP_FEATURE_USE_BASE
550 : private nsCOMPtr_base
551 #endif
554 #ifdef NSCAP_FEATURE_USE_BASE
555 #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
556 #else
557 #define NSCAP_CTOR_BASE(x) mRawPtr(x)
559 private:
560 void assign_with_AddRef( nsISupports* );
561 void assign_from_qi( const nsQueryInterface, const nsIID& );
562 void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
563 void assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
564 void assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
565 void assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
566 void assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
567 void assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
568 void** begin_assignment();
570 void
571 assign_assuming_AddRef( T* newPtr )
573 T* oldPtr = mRawPtr;
574 mRawPtr = newPtr;
575 NSCAP_LOG_ASSIGNMENT(this, newPtr);
576 NSCAP_LOG_RELEASE(this, oldPtr);
577 if ( oldPtr )
578 NSCAP_RELEASE(this, oldPtr);
581 private:
582 T* mRawPtr;
583 #endif
585 public:
586 typedef T element_type;
588 #ifndef NSCAP_FEATURE_USE_BASE
589 ~nsCOMPtr()
591 NSCAP_LOG_RELEASE(this, mRawPtr);
592 if ( mRawPtr )
593 NSCAP_RELEASE(this, mRawPtr);
595 #endif
597 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
598 void
599 Assert_NoQueryNeeded()
601 if ( mRawPtr )
603 nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
604 NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
608 #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
609 #else
610 #define NSCAP_ASSERT_NO_QUERY_NEEDED()
611 #endif
614 // Constructors
616 nsCOMPtr()
617 : NSCAP_CTOR_BASE(0)
618 // default constructor
620 NSCAP_LOG_ASSIGNMENT(this, 0);
623 nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
624 : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
625 // copy-constructor
627 if ( mRawPtr )
628 NSCAP_ADDREF(this, mRawPtr);
629 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
632 nsCOMPtr( T* aRawPtr )
633 : NSCAP_CTOR_BASE(aRawPtr)
634 // construct from a raw pointer (of the right type)
636 if ( mRawPtr )
637 NSCAP_ADDREF(this, mRawPtr);
638 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
639 NSCAP_ASSERT_NO_QUERY_NEEDED();
642 nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
643 : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
644 // construct from |dont_AddRef(expr)|
646 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
647 NSCAP_ASSERT_NO_QUERY_NEEDED();
650 nsCOMPtr( const nsQueryInterface qi )
651 : NSCAP_CTOR_BASE(0)
652 // construct from |do_QueryInterface(expr)|
654 NSCAP_LOG_ASSIGNMENT(this, 0);
655 assign_from_qi(qi, NS_GET_TEMPLATE_IID(T));
658 nsCOMPtr( const nsQueryInterfaceWithError& qi )
659 : NSCAP_CTOR_BASE(0)
660 // construct from |do_QueryInterface(expr, &rv)|
662 NSCAP_LOG_ASSIGNMENT(this, 0);
663 assign_from_qi_with_error(qi, NS_GET_TEMPLATE_IID(T));
666 nsCOMPtr( const nsGetServiceByCID gs )
667 : NSCAP_CTOR_BASE(0)
668 // construct from |do_GetService(cid_expr)|
670 NSCAP_LOG_ASSIGNMENT(this, 0);
671 assign_from_gs_cid(gs, NS_GET_TEMPLATE_IID(T));
674 nsCOMPtr( const nsGetServiceByCIDWithError& gs )
675 : NSCAP_CTOR_BASE(0)
676 // construct from |do_GetService(cid_expr, &rv)|
678 NSCAP_LOG_ASSIGNMENT(this, 0);
679 assign_from_gs_cid_with_error(gs, NS_GET_TEMPLATE_IID(T));
682 nsCOMPtr( const nsGetServiceByContractID gs )
683 : NSCAP_CTOR_BASE(0)
684 // construct from |do_GetService(contractid_expr)|
686 NSCAP_LOG_ASSIGNMENT(this, 0);
687 assign_from_gs_contractid(gs, NS_GET_TEMPLATE_IID(T));
690 nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
691 : NSCAP_CTOR_BASE(0)
692 // construct from |do_GetService(contractid_expr, &rv)|
694 NSCAP_LOG_ASSIGNMENT(this, 0);
695 assign_from_gs_contractid_with_error(gs, NS_GET_TEMPLATE_IID(T));
698 nsCOMPtr( const nsCOMPtr_helper& helper )
699 : NSCAP_CTOR_BASE(0)
700 // ...and finally, anything else we might need to construct from
701 // can exploit the |nsCOMPtr_helper| facility
703 NSCAP_LOG_ASSIGNMENT(this, 0);
704 assign_from_helper(helper, NS_GET_TEMPLATE_IID(T));
705 NSCAP_ASSERT_NO_QUERY_NEEDED();
709 // Assignment operators
711 nsCOMPtr<T>&
712 operator=( const nsCOMPtr<T>& rhs )
713 // copy assignment operator
715 assign_with_AddRef(rhs.mRawPtr);
716 return *this;
719 nsCOMPtr<T>&
720 operator=( T* rhs )
721 // assign from a raw pointer (of the right type)
723 assign_with_AddRef(rhs);
724 NSCAP_ASSERT_NO_QUERY_NEEDED();
725 return *this;
728 nsCOMPtr<T>&
729 operator=( const already_AddRefed<T>& rhs )
730 // assign from |dont_AddRef(expr)|
732 assign_assuming_AddRef(rhs.mRawPtr);
733 NSCAP_ASSERT_NO_QUERY_NEEDED();
734 return *this;
737 nsCOMPtr<T>&
738 operator=( const nsQueryInterface rhs )
739 // assign from |do_QueryInterface(expr)|
741 assign_from_qi(rhs, NS_GET_TEMPLATE_IID(T));
742 return *this;
745 nsCOMPtr<T>&
746 operator=( const nsQueryInterfaceWithError& rhs )
747 // assign from |do_QueryInterface(expr, &rv)|
749 assign_from_qi_with_error(rhs, NS_GET_TEMPLATE_IID(T));
750 return *this;
753 nsCOMPtr<T>&
754 operator=( const nsGetServiceByCID rhs )
755 // assign from |do_GetService(cid_expr)|
757 assign_from_gs_cid(rhs, NS_GET_TEMPLATE_IID(T));
758 return *this;
761 nsCOMPtr<T>&
762 operator=( const nsGetServiceByCIDWithError& rhs )
763 // assign from |do_GetService(cid_expr, &rv)|
765 assign_from_gs_cid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
766 return *this;
769 nsCOMPtr<T>&
770 operator=( const nsGetServiceByContractID rhs )
771 // assign from |do_GetService(contractid_expr)|
773 assign_from_gs_contractid(rhs, NS_GET_TEMPLATE_IID(T));
774 return *this;
777 nsCOMPtr<T>&
778 operator=( const nsGetServiceByContractIDWithError& rhs )
779 // assign from |do_GetService(contractid_expr, &rv)|
781 assign_from_gs_contractid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
782 return *this;
785 nsCOMPtr<T>&
786 operator=( const nsCOMPtr_helper& rhs )
787 // ...and finally, anything else we might need to assign from
788 // can exploit the |nsCOMPtr_helper| facility.
790 assign_from_helper(rhs, NS_GET_TEMPLATE_IID(T));
791 NSCAP_ASSERT_NO_QUERY_NEEDED();
792 return *this;
795 void
796 swap( nsCOMPtr<T>& rhs )
797 // ...exchange ownership with |rhs|; can save a pair of refcount operations
799 #ifdef NSCAP_FEATURE_USE_BASE
800 nsISupports* temp = rhs.mRawPtr;
801 #else
802 T* temp = rhs.mRawPtr;
803 #endif
804 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
805 NSCAP_LOG_ASSIGNMENT(this, temp);
806 NSCAP_LOG_RELEASE(this, mRawPtr);
807 NSCAP_LOG_RELEASE(&rhs, temp);
808 rhs.mRawPtr = mRawPtr;
809 mRawPtr = temp;
810 // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
813 void
814 swap( T*& rhs )
815 // ...exchange ownership with |rhs|; can save a pair of refcount operations
817 #ifdef NSCAP_FEATURE_USE_BASE
818 nsISupports* temp = rhs;
819 #else
820 T* temp = rhs;
821 #endif
822 NSCAP_LOG_ASSIGNMENT(this, temp);
823 NSCAP_LOG_RELEASE(this, mRawPtr);
824 rhs = reinterpret_cast<T*>(mRawPtr);
825 mRawPtr = temp;
826 NSCAP_ASSERT_NO_QUERY_NEEDED();
830 // Other pointer operators
832 already_AddRefed<T>
833 forget()
834 // return the value of mRawPtr and null out mRawPtr. Useful for
835 // already_AddRefed return values.
837 T* temp = 0;
838 swap(temp);
839 return temp;
842 void
843 forget( T** rhs )
844 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
845 // Useful to avoid unnecessary AddRef/Release pairs with "out"
846 // parameters.
848 NS_ASSERTION(rhs, "Null pointer passed to forget!");
849 *rhs = 0;
850 swap(*rhs);
854 get() const
856 Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
857 Use |get()| to resolve ambiguity or to get a castable pointer.
860 return reinterpret_cast<T*>(mRawPtr);
863 operator nsDerivedSafe<T>*() const
865 ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
866 and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
867 that makes an |nsCOMPtr| substitutable for a raw pointer.
869 Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
872 return get_DerivedSafe();
875 nsDerivedSafe<T>*
876 operator->() const
878 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
879 return get_DerivedSafe();
882 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
883 // broken version for IRIX
885 nsCOMPtr<T>*
886 get_address() const
887 // This is not intended to be used by clients. See |address_of|
888 // below.
890 return const_cast<nsCOMPtr<T>*>(this);
893 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
895 nsCOMPtr<T>*
896 get_address()
897 // This is not intended to be used by clients. See |address_of|
898 // below.
900 return this;
903 const nsCOMPtr<T>*
904 get_address() const
905 // This is not intended to be used by clients. See |address_of|
906 // below.
908 return this;
911 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
913 public:
914 nsDerivedSafe<T>&
915 operator*() const
917 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
918 return *get_DerivedSafe();
921 #if 0
922 private:
923 friend class nsGetterAddRefs<T>;
924 #endif
927 StartAssignment()
929 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
930 return reinterpret_cast<T**>(begin_assignment());
931 #else
932 assign_assuming_AddRef(0);
933 return reinterpret_cast<T**>(&mRawPtr);
934 #endif
937 private:
938 nsDerivedSafe<T>*
939 get_DerivedSafe() const
941 return reinterpret_cast<nsDerivedSafe<T>*>(mRawPtr);
949 Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
950 same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
951 to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able
952 to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
953 querying ensues. Clients need to be able to pass around arbitrary interface pointers,
954 without hassles, through intermediary code that doesn't know the exact type.
957 NS_SPECIALIZE_TEMPLATE
958 class nsCOMPtr<nsISupports>
959 : private nsCOMPtr_base
961 public:
962 typedef nsISupports element_type;
964 // Constructors
966 nsCOMPtr()
967 : nsCOMPtr_base(0)
968 // default constructor
970 NSCAP_LOG_ASSIGNMENT(this, 0);
973 nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
974 : nsCOMPtr_base(aSmartPtr.mRawPtr)
975 // copy constructor
977 if ( mRawPtr )
978 NSCAP_ADDREF(this, mRawPtr);
979 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
982 nsCOMPtr( nsISupports* aRawPtr )
983 : nsCOMPtr_base(aRawPtr)
984 // construct from a raw pointer (of the right type)
986 if ( mRawPtr )
987 NSCAP_ADDREF(this, mRawPtr);
988 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
991 nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
992 : nsCOMPtr_base(aSmartPtr.mRawPtr)
993 // construct from |dont_AddRef(expr)|
995 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
998 nsCOMPtr( const nsQueryInterface qi )
999 : nsCOMPtr_base(0)
1000 // assign from |do_QueryInterface(expr)|
1002 NSCAP_LOG_ASSIGNMENT(this, 0);
1003 assign_from_qi(qi, NS_GET_IID(nsISupports));
1006 nsCOMPtr( const nsQueryInterfaceWithError& qi )
1007 : nsCOMPtr_base(0)
1008 // assign from |do_QueryInterface(expr, &rv)|
1010 NSCAP_LOG_ASSIGNMENT(this, 0);
1011 assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
1014 nsCOMPtr( const nsGetServiceByCID gs )
1015 : nsCOMPtr_base(0)
1016 // assign from |do_GetService(cid_expr)|
1018 NSCAP_LOG_ASSIGNMENT(this, 0);
1019 assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
1022 nsCOMPtr( const nsGetServiceByCIDWithError& gs )
1023 : nsCOMPtr_base(0)
1024 // assign from |do_GetService(cid_expr, &rv)|
1026 NSCAP_LOG_ASSIGNMENT(this, 0);
1027 assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
1030 nsCOMPtr( const nsGetServiceByContractID gs )
1031 : nsCOMPtr_base(0)
1032 // assign from |do_GetService(contractid_expr)|
1034 NSCAP_LOG_ASSIGNMENT(this, 0);
1035 assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
1038 nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
1039 : nsCOMPtr_base(0)
1040 // assign from |do_GetService(contractid_expr, &rv)|
1042 NSCAP_LOG_ASSIGNMENT(this, 0);
1043 assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
1046 nsCOMPtr( const nsCOMPtr_helper& helper )
1047 : nsCOMPtr_base(0)
1048 // ...and finally, anything else we might need to construct from
1049 // can exploit the |nsCOMPtr_helper| facility
1051 NSCAP_LOG_ASSIGNMENT(this, 0);
1052 assign_from_helper(helper, NS_GET_IID(nsISupports));
1056 // Assignment operators
1058 nsCOMPtr<nsISupports>&
1059 operator=( const nsCOMPtr<nsISupports>& rhs )
1060 // copy assignment operator
1062 assign_with_AddRef(rhs.mRawPtr);
1063 return *this;
1066 nsCOMPtr<nsISupports>&
1067 operator=( nsISupports* rhs )
1068 // assign from a raw pointer (of the right type)
1070 assign_with_AddRef(rhs);
1071 return *this;
1074 nsCOMPtr<nsISupports>&
1075 operator=( const already_AddRefed<nsISupports>& rhs )
1076 // assign from |dont_AddRef(expr)|
1078 assign_assuming_AddRef(rhs.mRawPtr);
1079 return *this;
1082 nsCOMPtr<nsISupports>&
1083 operator=( const nsQueryInterface rhs )
1084 // assign from |do_QueryInterface(expr)|
1086 assign_from_qi(rhs, NS_GET_IID(nsISupports));
1087 return *this;
1090 nsCOMPtr<nsISupports>&
1091 operator=( const nsQueryInterfaceWithError& rhs )
1092 // assign from |do_QueryInterface(expr, &rv)|
1094 assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
1095 return *this;
1098 nsCOMPtr<nsISupports>&
1099 operator=( const nsGetServiceByCID rhs )
1100 // assign from |do_GetService(cid_expr)|
1102 assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
1103 return *this;
1106 nsCOMPtr<nsISupports>&
1107 operator=( const nsGetServiceByCIDWithError& rhs )
1108 // assign from |do_GetService(cid_expr, &rv)|
1110 assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
1111 return *this;
1114 nsCOMPtr<nsISupports>&
1115 operator=( const nsGetServiceByContractID rhs )
1116 // assign from |do_GetService(contractid_expr)|
1118 assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
1119 return *this;
1122 nsCOMPtr<nsISupports>&
1123 operator=( const nsGetServiceByContractIDWithError& rhs )
1124 // assign from |do_GetService(contractid_expr, &rv)|
1126 assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
1127 return *this;
1130 nsCOMPtr<nsISupports>&
1131 operator=( const nsCOMPtr_helper& rhs )
1132 // ...and finally, anything else we might need to assign from
1133 // can exploit the |nsCOMPtr_helper| facility.
1135 assign_from_helper(rhs, NS_GET_IID(nsISupports));
1136 return *this;
1139 void
1140 swap( nsCOMPtr<nsISupports>& rhs )
1141 // ...exchange ownership with |rhs|; can save a pair of refcount operations
1143 nsISupports* temp = rhs.mRawPtr;
1144 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
1145 NSCAP_LOG_ASSIGNMENT(this, temp);
1146 NSCAP_LOG_RELEASE(this, mRawPtr);
1147 NSCAP_LOG_RELEASE(&rhs, temp);
1148 rhs.mRawPtr = mRawPtr;
1149 mRawPtr = temp;
1152 void
1153 swap( nsISupports*& rhs )
1154 // ...exchange ownership with |rhs|; can save a pair of refcount operations
1156 nsISupports* temp = rhs;
1157 NSCAP_LOG_ASSIGNMENT(this, temp);
1158 NSCAP_LOG_RELEASE(this, mRawPtr);
1159 rhs = mRawPtr;
1160 mRawPtr = temp;
1163 void
1164 forget( nsISupports** rhs )
1165 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
1166 // Useful to avoid unnecessary AddRef/Release pairs with "out"
1167 // parameters.
1169 NS_ASSERTION(rhs, "Null pointer passed to forget!");
1170 *rhs = 0;
1171 swap(*rhs);
1174 // Other pointer operators
1176 nsISupports*
1177 get() const
1179 Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
1180 Use |get()| to resolve ambiguity or to get a castable pointer.
1183 return reinterpret_cast<nsISupports*>(mRawPtr);
1186 operator nsDerivedSafe<nsISupports>*() const
1188 ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
1189 and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
1190 that makes an |nsCOMPtr| substitutable for a raw pointer.
1192 Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
1195 return get_DerivedSafe();
1198 nsDerivedSafe<nsISupports>*
1199 operator->() const
1201 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
1202 return get_DerivedSafe();
1205 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
1206 // broken version for IRIX
1208 nsCOMPtr<nsISupports>*
1209 get_address() const
1210 // This is not intended to be used by clients. See |address_of|
1211 // below.
1213 return const_cast<nsCOMPtr<nsISupports>*>(this);
1216 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1218 nsCOMPtr<nsISupports>*
1219 get_address()
1220 // This is not intended to be used by clients. See |address_of|
1221 // below.
1223 return this;
1226 const nsCOMPtr<nsISupports>*
1227 get_address() const
1228 // This is not intended to be used by clients. See |address_of|
1229 // below.
1231 return this;
1234 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1236 public:
1238 nsDerivedSafe<nsISupports>&
1239 operator*() const
1241 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
1242 return *get_DerivedSafe();
1245 #if 0
1246 private:
1247 friend class nsGetterAddRefs<nsISupports>;
1248 #endif
1250 nsISupports**
1251 StartAssignment()
1253 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
1254 return reinterpret_cast<nsISupports**>(begin_assignment());
1255 #else
1256 assign_assuming_AddRef(0);
1257 return reinterpret_cast<nsISupports**>(&mRawPtr);
1258 #endif
1261 private:
1262 nsDerivedSafe<nsISupports>*
1263 get_DerivedSafe() const
1265 return reinterpret_cast<nsDerivedSafe<nsISupports>*>(mRawPtr);
1270 #ifndef NSCAP_FEATURE_USE_BASE
1271 template <class T>
1272 void
1273 nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
1275 if ( rawPtr )
1276 NSCAP_ADDREF(this, rawPtr);
1277 assign_assuming_AddRef(reinterpret_cast<T*>(rawPtr));
1280 template <class T>
1281 void
1282 nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
1284 void* newRawPtr;
1285 if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
1286 newRawPtr = 0;
1287 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1290 template <class T>
1291 void
1292 nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
1294 void* newRawPtr;
1295 if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
1296 newRawPtr = 0;
1297 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1300 template <class T>
1301 void
1302 nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
1304 void* newRawPtr;
1305 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1306 newRawPtr = 0;
1307 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1310 template <class T>
1311 void
1312 nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
1314 void* newRawPtr;
1315 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1316 newRawPtr = 0;
1317 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1320 template <class T>
1321 void
1322 nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
1324 void* newRawPtr;
1325 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1326 newRawPtr = 0;
1327 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1330 template <class T>
1331 void
1332 nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
1334 void* newRawPtr;
1335 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1336 newRawPtr = 0;
1337 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1340 template <class T>
1341 void
1342 nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
1344 void* newRawPtr;
1345 if ( NS_FAILED( helper(aIID, &newRawPtr) ) )
1346 newRawPtr = 0;
1347 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1350 template <class T>
1351 void**
1352 nsCOMPtr<T>::begin_assignment()
1354 assign_assuming_AddRef(0);
1355 union { T** mT; void** mVoid; } result;
1356 result.mT = &mRawPtr;
1357 return result.mVoid;
1359 #endif
1361 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
1363 // This is the broken version for IRIX, which can't handle the version below.
1365 template <class T>
1366 inline
1367 nsCOMPtr<T>*
1368 address_of( const nsCOMPtr<T>& aPtr )
1370 return aPtr.get_address();
1373 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1375 template <class T>
1376 inline
1377 nsCOMPtr<T>*
1378 address_of( nsCOMPtr<T>& aPtr )
1380 return aPtr.get_address();
1383 template <class T>
1384 inline
1385 const nsCOMPtr<T>*
1386 address_of( const nsCOMPtr<T>& aPtr )
1388 return aPtr.get_address();
1391 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1393 template <class T>
1394 class nsGetterAddRefs
1398 This class is designed to be used for anonymous temporary objects in the
1399 argument list of calls that return COM interface pointers, e.g.,
1401 nsCOMPtr<IFoo> fooP;
1402 ...->QueryInterface(iid, getter_AddRefs(fooP))
1404 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
1406 When initialized with a |nsCOMPtr|, as in the example above, it returns
1407 a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
1408 case) can fill in.
1410 This type should be a nested class inside |nsCOMPtr<T>|.
1413 public:
1414 explicit
1415 nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
1416 : mTargetSmartPtr(aSmartPtr)
1418 // nothing else to do
1421 #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
1422 ~nsGetterAddRefs()
1424 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1425 NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
1426 #endif
1428 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
1429 mTargetSmartPtr.Assert_NoQueryNeeded();
1430 #endif
1432 #endif
1434 operator void**()
1436 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1439 operator nsISupports**()
1441 return reinterpret_cast<nsISupports**>(mTargetSmartPtr.StartAssignment());
1444 operator T**()
1446 return mTargetSmartPtr.StartAssignment();
1450 operator*()
1452 return *(mTargetSmartPtr.StartAssignment());
1455 private:
1456 nsCOMPtr<T>& mTargetSmartPtr;
1460 NS_SPECIALIZE_TEMPLATE
1461 class nsGetterAddRefs<nsISupports>
1463 public:
1464 explicit
1465 nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
1466 : mTargetSmartPtr(aSmartPtr)
1468 // nothing else to do
1471 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1472 ~nsGetterAddRefs()
1474 NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
1476 #endif
1478 operator void**()
1480 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1483 operator nsISupports**()
1485 return mTargetSmartPtr.StartAssignment();
1488 nsISupports*&
1489 operator*()
1491 return *(mTargetSmartPtr.StartAssignment());
1494 private:
1495 nsCOMPtr<nsISupports>& mTargetSmartPtr;
1499 template <class T>
1500 inline
1501 nsGetterAddRefs<T>
1502 getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
1504 Used around a |nsCOMPtr| when
1505 ...makes the class |nsGetterAddRefs<T>| invisible.
1508 return nsGetterAddRefs<T>(aSmartPtr);
1513 // Comparing two |nsCOMPtr|s
1515 template <class T, class U>
1516 inline
1517 NSCAP_BOOL
1518 operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1520 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
1524 template <class T, class U>
1525 inline
1526 NSCAP_BOOL
1527 operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1529 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
1533 // Comparing an |nsCOMPtr| to a raw pointer
1535 template <class T, class U>
1536 inline
1537 NSCAP_BOOL
1538 operator==( const nsCOMPtr<T>& lhs, const U* rhs )
1540 return static_cast<const T*>(lhs.get()) == rhs;
1543 template <class T, class U>
1544 inline
1545 NSCAP_BOOL
1546 operator==( const U* lhs, const nsCOMPtr<T>& rhs )
1548 return lhs == static_cast<const T*>(rhs.get());
1551 template <class T, class U>
1552 inline
1553 NSCAP_BOOL
1554 operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
1556 return static_cast<const T*>(lhs.get()) != rhs;
1559 template <class T, class U>
1560 inline
1561 NSCAP_BOOL
1562 operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
1564 return lhs != static_cast<const T*>(rhs.get());
1567 // To avoid ambiguities caused by the presence of builtin |operator==|s
1568 // creating a situation where one of the |operator==| defined above
1569 // has a better conversion for one argument and the builtin has a
1570 // better conversion for the other argument, define additional
1571 // |operator==| without the |const| on the raw pointer.
1572 // See bug 65664 for details.
1574 // This is defined by an autoconf test, but VC++ also has a bug that
1575 // prevents us from using these. (It also, fortunately, has the bug
1576 // that we don't need them either.)
1577 #if defined(_MSC_VER) && (_MSC_VER < 1310)
1578 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1579 #define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1580 #endif
1581 #endif
1583 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1584 template <class T, class U>
1585 inline
1586 NSCAP_BOOL
1587 operator==( const nsCOMPtr<T>& lhs, U* rhs )
1589 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
1592 template <class T, class U>
1593 inline
1594 NSCAP_BOOL
1595 operator==( U* lhs, const nsCOMPtr<T>& rhs )
1597 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
1600 template <class T, class U>
1601 inline
1602 NSCAP_BOOL
1603 operator!=( const nsCOMPtr<T>& lhs, U* rhs )
1605 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
1608 template <class T, class U>
1609 inline
1610 NSCAP_BOOL
1611 operator!=( U* lhs, const nsCOMPtr<T>& rhs )
1613 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
1615 #endif
1619 // Comparing an |nsCOMPtr| to |0|
1621 class NSCAP_Zero;
1623 template <class T>
1624 inline
1625 NSCAP_BOOL
1626 operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1627 // specifically to allow |smartPtr == 0|
1629 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
1632 template <class T>
1633 inline
1634 NSCAP_BOOL
1635 operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1636 // specifically to allow |0 == smartPtr|
1638 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
1641 template <class T>
1642 inline
1643 NSCAP_BOOL
1644 operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1645 // specifically to allow |smartPtr != 0|
1647 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
1650 template <class T>
1651 inline
1652 NSCAP_BOOL
1653 operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1654 // specifically to allow |0 != smartPtr|
1656 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
1660 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
1662 // We need to explicitly define comparison operators for `int'
1663 // because the compiler is lame.
1665 template <class T>
1666 inline
1667 NSCAP_BOOL
1668 operator==( const nsCOMPtr<T>& lhs, int rhs )
1669 // specifically to allow |smartPtr == 0|
1671 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
1674 template <class T>
1675 inline
1676 NSCAP_BOOL
1677 operator==( int lhs, const nsCOMPtr<T>& rhs )
1678 // specifically to allow |0 == smartPtr|
1680 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
1683 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
1685 // Comparing any two [XP]COM objects for identity
1687 inline
1688 NSCAP_BOOL
1689 SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
1691 return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
1696 template <class SourceType, class DestinationType>
1697 inline
1698 nsresult
1699 CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
1701 return CallQueryInterface(aSourcePtr.get(), aDestPtr);
1704 #endif // !defined(nsCOMPtr_h___)