1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/nsCOMPtr.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1661 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsCOMPtr_h___ 1.10 +#define nsCOMPtr_h___ 1.11 + 1.12 +/* 1.13 + Having problems? 1.14 + 1.15 + See the User Manual at: 1.16 + http://www.mozilla.org/projects/xpcom/nsCOMPtr.html 1.17 + 1.18 + 1.19 + nsCOMPtr 1.20 + better than a raw pointer 1.21 + for owning objects 1.22 + -- scc 1.23 +*/ 1.24 + 1.25 +#include "mozilla/Attributes.h" 1.26 +#include "mozilla/TypeTraits.h" 1.27 +#include "mozilla/Assertions.h" 1.28 +#include "mozilla/NullPtr.h" 1.29 +#include "mozilla/Move.h" 1.30 + 1.31 +#include "nsDebug.h" // for |NS_ABORT_IF_FALSE|, |NS_ASSERTION| 1.32 +#include "nsISupportsUtils.h" // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al 1.33 +#include "nscore.h" // for |NS_COM_GLUE| 1.34 + 1.35 +#include "nsCycleCollectionNoteChild.h" 1.36 + 1.37 + 1.38 +/* 1.39 + WARNING: 1.40 + This file defines several macros for internal use only. These macros begin with the 1.41 + prefix |NSCAP_|. Do not use these macros in your own code. They are for internal use 1.42 + only for cross-platform compatibility, and are subject to change without notice. 1.43 +*/ 1.44 + 1.45 + 1.46 +#ifdef _MSC_VER 1.47 + #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT 1.48 + // under VC++, we win by inlining StartAssignment 1.49 + 1.50 + // Also under VC++, at the highest warning level, we are overwhelmed with warnings 1.51 + // about (unused) inline functions being removed. This is to be expected with 1.52 + // templates, so we disable the warning. 1.53 + #pragma warning( disable: 4514 ) 1.54 +#endif 1.55 + 1.56 +#define NSCAP_FEATURE_USE_BASE 1.57 + 1.58 +#ifdef DEBUG 1.59 + #define NSCAP_FEATURE_TEST_DONTQUERY_CASES 1.60 + #undef NSCAP_FEATURE_USE_BASE 1.61 +//#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS 1.62 +#endif 1.63 + 1.64 +#ifdef __GNUC__ 1.65 + // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing 1.66 + // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher 1.67 + // don't reorder instructions based on aliasing assumptions for 1.68 + // this variable. Fortunately, gcc versions < 3.3 do not do any 1.69 + // optimizations that break nsCOMPtr. 1.70 + 1.71 + #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__)) 1.72 +#else 1.73 + #define NS_MAY_ALIAS_PTR(t) t* 1.74 +#endif 1.75 + 1.76 +#if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES) 1.77 + #define NSCAP_FEATURE_USE_BASE 1.78 +#endif 1.79 + 1.80 + /* 1.81 + The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|) 1.82 + allow external clients the ability to add logging or other interesting debug facilities. 1.83 + In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you 1.84 + provide (e.g., in "nsISupportsImpl.h") suitable definitions 1.85 + 1.86 + #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr) 1.87 + #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr) 1.88 + */ 1.89 + 1.90 +#ifndef NSCAP_ADDREF 1.91 + #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef() 1.92 +#endif 1.93 + 1.94 +#ifndef NSCAP_RELEASE 1.95 + #define NSCAP_RELEASE(this, ptr) (ptr)->Release() 1.96 +#endif 1.97 + 1.98 + // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging. 1.99 +#ifdef NSCAP_LOG_ASSIGNMENT 1.100 + // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know 1.101 + // to instantiate |~nsGetterAddRefs| in turn to note the external assignment into 1.102 + // the |nsCOMPtr|. 1.103 + #define NSCAP_LOG_EXTERNAL_ASSIGNMENT 1.104 +#else 1.105 + // ...otherwise, just strip it out of the code 1.106 + #define NSCAP_LOG_ASSIGNMENT(this, ptr) 1.107 +#endif 1.108 + 1.109 +#ifndef NSCAP_LOG_RELEASE 1.110 + #define NSCAP_LOG_RELEASE(this, ptr) 1.111 +#endif 1.112 + 1.113 +namespace mozilla { 1.114 + 1.115 +struct unused_t; 1.116 + 1.117 +} // namespace mozilla 1.118 + 1.119 +template <class T> 1.120 +struct already_AddRefed 1.121 + /* 1.122 + ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_ 1.123 + |AddRef|ing it. You might want to use this as a return type from a function 1.124 + that produces an already |AddRef|ed pointer as a result. 1.125 + 1.126 + See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|. 1.127 + 1.128 + This type should be a nested class inside |nsCOMPtr<T>|. 1.129 + 1.130 + Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to 1.131 + avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest 1.132 + case, and perhaps worth the savings in time and space that its specific 1.133 + implementation affords over the more general solution offered by 1.134 + |nsCOMPtr_helper|. 1.135 + */ 1.136 + { 1.137 + /* 1.138 + * Prohibit all one-argument overloads but already_AddRefed(T*) and 1.139 + * already_AddRefed(decltype(nullptr)), and funnel the nullptr case through 1.140 + * the T* constructor. 1.141 + */ 1.142 + template<typename N> 1.143 + already_AddRefed(N, 1.144 + typename mozilla::EnableIf<mozilla::IsNullPointer<N>::value, 1.145 + int>::Type dummy = 0) 1.146 + : mRawPtr(nullptr) 1.147 + { 1.148 + // nothing else to do here 1.149 + } 1.150 + 1.151 + already_AddRefed( T* aRawPtr ) 1.152 + : mRawPtr(aRawPtr) 1.153 + { 1.154 + // nothing else to do here 1.155 + } 1.156 + 1.157 + // Disallowed. Use move semantics instead. 1.158 + already_AddRefed(const already_AddRefed<T>& aOther) MOZ_DELETE; 1.159 + 1.160 + already_AddRefed(already_AddRefed<T>&& aOther) 1.161 + : mRawPtr(aOther.take()) 1.162 + { 1.163 + // nothing else to do here 1.164 + } 1.165 + 1.166 + ~already_AddRefed() 1.167 + { 1.168 + MOZ_ASSERT(!mRawPtr); 1.169 + } 1.170 + 1.171 + // Specialize the unused operator<< for already_AddRefed, to allow 1.172 + // nsCOMPtr<nsIFoo> foo; 1.173 + // unused << foo.forget(); 1.174 + friend void operator<<(const mozilla::unused_t& unused, 1.175 + const already_AddRefed<T>& rhs) 1.176 + { 1.177 + auto mutableAlreadyAddRefed = const_cast<already_AddRefed<T>*>(&rhs); 1.178 + unused << mutableAlreadyAddRefed->take(); 1.179 + } 1.180 + 1.181 + MOZ_WARN_UNUSED_RESULT T* take() 1.182 + { 1.183 + T* rawPtr = mRawPtr; 1.184 + mRawPtr = nullptr; 1.185 + return rawPtr; 1.186 + } 1.187 + 1.188 + /** 1.189 + * This helper is useful in cases like 1.190 + * 1.191 + * already_AddRefed<BaseClass> 1.192 + * Foo() 1.193 + * { 1.194 + * nsRefPtr<SubClass> x = ...; 1.195 + * return x.forget(); 1.196 + * } 1.197 + * 1.198 + * The autoconversion allows one to omit the idiom 1.199 + * 1.200 + * nsRefPtr<BaseClass> y = x.forget(); 1.201 + * return y.forget(); 1.202 + */ 1.203 + template<class U> 1.204 + operator already_AddRefed<U>() 1.205 + { 1.206 + U* tmp = mRawPtr; 1.207 + mRawPtr = nullptr; 1.208 + return already_AddRefed<U>(tmp); 1.209 + } 1.210 + 1.211 + /** 1.212 + * This helper provides a static_cast replacement for already_AddRefed, so 1.213 + * if you have 1.214 + * 1.215 + * already_AddRefed<Parent> F(); 1.216 + * 1.217 + * you can write 1.218 + * 1.219 + * already_AddRefed<Child> 1.220 + * G() 1.221 + * { 1.222 + * return F().downcast<Child>(); 1.223 + * } 1.224 + * 1.225 + * instead of 1.226 + * 1.227 + * return dont_AddRef(static_cast<Child*>(F().get())); 1.228 + */ 1.229 + template<class U> 1.230 + already_AddRefed<U> downcast() 1.231 + { 1.232 + U* tmp = static_cast<U*>(mRawPtr); 1.233 + mRawPtr = nullptr; 1.234 + return already_AddRefed<U>(tmp); 1.235 + } 1.236 + 1.237 + private: 1.238 + T* mRawPtr; 1.239 + }; 1.240 + 1.241 +template <class T> 1.242 +inline 1.243 +already_AddRefed<T> 1.244 +dont_AddRef( T* aRawPtr ) 1.245 + { 1.246 + return already_AddRefed<T>(aRawPtr); 1.247 + } 1.248 + 1.249 +template <class T> 1.250 +inline 1.251 +already_AddRefed<T>&& 1.252 +dont_AddRef( already_AddRefed<T>&& aAlreadyAddRefedPtr ) 1.253 + { 1.254 + return mozilla::Move(aAlreadyAddRefedPtr); 1.255 + } 1.256 + 1.257 + 1.258 + 1.259 +class nsCOMPtr_helper 1.260 + /* 1.261 + An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms 1.262 + that are more convenient to call, and more efficient to use with |nsCOMPtr|s. 1.263 + Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc. 1.264 + 1.265 + Here are the rules for a helper: 1.266 + - it implements |operator()| to produce an interface pointer 1.267 + - (except for its name) |operator()| is a valid [XP]COM `getter' 1.268 + - the interface pointer that it returns is already |AddRef()|ed (as from any good getter) 1.269 + - it matches the type requested with the supplied |nsIID| argument 1.270 + - its constructor provides an optional |nsresult*| that |operator()| can fill 1.271 + in with an error when it is executed 1.272 + 1.273 + See |class nsGetInterface| for an example. 1.274 + */ 1.275 + { 1.276 + public: 1.277 + virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0; 1.278 + }; 1.279 + 1.280 +/* 1.281 + |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to 1.282 + avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface| 1.283 + is called often enough that the codesize savings are big enough to 1.284 + warrant the specialcasing. 1.285 +*/ 1.286 + 1.287 +class 1.288 + NS_COM_GLUE 1.289 + MOZ_STACK_CLASS 1.290 +nsQueryInterface MOZ_FINAL 1.291 + { 1.292 + public: 1.293 + explicit 1.294 + nsQueryInterface( nsISupports* aRawPtr ) 1.295 + : mRawPtr(aRawPtr) 1.296 + { 1.297 + // nothing else to do here 1.298 + } 1.299 + 1.300 + nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const; 1.301 + 1.302 + private: 1.303 + nsISupports* mRawPtr; 1.304 + }; 1.305 + 1.306 +class NS_COM_GLUE nsQueryInterfaceWithError 1.307 + { 1.308 + public: 1.309 + nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error ) 1.310 + : mRawPtr(aRawPtr), 1.311 + mErrorPtr(error) 1.312 + { 1.313 + // nothing else to do here 1.314 + } 1.315 + 1.316 + nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const; 1.317 + 1.318 + private: 1.319 + nsISupports* mRawPtr; 1.320 + nsresult* mErrorPtr; 1.321 + }; 1.322 + 1.323 +inline 1.324 +nsQueryInterface 1.325 +do_QueryInterface( nsISupports* aRawPtr ) 1.326 + { 1.327 + return nsQueryInterface(aRawPtr); 1.328 + } 1.329 + 1.330 +inline 1.331 +nsQueryInterfaceWithError 1.332 +do_QueryInterface( nsISupports* aRawPtr, nsresult* error ) 1.333 + { 1.334 + return nsQueryInterfaceWithError(aRawPtr, error); 1.335 + } 1.336 + 1.337 +template <class T> 1.338 +inline 1.339 +void 1.340 +do_QueryInterface( already_AddRefed<T>& ) 1.341 + { 1.342 + // This signature exists solely to _stop_ you from doing the bad thing. 1.343 + // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by 1.344 + // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>. 1.345 + } 1.346 + 1.347 +template <class T> 1.348 +inline 1.349 +void 1.350 +do_QueryInterface( already_AddRefed<T>&, nsresult* ) 1.351 + { 1.352 + // This signature exists solely to _stop_ you from doing the bad thing. 1.353 + // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by 1.354 + // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>. 1.355 + } 1.356 + 1.357 + 1.358 +//////////////////////////////////////////////////////////////////////////// 1.359 +// Using servicemanager with COMPtrs 1.360 +class NS_COM_GLUE nsGetServiceByCID 1.361 +{ 1.362 + public: 1.363 + explicit nsGetServiceByCID(const nsCID& aCID) 1.364 + : mCID(aCID) 1.365 + { 1.366 + // nothing else to do 1.367 + } 1.368 + 1.369 + nsresult NS_FASTCALL operator()( const nsIID&, void** ) const; 1.370 + 1.371 + private: 1.372 + const nsCID& mCID; 1.373 +}; 1.374 + 1.375 +class NS_COM_GLUE nsGetServiceByCIDWithError 1.376 +{ 1.377 + public: 1.378 + nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr ) 1.379 + : mCID(aCID), 1.380 + mErrorPtr(aErrorPtr) 1.381 + { 1.382 + // nothing else to do 1.383 + } 1.384 + 1.385 + nsresult NS_FASTCALL operator()( const nsIID&, void** ) const; 1.386 + 1.387 + private: 1.388 + const nsCID& mCID; 1.389 + nsresult* mErrorPtr; 1.390 +}; 1.391 + 1.392 +class NS_COM_GLUE nsGetServiceByContractID 1.393 +{ 1.394 + public: 1.395 + explicit nsGetServiceByContractID(const char* aContractID) 1.396 + : mContractID(aContractID) 1.397 + { 1.398 + // nothing else to do 1.399 + } 1.400 + 1.401 + nsresult NS_FASTCALL operator()( const nsIID&, void** ) const; 1.402 + 1.403 + private: 1.404 + const char* mContractID; 1.405 +}; 1.406 + 1.407 +class NS_COM_GLUE nsGetServiceByContractIDWithError 1.408 +{ 1.409 + public: 1.410 + nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr) 1.411 + : mContractID(aContractID), 1.412 + mErrorPtr(aErrorPtr) 1.413 + { 1.414 + // nothing else to do 1.415 + } 1.416 + 1.417 + nsresult NS_FASTCALL operator()( const nsIID&, void** ) const; 1.418 + 1.419 + private: 1.420 + const char* mContractID; 1.421 + nsresult* mErrorPtr; 1.422 +}; 1.423 + 1.424 +class 1.425 +nsCOMPtr_base 1.426 + /* 1.427 + ...factors implementation for all template versions of |nsCOMPtr|. 1.428 + 1.429 + This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work 1.430 + because unlike the 1.431 + 1.432 + Here's the way people normally do things like this 1.433 + 1.434 + template <class T> class Foo { ... }; 1.435 + template <> class Foo<void*> { ... }; 1.436 + template <class T> class Foo<T*> : private Foo<void*> { ... }; 1.437 + */ 1.438 + { 1.439 + public: 1.440 + 1.441 + nsCOMPtr_base( nsISupports* rawPtr = 0 ) 1.442 + : mRawPtr(rawPtr) 1.443 + { 1.444 + // nothing else to do here 1.445 + } 1.446 + 1.447 + NS_COM_GLUE NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base() 1.448 + { 1.449 + NSCAP_LOG_RELEASE(this, mRawPtr); 1.450 + if ( mRawPtr ) 1.451 + NSCAP_RELEASE(this, mRawPtr); 1.452 + } 1.453 + 1.454 + NS_COM_GLUE void NS_FASTCALL assign_with_AddRef( nsISupports* ); 1.455 + NS_COM_GLUE void NS_FASTCALL assign_from_qi( const nsQueryInterface, const nsIID& ); 1.456 + NS_COM_GLUE void NS_FASTCALL assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& ); 1.457 + NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid( const nsGetServiceByCID, const nsIID& ); 1.458 + NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& ); 1.459 + NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& ); 1.460 + NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& ); 1.461 + NS_COM_GLUE void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& ); 1.462 + NS_COM_GLUE void** NS_FASTCALL begin_assignment(); 1.463 + 1.464 + protected: 1.465 + NS_MAY_ALIAS_PTR(nsISupports) mRawPtr; 1.466 + 1.467 + void 1.468 + assign_assuming_AddRef( nsISupports* newPtr ) 1.469 + { 1.470 + /* 1.471 + |AddRef()|ing the new value (before entering this function) before 1.472 + |Release()|ing the old lets us safely ignore the self-assignment case. 1.473 + We must, however, be careful only to |Release()| _after_ doing the 1.474 + assignment, in case the |Release()| leads to our _own_ destruction, 1.475 + which would, in turn, cause an incorrect second |Release()| of our old 1.476 + pointer. Thank <waterson@netscape.com> for discovering this. 1.477 + */ 1.478 + nsISupports* oldPtr = mRawPtr; 1.479 + mRawPtr = newPtr; 1.480 + NSCAP_LOG_ASSIGNMENT(this, newPtr); 1.481 + NSCAP_LOG_RELEASE(this, oldPtr); 1.482 + if ( oldPtr ) 1.483 + NSCAP_RELEASE(this, oldPtr); 1.484 + } 1.485 + }; 1.486 + 1.487 +// template <class T> class nsGetterAddRefs; 1.488 + 1.489 +template <class T> 1.490 +class nsCOMPtr MOZ_FINAL 1.491 +#ifdef NSCAP_FEATURE_USE_BASE 1.492 + : private nsCOMPtr_base 1.493 +#endif 1.494 + { 1.495 + 1.496 +#ifdef NSCAP_FEATURE_USE_BASE 1.497 + #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x) 1.498 +#else 1.499 + #define NSCAP_CTOR_BASE(x) mRawPtr(x) 1.500 + 1.501 + private: 1.502 + void assign_with_AddRef( nsISupports* ); 1.503 + void assign_from_qi( const nsQueryInterface, const nsIID& ); 1.504 + void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& ); 1.505 + void assign_from_gs_cid( const nsGetServiceByCID, const nsIID& ); 1.506 + void assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& ); 1.507 + void assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& ); 1.508 + void assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& ); 1.509 + void assign_from_helper( const nsCOMPtr_helper&, const nsIID& ); 1.510 + void** begin_assignment(); 1.511 + 1.512 + void 1.513 + assign_assuming_AddRef( T* newPtr ) 1.514 + { 1.515 + T* oldPtr = mRawPtr; 1.516 + mRawPtr = newPtr; 1.517 + NSCAP_LOG_ASSIGNMENT(this, newPtr); 1.518 + NSCAP_LOG_RELEASE(this, oldPtr); 1.519 + if ( oldPtr ) 1.520 + NSCAP_RELEASE(this, oldPtr); 1.521 + } 1.522 + 1.523 + private: 1.524 + T* mRawPtr; 1.525 +#endif 1.526 + 1.527 + public: 1.528 + typedef T element_type; 1.529 + 1.530 +#ifndef NSCAP_FEATURE_USE_BASE 1.531 + ~nsCOMPtr() 1.532 + { 1.533 + NSCAP_LOG_RELEASE(this, mRawPtr); 1.534 + if ( mRawPtr ) 1.535 + NSCAP_RELEASE(this, mRawPtr); 1.536 + } 1.537 +#endif 1.538 + 1.539 +#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES 1.540 + void 1.541 + Assert_NoQueryNeeded() 1.542 + { 1.543 + if ( mRawPtr ) 1.544 + { 1.545 + nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) ); 1.546 + NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed"); 1.547 + } 1.548 + } 1.549 + 1.550 + #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded(); 1.551 +#else 1.552 + #define NSCAP_ASSERT_NO_QUERY_NEEDED() 1.553 +#endif 1.554 + 1.555 + 1.556 + // Constructors 1.557 + 1.558 + nsCOMPtr() 1.559 + : NSCAP_CTOR_BASE(0) 1.560 + // default constructor 1.561 + { 1.562 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.563 + } 1.564 + 1.565 + nsCOMPtr( const nsCOMPtr<T>& aSmartPtr ) 1.566 + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) 1.567 + // copy-constructor 1.568 + { 1.569 + if ( mRawPtr ) 1.570 + NSCAP_ADDREF(this, mRawPtr); 1.571 + NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr); 1.572 + } 1.573 + 1.574 + nsCOMPtr( T* aRawPtr ) 1.575 + : NSCAP_CTOR_BASE(aRawPtr) 1.576 + // construct from a raw pointer (of the right type) 1.577 + { 1.578 + if ( mRawPtr ) 1.579 + NSCAP_ADDREF(this, mRawPtr); 1.580 + NSCAP_LOG_ASSIGNMENT(this, aRawPtr); 1.581 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.582 + } 1.583 + 1.584 + nsCOMPtr( already_AddRefed<T>& aSmartPtr ) 1.585 + : NSCAP_CTOR_BASE(aSmartPtr.take()) 1.586 + // construct from |already_AddRefed| 1.587 + { 1.588 + NSCAP_LOG_ASSIGNMENT(this, mRawPtr); 1.589 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.590 + } 1.591 + 1.592 + nsCOMPtr( already_AddRefed<T>&& aSmartPtr ) 1.593 + : NSCAP_CTOR_BASE(aSmartPtr.take()) 1.594 + // construct from |otherComPtr.forget()| 1.595 + { 1.596 + NSCAP_LOG_ASSIGNMENT(this, mRawPtr); 1.597 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.598 + } 1.599 + 1.600 + template<typename U> 1.601 + nsCOMPtr( already_AddRefed<U>& aSmartPtr ) 1.602 + : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take())) 1.603 + // construct from |already_AddRefed| 1.604 + { 1.605 + // But make sure that U actually inherits from T 1.606 + static_assert(mozilla::IsBaseOf<T, U>::value, 1.607 + "U is not a subclass of T"); 1.608 + NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr)); 1.609 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.610 + } 1.611 + 1.612 + template<typename U> 1.613 + nsCOMPtr( already_AddRefed<U>&& aSmartPtr ) 1.614 + : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take())) 1.615 + // construct from |otherComPtr.forget()| 1.616 + { 1.617 + // But make sure that U actually inherits from T 1.618 + static_assert(mozilla::IsBaseOf<T, U>::value, 1.619 + "U is not a subclass of T"); 1.620 + NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr)); 1.621 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.622 + } 1.623 + 1.624 + nsCOMPtr( const nsQueryInterface qi ) 1.625 + : NSCAP_CTOR_BASE(0) 1.626 + // construct from |do_QueryInterface(expr)| 1.627 + { 1.628 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.629 + assign_from_qi(qi, NS_GET_TEMPLATE_IID(T)); 1.630 + } 1.631 + 1.632 + nsCOMPtr( const nsQueryInterfaceWithError& qi ) 1.633 + : NSCAP_CTOR_BASE(0) 1.634 + // construct from |do_QueryInterface(expr, &rv)| 1.635 + { 1.636 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.637 + assign_from_qi_with_error(qi, NS_GET_TEMPLATE_IID(T)); 1.638 + } 1.639 + 1.640 + nsCOMPtr( const nsGetServiceByCID gs ) 1.641 + : NSCAP_CTOR_BASE(0) 1.642 + // construct from |do_GetService(cid_expr)| 1.643 + { 1.644 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.645 + assign_from_gs_cid(gs, NS_GET_TEMPLATE_IID(T)); 1.646 + } 1.647 + 1.648 + nsCOMPtr( const nsGetServiceByCIDWithError& gs ) 1.649 + : NSCAP_CTOR_BASE(0) 1.650 + // construct from |do_GetService(cid_expr, &rv)| 1.651 + { 1.652 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.653 + assign_from_gs_cid_with_error(gs, NS_GET_TEMPLATE_IID(T)); 1.654 + } 1.655 + 1.656 + nsCOMPtr( const nsGetServiceByContractID gs ) 1.657 + : NSCAP_CTOR_BASE(0) 1.658 + // construct from |do_GetService(contractid_expr)| 1.659 + { 1.660 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.661 + assign_from_gs_contractid(gs, NS_GET_TEMPLATE_IID(T)); 1.662 + } 1.663 + 1.664 + nsCOMPtr( const nsGetServiceByContractIDWithError& gs ) 1.665 + : NSCAP_CTOR_BASE(0) 1.666 + // construct from |do_GetService(contractid_expr, &rv)| 1.667 + { 1.668 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.669 + assign_from_gs_contractid_with_error(gs, NS_GET_TEMPLATE_IID(T)); 1.670 + } 1.671 + 1.672 + nsCOMPtr( const nsCOMPtr_helper& helper ) 1.673 + : NSCAP_CTOR_BASE(0) 1.674 + // ...and finally, anything else we might need to construct from 1.675 + // can exploit the |nsCOMPtr_helper| facility 1.676 + { 1.677 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.678 + assign_from_helper(helper, NS_GET_TEMPLATE_IID(T)); 1.679 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.680 + } 1.681 + 1.682 + 1.683 + // Assignment operators 1.684 + 1.685 + nsCOMPtr<T>& 1.686 + operator=( const nsCOMPtr<T>& rhs ) 1.687 + // copy assignment operator 1.688 + { 1.689 + assign_with_AddRef(rhs.mRawPtr); 1.690 + return *this; 1.691 + } 1.692 + 1.693 + nsCOMPtr<T>& 1.694 + operator=( T* rhs ) 1.695 + // assign from a raw pointer (of the right type) 1.696 + { 1.697 + assign_with_AddRef(rhs); 1.698 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.699 + return *this; 1.700 + } 1.701 + 1.702 + template<typename U> 1.703 + nsCOMPtr<T>& 1.704 + operator=( already_AddRefed<U>& rhs ) 1.705 + // assign from |already_AddRefed| 1.706 + { 1.707 + // Make sure that U actually inherits from T 1.708 + static_assert(mozilla::IsBaseOf<T, U>::value, 1.709 + "U is not a subclass of T"); 1.710 + assign_assuming_AddRef(static_cast<T*>(rhs.take())); 1.711 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.712 + return *this; 1.713 + } 1.714 + 1.715 + template<typename U> 1.716 + nsCOMPtr<T>& 1.717 + operator=( already_AddRefed<U>&& rhs ) 1.718 + // assign from |otherComPtr.forget()| 1.719 + { 1.720 + // Make sure that U actually inherits from T 1.721 + static_assert(mozilla::IsBaseOf<T, U>::value, 1.722 + "U is not a subclass of T"); 1.723 + assign_assuming_AddRef(static_cast<T*>(rhs.take())); 1.724 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.725 + return *this; 1.726 + } 1.727 + 1.728 + nsCOMPtr<T>& 1.729 + operator=( const nsQueryInterface rhs ) 1.730 + // assign from |do_QueryInterface(expr)| 1.731 + { 1.732 + assign_from_qi(rhs, NS_GET_TEMPLATE_IID(T)); 1.733 + return *this; 1.734 + } 1.735 + 1.736 + nsCOMPtr<T>& 1.737 + operator=( const nsQueryInterfaceWithError& rhs ) 1.738 + // assign from |do_QueryInterface(expr, &rv)| 1.739 + { 1.740 + assign_from_qi_with_error(rhs, NS_GET_TEMPLATE_IID(T)); 1.741 + return *this; 1.742 + } 1.743 + 1.744 + nsCOMPtr<T>& 1.745 + operator=( const nsGetServiceByCID rhs ) 1.746 + // assign from |do_GetService(cid_expr)| 1.747 + { 1.748 + assign_from_gs_cid(rhs, NS_GET_TEMPLATE_IID(T)); 1.749 + return *this; 1.750 + } 1.751 + 1.752 + nsCOMPtr<T>& 1.753 + operator=( const nsGetServiceByCIDWithError& rhs ) 1.754 + // assign from |do_GetService(cid_expr, &rv)| 1.755 + { 1.756 + assign_from_gs_cid_with_error(rhs, NS_GET_TEMPLATE_IID(T)); 1.757 + return *this; 1.758 + } 1.759 + 1.760 + nsCOMPtr<T>& 1.761 + operator=( const nsGetServiceByContractID rhs ) 1.762 + // assign from |do_GetService(contractid_expr)| 1.763 + { 1.764 + assign_from_gs_contractid(rhs, NS_GET_TEMPLATE_IID(T)); 1.765 + return *this; 1.766 + } 1.767 + 1.768 + nsCOMPtr<T>& 1.769 + operator=( const nsGetServiceByContractIDWithError& rhs ) 1.770 + // assign from |do_GetService(contractid_expr, &rv)| 1.771 + { 1.772 + assign_from_gs_contractid_with_error(rhs, NS_GET_TEMPLATE_IID(T)); 1.773 + return *this; 1.774 + } 1.775 + 1.776 + nsCOMPtr<T>& 1.777 + operator=( const nsCOMPtr_helper& rhs ) 1.778 + // ...and finally, anything else we might need to assign from 1.779 + // can exploit the |nsCOMPtr_helper| facility. 1.780 + { 1.781 + assign_from_helper(rhs, NS_GET_TEMPLATE_IID(T)); 1.782 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.783 + return *this; 1.784 + } 1.785 + 1.786 + void 1.787 + swap( nsCOMPtr<T>& rhs ) 1.788 + // ...exchange ownership with |rhs|; can save a pair of refcount operations 1.789 + { 1.790 +#ifdef NSCAP_FEATURE_USE_BASE 1.791 + nsISupports* temp = rhs.mRawPtr; 1.792 +#else 1.793 + T* temp = rhs.mRawPtr; 1.794 +#endif 1.795 + NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr); 1.796 + NSCAP_LOG_ASSIGNMENT(this, temp); 1.797 + NSCAP_LOG_RELEASE(this, mRawPtr); 1.798 + NSCAP_LOG_RELEASE(&rhs, temp); 1.799 + rhs.mRawPtr = mRawPtr; 1.800 + mRawPtr = temp; 1.801 + // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED| 1.802 + } 1.803 + 1.804 + void 1.805 + swap( T*& rhs ) 1.806 + // ...exchange ownership with |rhs|; can save a pair of refcount operations 1.807 + { 1.808 +#ifdef NSCAP_FEATURE_USE_BASE 1.809 + nsISupports* temp = rhs; 1.810 +#else 1.811 + T* temp = rhs; 1.812 +#endif 1.813 + NSCAP_LOG_ASSIGNMENT(this, temp); 1.814 + NSCAP_LOG_RELEASE(this, mRawPtr); 1.815 + rhs = reinterpret_cast<T*>(mRawPtr); 1.816 + mRawPtr = temp; 1.817 + NSCAP_ASSERT_NO_QUERY_NEEDED(); 1.818 + } 1.819 + 1.820 + 1.821 + // Other pointer operators 1.822 + 1.823 + already_AddRefed<T> 1.824 + forget() 1.825 + // return the value of mRawPtr and null out mRawPtr. Useful for 1.826 + // already_AddRefed return values. 1.827 + { 1.828 + T* temp = 0; 1.829 + swap(temp); 1.830 + return already_AddRefed<T>(temp); 1.831 + } 1.832 + 1.833 + template <typename I> 1.834 + void 1.835 + forget( I** rhs ) 1.836 + // Set the target of rhs to the value of mRawPtr and null out mRawPtr. 1.837 + // Useful to avoid unnecessary AddRef/Release pairs with "out" 1.838 + // parameters where rhs bay be a T** or an I** where I is a base class 1.839 + // of T. 1.840 + { 1.841 + NS_ASSERTION(rhs, "Null pointer passed to forget!"); 1.842 + NSCAP_LOG_RELEASE(this, mRawPtr); 1.843 + *rhs = get(); 1.844 + mRawPtr = 0; 1.845 + } 1.846 + 1.847 + T* 1.848 + get() const 1.849 + /* 1.850 + Prefer the implicit conversion provided automatically by |operator T*() const|. 1.851 + Use |get()| to resolve ambiguity or to get a castable pointer. 1.852 + */ 1.853 + { 1.854 + return reinterpret_cast<T*>(mRawPtr); 1.855 + } 1.856 + 1.857 + operator T*() const 1.858 + /* 1.859 + ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it 1.860 + is used in a context where a raw pointer is expected. It is this operator 1.861 + that makes an |nsCOMPtr| substitutable for a raw pointer. 1.862 + 1.863 + Prefer the implicit use of this operator to calling |get()|, except where 1.864 + necessary to resolve ambiguity. 1.865 + */ 1.866 + { 1.867 + return get(); 1.868 + } 1.869 + 1.870 + T* 1.871 + operator->() const 1.872 + { 1.873 + NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->()."); 1.874 + return get(); 1.875 + } 1.876 + 1.877 + nsCOMPtr<T>* 1.878 + get_address() 1.879 + // This is not intended to be used by clients. See |address_of| 1.880 + // below. 1.881 + { 1.882 + return this; 1.883 + } 1.884 + 1.885 + const nsCOMPtr<T>* 1.886 + get_address() const 1.887 + // This is not intended to be used by clients. See |address_of| 1.888 + // below. 1.889 + { 1.890 + return this; 1.891 + } 1.892 + 1.893 + public: 1.894 + T& 1.895 + operator*() const 1.896 + { 1.897 + NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*()."); 1.898 + return *get(); 1.899 + } 1.900 + 1.901 + T** 1.902 + StartAssignment() 1.903 + { 1.904 +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT 1.905 + return reinterpret_cast<T**>(begin_assignment()); 1.906 +#else 1.907 + assign_assuming_AddRef(0); 1.908 + return reinterpret_cast<T**>(&mRawPtr); 1.909 +#endif 1.910 + } 1.911 + }; 1.912 + 1.913 + 1.914 + 1.915 + /* 1.916 + Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the 1.917 + same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing 1.918 + to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able 1.919 + to point to the single [XP]COM-correct |nsISupports| instance within an object; extra 1.920 + querying ensues. Clients need to be able to pass around arbitrary interface pointers, 1.921 + without hassles, through intermediary code that doesn't know the exact type. 1.922 + */ 1.923 + 1.924 +template <> 1.925 +class nsCOMPtr<nsISupports> 1.926 + : private nsCOMPtr_base 1.927 + { 1.928 + public: 1.929 + typedef nsISupports element_type; 1.930 + 1.931 + // Constructors 1.932 + 1.933 + nsCOMPtr() 1.934 + : nsCOMPtr_base(0) 1.935 + // default constructor 1.936 + { 1.937 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.938 + } 1.939 + 1.940 + nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr ) 1.941 + : nsCOMPtr_base(aSmartPtr.mRawPtr) 1.942 + // copy constructor 1.943 + { 1.944 + if ( mRawPtr ) 1.945 + NSCAP_ADDREF(this, mRawPtr); 1.946 + NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr); 1.947 + } 1.948 + 1.949 + nsCOMPtr( nsISupports* aRawPtr ) 1.950 + : nsCOMPtr_base(aRawPtr) 1.951 + // construct from a raw pointer (of the right type) 1.952 + { 1.953 + if ( mRawPtr ) 1.954 + NSCAP_ADDREF(this, mRawPtr); 1.955 + NSCAP_LOG_ASSIGNMENT(this, aRawPtr); 1.956 + } 1.957 + 1.958 + nsCOMPtr( already_AddRefed<nsISupports>& aSmartPtr ) 1.959 + : nsCOMPtr_base(aSmartPtr.take()) 1.960 + // construct from |already_AddRefed| 1.961 + { 1.962 + NSCAP_LOG_ASSIGNMENT(this, mRawPtr); 1.963 + } 1.964 + 1.965 + nsCOMPtr( already_AddRefed<nsISupports>&& aSmartPtr ) 1.966 + : nsCOMPtr_base(aSmartPtr.take()) 1.967 + // construct from |otherComPtr.forget()| 1.968 + { 1.969 + NSCAP_LOG_ASSIGNMENT(this, mRawPtr); 1.970 + } 1.971 + 1.972 + nsCOMPtr( const nsQueryInterface qi ) 1.973 + : nsCOMPtr_base(0) 1.974 + // assign from |do_QueryInterface(expr)| 1.975 + { 1.976 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.977 + assign_from_qi(qi, NS_GET_IID(nsISupports)); 1.978 + } 1.979 + 1.980 + nsCOMPtr( const nsQueryInterfaceWithError& qi ) 1.981 + : nsCOMPtr_base(0) 1.982 + // assign from |do_QueryInterface(expr, &rv)| 1.983 + { 1.984 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.985 + assign_from_qi_with_error(qi, NS_GET_IID(nsISupports)); 1.986 + } 1.987 + 1.988 + nsCOMPtr( const nsGetServiceByCID gs ) 1.989 + : nsCOMPtr_base(0) 1.990 + // assign from |do_GetService(cid_expr)| 1.991 + { 1.992 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.993 + assign_from_gs_cid(gs, NS_GET_IID(nsISupports)); 1.994 + } 1.995 + 1.996 + nsCOMPtr( const nsGetServiceByCIDWithError& gs ) 1.997 + : nsCOMPtr_base(0) 1.998 + // assign from |do_GetService(cid_expr, &rv)| 1.999 + { 1.1000 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.1001 + assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports)); 1.1002 + } 1.1003 + 1.1004 + nsCOMPtr( const nsGetServiceByContractID gs ) 1.1005 + : nsCOMPtr_base(0) 1.1006 + // assign from |do_GetService(contractid_expr)| 1.1007 + { 1.1008 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.1009 + assign_from_gs_contractid(gs, NS_GET_IID(nsISupports)); 1.1010 + } 1.1011 + 1.1012 + nsCOMPtr( const nsGetServiceByContractIDWithError& gs ) 1.1013 + : nsCOMPtr_base(0) 1.1014 + // assign from |do_GetService(contractid_expr, &rv)| 1.1015 + { 1.1016 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.1017 + assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports)); 1.1018 + } 1.1019 + 1.1020 + nsCOMPtr( const nsCOMPtr_helper& helper ) 1.1021 + : nsCOMPtr_base(0) 1.1022 + // ...and finally, anything else we might need to construct from 1.1023 + // can exploit the |nsCOMPtr_helper| facility 1.1024 + { 1.1025 + NSCAP_LOG_ASSIGNMENT(this, 0); 1.1026 + assign_from_helper(helper, NS_GET_IID(nsISupports)); 1.1027 + } 1.1028 + 1.1029 + 1.1030 + // Assignment operators 1.1031 + 1.1032 + nsCOMPtr<nsISupports>& 1.1033 + operator=( const nsCOMPtr<nsISupports>& rhs ) 1.1034 + // copy assignment operator 1.1035 + { 1.1036 + assign_with_AddRef(rhs.mRawPtr); 1.1037 + return *this; 1.1038 + } 1.1039 + 1.1040 + nsCOMPtr<nsISupports>& 1.1041 + operator=( nsISupports* rhs ) 1.1042 + // assign from a raw pointer (of the right type) 1.1043 + { 1.1044 + assign_with_AddRef(rhs); 1.1045 + return *this; 1.1046 + } 1.1047 + 1.1048 + nsCOMPtr<nsISupports>& 1.1049 + operator=( already_AddRefed<nsISupports>& rhs ) 1.1050 + // assign from |already_AddRefed| 1.1051 + { 1.1052 + assign_assuming_AddRef(rhs.take()); 1.1053 + return *this; 1.1054 + } 1.1055 + 1.1056 + nsCOMPtr<nsISupports>& 1.1057 + operator=( already_AddRefed<nsISupports>&& rhs ) 1.1058 + // assign from |otherComPtr.forget()| 1.1059 + { 1.1060 + assign_assuming_AddRef(rhs.take()); 1.1061 + return *this; 1.1062 + } 1.1063 + 1.1064 + nsCOMPtr<nsISupports>& 1.1065 + operator=( const nsQueryInterface rhs ) 1.1066 + // assign from |do_QueryInterface(expr)| 1.1067 + { 1.1068 + assign_from_qi(rhs, NS_GET_IID(nsISupports)); 1.1069 + return *this; 1.1070 + } 1.1071 + 1.1072 + nsCOMPtr<nsISupports>& 1.1073 + operator=( const nsQueryInterfaceWithError& rhs ) 1.1074 + // assign from |do_QueryInterface(expr, &rv)| 1.1075 + { 1.1076 + assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports)); 1.1077 + return *this; 1.1078 + } 1.1079 + 1.1080 + nsCOMPtr<nsISupports>& 1.1081 + operator=( const nsGetServiceByCID rhs ) 1.1082 + // assign from |do_GetService(cid_expr)| 1.1083 + { 1.1084 + assign_from_gs_cid(rhs, NS_GET_IID(nsISupports)); 1.1085 + return *this; 1.1086 + } 1.1087 + 1.1088 + nsCOMPtr<nsISupports>& 1.1089 + operator=( const nsGetServiceByCIDWithError& rhs ) 1.1090 + // assign from |do_GetService(cid_expr, &rv)| 1.1091 + { 1.1092 + assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports)); 1.1093 + return *this; 1.1094 + } 1.1095 + 1.1096 + nsCOMPtr<nsISupports>& 1.1097 + operator=( const nsGetServiceByContractID rhs ) 1.1098 + // assign from |do_GetService(contractid_expr)| 1.1099 + { 1.1100 + assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports)); 1.1101 + return *this; 1.1102 + } 1.1103 + 1.1104 + nsCOMPtr<nsISupports>& 1.1105 + operator=( const nsGetServiceByContractIDWithError& rhs ) 1.1106 + // assign from |do_GetService(contractid_expr, &rv)| 1.1107 + { 1.1108 + assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports)); 1.1109 + return *this; 1.1110 + } 1.1111 + 1.1112 + nsCOMPtr<nsISupports>& 1.1113 + operator=( const nsCOMPtr_helper& rhs ) 1.1114 + // ...and finally, anything else we might need to assign from 1.1115 + // can exploit the |nsCOMPtr_helper| facility. 1.1116 + { 1.1117 + assign_from_helper(rhs, NS_GET_IID(nsISupports)); 1.1118 + return *this; 1.1119 + } 1.1120 + 1.1121 + void 1.1122 + swap( nsCOMPtr<nsISupports>& rhs ) 1.1123 + // ...exchange ownership with |rhs|; can save a pair of refcount operations 1.1124 + { 1.1125 + nsISupports* temp = rhs.mRawPtr; 1.1126 + NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr); 1.1127 + NSCAP_LOG_ASSIGNMENT(this, temp); 1.1128 + NSCAP_LOG_RELEASE(this, mRawPtr); 1.1129 + NSCAP_LOG_RELEASE(&rhs, temp); 1.1130 + rhs.mRawPtr = mRawPtr; 1.1131 + mRawPtr = temp; 1.1132 + } 1.1133 + 1.1134 + void 1.1135 + swap( nsISupports*& rhs ) 1.1136 + // ...exchange ownership with |rhs|; can save a pair of refcount operations 1.1137 + { 1.1138 + nsISupports* temp = rhs; 1.1139 + NSCAP_LOG_ASSIGNMENT(this, temp); 1.1140 + NSCAP_LOG_RELEASE(this, mRawPtr); 1.1141 + rhs = mRawPtr; 1.1142 + mRawPtr = temp; 1.1143 + } 1.1144 + 1.1145 + already_AddRefed<nsISupports> 1.1146 + forget() 1.1147 + // return the value of mRawPtr and null out mRawPtr. Useful for 1.1148 + // already_AddRefed return values. 1.1149 + { 1.1150 + nsISupports* temp = 0; 1.1151 + swap(temp); 1.1152 + return already_AddRefed<nsISupports>(temp); 1.1153 + } 1.1154 + 1.1155 + void 1.1156 + forget( nsISupports** rhs ) 1.1157 + // Set the target of rhs to the value of mRawPtr and null out mRawPtr. 1.1158 + // Useful to avoid unnecessary AddRef/Release pairs with "out" 1.1159 + // parameters. 1.1160 + { 1.1161 + NS_ASSERTION(rhs, "Null pointer passed to forget!"); 1.1162 + *rhs = 0; 1.1163 + swap(*rhs); 1.1164 + } 1.1165 + 1.1166 + // Other pointer operators 1.1167 + 1.1168 + nsISupports* 1.1169 + get() const 1.1170 + /* 1.1171 + Prefer the implicit conversion provided automatically by 1.1172 + |operator nsISupports*() const|. 1.1173 + Use |get()| to resolve ambiguity or to get a castable pointer. 1.1174 + */ 1.1175 + { 1.1176 + return reinterpret_cast<nsISupports*>(mRawPtr); 1.1177 + } 1.1178 + 1.1179 + operator nsISupports*() const 1.1180 + /* 1.1181 + ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it 1.1182 + is used in a context where a raw pointer is expected. It is this operator 1.1183 + that makes an |nsCOMPtr| substitutable for a raw pointer. 1.1184 + 1.1185 + Prefer the implicit use of this operator to calling |get()|, except where 1.1186 + necessary to resolve ambiguity. 1.1187 + */ 1.1188 + { 1.1189 + return get(); 1.1190 + } 1.1191 + 1.1192 + nsISupports* 1.1193 + operator->() const 1.1194 + { 1.1195 + NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->()."); 1.1196 + return get(); 1.1197 + } 1.1198 + 1.1199 + nsCOMPtr<nsISupports>* 1.1200 + get_address() 1.1201 + // This is not intended to be used by clients. See |address_of| 1.1202 + // below. 1.1203 + { 1.1204 + return this; 1.1205 + } 1.1206 + 1.1207 + const nsCOMPtr<nsISupports>* 1.1208 + get_address() const 1.1209 + // This is not intended to be used by clients. See |address_of| 1.1210 + // below. 1.1211 + { 1.1212 + return this; 1.1213 + } 1.1214 + 1.1215 + public: 1.1216 + 1.1217 + nsISupports& 1.1218 + operator*() const 1.1219 + { 1.1220 + NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*()."); 1.1221 + return *get(); 1.1222 + } 1.1223 + 1.1224 + nsISupports** 1.1225 + StartAssignment() 1.1226 + { 1.1227 +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT 1.1228 + return reinterpret_cast<nsISupports**>(begin_assignment()); 1.1229 +#else 1.1230 + assign_assuming_AddRef(0); 1.1231 + return reinterpret_cast<nsISupports**>(&mRawPtr); 1.1232 +#endif 1.1233 + } 1.1234 + }; 1.1235 + 1.1236 +template <typename T> 1.1237 +inline void 1.1238 +ImplCycleCollectionUnlink(nsCOMPtr<T>& aField) 1.1239 +{ 1.1240 + aField = nullptr; 1.1241 +} 1.1242 + 1.1243 +template <typename T> 1.1244 +inline void 1.1245 +ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, 1.1246 + nsCOMPtr<T>& aField, 1.1247 + const char* aName, 1.1248 + uint32_t aFlags = 0) 1.1249 +{ 1.1250 + CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags); 1.1251 +} 1.1252 + 1.1253 +#ifndef NSCAP_FEATURE_USE_BASE 1.1254 +template <class T> 1.1255 +void 1.1256 +nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr ) 1.1257 + { 1.1258 + if ( rawPtr ) 1.1259 + NSCAP_ADDREF(this, rawPtr); 1.1260 + assign_assuming_AddRef(reinterpret_cast<T*>(rawPtr)); 1.1261 + } 1.1262 + 1.1263 +template <class T> 1.1264 +void 1.1265 +nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID ) 1.1266 + { 1.1267 + void* newRawPtr; 1.1268 + if ( NS_FAILED( qi(aIID, &newRawPtr) ) ) 1.1269 + newRawPtr = 0; 1.1270 + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); 1.1271 + } 1.1272 + 1.1273 +template <class T> 1.1274 +void 1.1275 +nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID ) 1.1276 + { 1.1277 + void* newRawPtr; 1.1278 + if ( NS_FAILED( qi(aIID, &newRawPtr) ) ) 1.1279 + newRawPtr = 0; 1.1280 + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); 1.1281 + } 1.1282 + 1.1283 +template <class T> 1.1284 +void 1.1285 +nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID ) 1.1286 + { 1.1287 + void* newRawPtr; 1.1288 + if ( NS_FAILED( gs(aIID, &newRawPtr) ) ) 1.1289 + newRawPtr = 0; 1.1290 + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); 1.1291 + } 1.1292 + 1.1293 +template <class T> 1.1294 +void 1.1295 +nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID ) 1.1296 + { 1.1297 + void* newRawPtr; 1.1298 + if ( NS_FAILED( gs(aIID, &newRawPtr) ) ) 1.1299 + newRawPtr = 0; 1.1300 + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); 1.1301 + } 1.1302 + 1.1303 +template <class T> 1.1304 +void 1.1305 +nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID ) 1.1306 + { 1.1307 + void* newRawPtr; 1.1308 + if ( NS_FAILED( gs(aIID, &newRawPtr) ) ) 1.1309 + newRawPtr = 0; 1.1310 + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); 1.1311 + } 1.1312 + 1.1313 +template <class T> 1.1314 +void 1.1315 +nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID ) 1.1316 + { 1.1317 + void* newRawPtr; 1.1318 + if ( NS_FAILED( gs(aIID, &newRawPtr) ) ) 1.1319 + newRawPtr = 0; 1.1320 + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); 1.1321 + } 1.1322 + 1.1323 +template <class T> 1.1324 +void 1.1325 +nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID ) 1.1326 + { 1.1327 + void* newRawPtr; 1.1328 + if ( NS_FAILED( helper(aIID, &newRawPtr) ) ) 1.1329 + newRawPtr = 0; 1.1330 + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); 1.1331 + } 1.1332 + 1.1333 +template <class T> 1.1334 +void** 1.1335 +nsCOMPtr<T>::begin_assignment() 1.1336 + { 1.1337 + assign_assuming_AddRef(0); 1.1338 + union { T** mT; void** mVoid; } result; 1.1339 + result.mT = &mRawPtr; 1.1340 + return result.mVoid; 1.1341 + } 1.1342 +#endif 1.1343 + 1.1344 +template <class T> 1.1345 +inline 1.1346 +nsCOMPtr<T>* 1.1347 +address_of( nsCOMPtr<T>& aPtr ) 1.1348 + { 1.1349 + return aPtr.get_address(); 1.1350 + } 1.1351 + 1.1352 +template <class T> 1.1353 +inline 1.1354 +const nsCOMPtr<T>* 1.1355 +address_of( const nsCOMPtr<T>& aPtr ) 1.1356 + { 1.1357 + return aPtr.get_address(); 1.1358 + } 1.1359 + 1.1360 +template <class T> 1.1361 +class nsGetterAddRefs 1.1362 + /* 1.1363 + ... 1.1364 + 1.1365 + This class is designed to be used for anonymous temporary objects in the 1.1366 + argument list of calls that return COM interface pointers, e.g., 1.1367 + 1.1368 + nsCOMPtr<IFoo> fooP; 1.1369 + ...->QueryInterface(iid, getter_AddRefs(fooP)) 1.1370 + 1.1371 + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead. 1.1372 + 1.1373 + When initialized with a |nsCOMPtr|, as in the example above, it returns 1.1374 + a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this 1.1375 + case) can fill in. 1.1376 + 1.1377 + This type should be a nested class inside |nsCOMPtr<T>|. 1.1378 + */ 1.1379 + { 1.1380 + public: 1.1381 + explicit 1.1382 + nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr ) 1.1383 + : mTargetSmartPtr(aSmartPtr) 1.1384 + { 1.1385 + // nothing else to do 1.1386 + } 1.1387 + 1.1388 +#if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT) 1.1389 + ~nsGetterAddRefs() 1.1390 + { 1.1391 +#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT 1.1392 + NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get()); 1.1393 +#endif 1.1394 + 1.1395 +#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES 1.1396 + mTargetSmartPtr.Assert_NoQueryNeeded(); 1.1397 +#endif 1.1398 + } 1.1399 +#endif 1.1400 + 1.1401 + operator void**() 1.1402 + { 1.1403 + return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment()); 1.1404 + } 1.1405 + operator T**() 1.1406 + { 1.1407 + return mTargetSmartPtr.StartAssignment(); 1.1408 + } 1.1409 + 1.1410 + T*& 1.1411 + operator*() 1.1412 + { 1.1413 + return *(mTargetSmartPtr.StartAssignment()); 1.1414 + } 1.1415 + 1.1416 + private: 1.1417 + nsCOMPtr<T>& mTargetSmartPtr; 1.1418 + }; 1.1419 + 1.1420 + 1.1421 +template <> 1.1422 +class nsGetterAddRefs<nsISupports> 1.1423 + { 1.1424 + public: 1.1425 + explicit 1.1426 + nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr ) 1.1427 + : mTargetSmartPtr(aSmartPtr) 1.1428 + { 1.1429 + // nothing else to do 1.1430 + } 1.1431 + 1.1432 +#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT 1.1433 + ~nsGetterAddRefs() 1.1434 + { 1.1435 + NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get()); 1.1436 + } 1.1437 +#endif 1.1438 + 1.1439 + operator void**() 1.1440 + { 1.1441 + return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment()); 1.1442 + } 1.1443 + 1.1444 + operator nsISupports**() 1.1445 + { 1.1446 + return mTargetSmartPtr.StartAssignment(); 1.1447 + } 1.1448 + 1.1449 + nsISupports*& 1.1450 + operator*() 1.1451 + { 1.1452 + return *(mTargetSmartPtr.StartAssignment()); 1.1453 + } 1.1454 + 1.1455 + private: 1.1456 + nsCOMPtr<nsISupports>& mTargetSmartPtr; 1.1457 + }; 1.1458 + 1.1459 + 1.1460 +template <class T> 1.1461 +inline 1.1462 +nsGetterAddRefs<T> 1.1463 +getter_AddRefs( nsCOMPtr<T>& aSmartPtr ) 1.1464 + /* 1.1465 + Used around a |nsCOMPtr| when 1.1466 + ...makes the class |nsGetterAddRefs<T>| invisible. 1.1467 + */ 1.1468 + { 1.1469 + return nsGetterAddRefs<T>(aSmartPtr); 1.1470 + } 1.1471 + 1.1472 +template <class T, class DestinationType> 1.1473 +inline 1.1474 +nsresult 1.1475 +CallQueryInterface( T* aSource, nsGetterAddRefs<DestinationType> aDestination ) 1.1476 +{ 1.1477 + return CallQueryInterface(aSource, 1.1478 + static_cast<DestinationType**>(aDestination)); 1.1479 +} 1.1480 + 1.1481 + 1.1482 + // Comparing two |nsCOMPtr|s 1.1483 + 1.1484 +template <class T, class U> 1.1485 +inline 1.1486 +bool 1.1487 +operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs ) 1.1488 + { 1.1489 + return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get()); 1.1490 + } 1.1491 + 1.1492 + 1.1493 +template <class T, class U> 1.1494 +inline 1.1495 +bool 1.1496 +operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs ) 1.1497 + { 1.1498 + return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get()); 1.1499 + } 1.1500 + 1.1501 + 1.1502 + // Comparing an |nsCOMPtr| to a raw pointer 1.1503 + 1.1504 +template <class T, class U> 1.1505 +inline 1.1506 +bool 1.1507 +operator==( const nsCOMPtr<T>& lhs, const U* rhs ) 1.1508 + { 1.1509 + return static_cast<const T*>(lhs.get()) == rhs; 1.1510 + } 1.1511 + 1.1512 +template <class T, class U> 1.1513 +inline 1.1514 +bool 1.1515 +operator==( const U* lhs, const nsCOMPtr<T>& rhs ) 1.1516 + { 1.1517 + return lhs == static_cast<const T*>(rhs.get()); 1.1518 + } 1.1519 + 1.1520 +template <class T, class U> 1.1521 +inline 1.1522 +bool 1.1523 +operator!=( const nsCOMPtr<T>& lhs, const U* rhs ) 1.1524 + { 1.1525 + return static_cast<const T*>(lhs.get()) != rhs; 1.1526 + } 1.1527 + 1.1528 +template <class T, class U> 1.1529 +inline 1.1530 +bool 1.1531 +operator!=( const U* lhs, const nsCOMPtr<T>& rhs ) 1.1532 + { 1.1533 + return lhs != static_cast<const T*>(rhs.get()); 1.1534 + } 1.1535 + 1.1536 + // To avoid ambiguities caused by the presence of builtin |operator==|s 1.1537 + // creating a situation where one of the |operator==| defined above 1.1538 + // has a better conversion for one argument and the builtin has a 1.1539 + // better conversion for the other argument, define additional 1.1540 + // |operator==| without the |const| on the raw pointer. 1.1541 + // See bug 65664 for details. 1.1542 + 1.1543 +#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ 1.1544 +template <class T, class U> 1.1545 +inline 1.1546 +bool 1.1547 +operator==( const nsCOMPtr<T>& lhs, U* rhs ) 1.1548 + { 1.1549 + return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs); 1.1550 + } 1.1551 + 1.1552 +template <class T, class U> 1.1553 +inline 1.1554 +bool 1.1555 +operator==( U* lhs, const nsCOMPtr<T>& rhs ) 1.1556 + { 1.1557 + return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get()); 1.1558 + } 1.1559 + 1.1560 +template <class T, class U> 1.1561 +inline 1.1562 +bool 1.1563 +operator!=( const nsCOMPtr<T>& lhs, U* rhs ) 1.1564 + { 1.1565 + return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs); 1.1566 + } 1.1567 + 1.1568 +template <class T, class U> 1.1569 +inline 1.1570 +bool 1.1571 +operator!=( U* lhs, const nsCOMPtr<T>& rhs ) 1.1572 + { 1.1573 + return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get()); 1.1574 + } 1.1575 +#endif 1.1576 + 1.1577 + 1.1578 + 1.1579 + // Comparing an |nsCOMPtr| to |0| 1.1580 + 1.1581 +class NSCAP_Zero; 1.1582 + 1.1583 +template <class T> 1.1584 +inline 1.1585 +bool 1.1586 +operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs ) 1.1587 + // specifically to allow |smartPtr == 0| 1.1588 + { 1.1589 + return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs); 1.1590 + } 1.1591 + 1.1592 +template <class T> 1.1593 +inline 1.1594 +bool 1.1595 +operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs ) 1.1596 + // specifically to allow |0 == smartPtr| 1.1597 + { 1.1598 + return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get()); 1.1599 + } 1.1600 + 1.1601 +template <class T> 1.1602 +inline 1.1603 +bool 1.1604 +operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs ) 1.1605 + // specifically to allow |smartPtr != 0| 1.1606 + { 1.1607 + return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs); 1.1608 + } 1.1609 + 1.1610 +template <class T> 1.1611 +inline 1.1612 +bool 1.1613 +operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs ) 1.1614 + // specifically to allow |0 != smartPtr| 1.1615 + { 1.1616 + return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get()); 1.1617 + } 1.1618 + 1.1619 + 1.1620 +#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO 1.1621 + 1.1622 + // We need to explicitly define comparison operators for `int' 1.1623 + // because the compiler is lame. 1.1624 + 1.1625 +template <class T> 1.1626 +inline 1.1627 +bool 1.1628 +operator==( const nsCOMPtr<T>& lhs, int rhs ) 1.1629 + // specifically to allow |smartPtr == 0| 1.1630 + { 1.1631 + return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs); 1.1632 + } 1.1633 + 1.1634 +template <class T> 1.1635 +inline 1.1636 +bool 1.1637 +operator==( int lhs, const nsCOMPtr<T>& rhs ) 1.1638 + // specifically to allow |0 == smartPtr| 1.1639 + { 1.1640 + return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get()); 1.1641 + } 1.1642 + 1.1643 +#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) 1.1644 + 1.1645 + // Comparing any two [XP]COM objects for identity 1.1646 + 1.1647 +inline 1.1648 +bool 1.1649 +SameCOMIdentity( nsISupports* lhs, nsISupports* rhs ) 1.1650 + { 1.1651 + return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) ); 1.1652 + } 1.1653 + 1.1654 + 1.1655 + 1.1656 +template <class SourceType, class DestinationType> 1.1657 +inline 1.1658 +nsresult 1.1659 +CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr ) 1.1660 + { 1.1661 + return CallQueryInterface(aSourcePtr.get(), aDestPtr); 1.1662 + } 1.1663 + 1.1664 +#endif // !defined(nsCOMPtr_h___)