diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /xpcom/glue/nsCOMPtr.h | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'xpcom/glue/nsCOMPtr.h')
-rw-r--r-- | xpcom/glue/nsCOMPtr.h | 1472 |
1 files changed, 1472 insertions, 0 deletions
diff --git a/xpcom/glue/nsCOMPtr.h b/xpcom/glue/nsCOMPtr.h new file mode 100644 index 000000000..373f55cbb --- /dev/null +++ b/xpcom/glue/nsCOMPtr.h @@ -0,0 +1,1472 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsCOMPtr_h___ +#define nsCOMPtr_h___ + +/* + * Having problems? + * + * See the User Manual at: + * http://www.mozilla.org/projects/xpcom/nsCOMPtr.html + * + * + * nsCOMPtr + * better than a raw pointer + * for owning objects + * -- scc + */ + +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/Move.h" +#include "mozilla/TypeTraits.h" + +#include "nsDebug.h" // for |NS_ASSERTION| +#include "nsISupportsUtils.h" // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al +#include "mozilla/RefPtr.h" + +#include "nsCycleCollectionNoteChild.h" + + +/* + * WARNING: This file defines several macros for internal use only. These + * macros begin with the prefix |NSCAP_|. Do not use these macros in your own + * code. They are for internal use only for cross-platform compatibility, and + * are subject to change without notice. + */ + + +#ifdef _MSC_VER + // Under VC++, we win by inlining StartAssignment. + #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT + + // Also under VC++, at the highest warning level, we are overwhelmed with + // warnings about (unused) inline functions being removed. This is to be + // expected with templates, so we disable the warning. + #pragma warning( disable: 4514 ) +#endif + +#define NSCAP_FEATURE_USE_BASE + +#ifdef DEBUG + #define NSCAP_FEATURE_TEST_DONTQUERY_CASES + #undef NSCAP_FEATURE_USE_BASE +#endif + +#ifdef __GNUC__ + // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing + // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher + // don't reorder instructions based on aliasing assumptions for + // this variable. Fortunately, gcc versions < 3.3 do not do any + // optimizations that break nsCOMPtr. + + #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__)) +#else + #define NS_MAY_ALIAS_PTR(t) t* +#endif + +#if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES) + #define NSCAP_FEATURE_USE_BASE +#endif + +/* + * The following three macros (NSCAP_ADDREF, NSCAP_RELEASE, and + * NSCAP_LOG_ASSIGNMENT) allow external clients the ability to add logging or + * other interesting debug facilities. In fact, if you want |nsCOMPtr| to + * participate in the standard logging facility, you provide + * (e.g., in "nsISupportsImpl.h") suitable definitions + * + * #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr) + * #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr) + */ + +#ifndef NSCAP_ADDREF + #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef() +#endif + +#ifndef NSCAP_RELEASE + #define NSCAP_RELEASE(this, ptr) (ptr)->Release() +#endif + +// Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging. +#ifdef NSCAP_LOG_ASSIGNMENT + // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we + // know to instantiate |~nsGetterAddRefs| in turn to note the external + // assignment into the |nsCOMPtr|. + #define NSCAP_LOG_EXTERNAL_ASSIGNMENT +#else + // ...otherwise, just strip it out of the code + #define NSCAP_LOG_ASSIGNMENT(this, ptr) +#endif + +#ifndef NSCAP_LOG_RELEASE + #define NSCAP_LOG_RELEASE(this, ptr) +#endif + +namespace mozilla { +template<class T> class OwningNonNull; +} // namespace mozilla + +template<class T> +inline already_AddRefed<T> +dont_AddRef(T* aRawPtr) +{ + return already_AddRefed<T>(aRawPtr); +} + +template<class T> +inline already_AddRefed<T>&& +dont_AddRef(already_AddRefed<T>&& aAlreadyAddRefedPtr) +{ + return mozilla::Move(aAlreadyAddRefedPtr); +} + + +/* + * An nsCOMPtr_helper transforms commonly called getters into typesafe forms + * that are more convenient to call, and more efficient to use with |nsCOMPtr|s. + * Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc. + * + * Here are the rules for a helper: + * - it implements |operator()| to produce an interface pointer + * - (except for its name) |operator()| is a valid [XP]COM `getter' + * - the interface pointer that it returns is already |AddRef()|ed (as from + * any good getter) + * - it matches the type requested with the supplied |nsIID| argument + * - its constructor provides an optional |nsresult*| that |operator()| can + * fill in with an error when it is executed + * + * See |class nsGetInterface| for an example. + */ +class MOZ_STACK_CLASS nsCOMPtr_helper +{ +public: + virtual nsresult NS_FASTCALL operator()(const nsIID&, void**) const = 0; +}; + +/* + * nsQueryInterface could have been implemented as an nsCOMPtr_helper to avoid + * adding specialized machinery in nsCOMPtr, but do_QueryInterface is called + * often enough that the codesize savings are big enough to warrant the + * specialcasing. + */ +class MOZ_STACK_CLASS nsQueryInterface final +{ +public: + explicit + nsQueryInterface(nsISupports* aRawPtr) : mRawPtr(aRawPtr) {} + + nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const; + +private: + nsISupports* MOZ_OWNING_REF mRawPtr; +}; + +class nsQueryInterfaceWithError final +{ +public: + nsQueryInterfaceWithError(nsISupports* aRawPtr, nsresult* aError) + : mRawPtr(aRawPtr) + , mErrorPtr(aError) + { + } + + nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const; + +private: + nsISupports* MOZ_OWNING_REF mRawPtr; + nsresult* mErrorPtr; +}; + +inline nsQueryInterface +do_QueryInterface(nsISupports* aRawPtr) +{ + return nsQueryInterface(aRawPtr); +} + +inline nsQueryInterfaceWithError +do_QueryInterface(nsISupports* aRawPtr, nsresult* aError) +{ + return nsQueryInterfaceWithError(aRawPtr, aError); +} + +template<class T> +inline void +do_QueryInterface(already_AddRefed<T>&) +{ + // This signature exists solely to _stop_ you from doing the bad thing. + // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by + // someone else is an automatic leak. See bug 8221. +} + +template<class T> +inline void +do_QueryInterface(already_AddRefed<T>&, nsresult*) +{ + // This signature exists solely to _stop_ you from doing the bad thing. + // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by + // someone else is an automatic leak. See bug 8221. +} + + +//////////////////////////////////////////////////////////////////////////// +// Using servicemanager with COMPtrs +class nsGetServiceByCID final +{ +public: + explicit nsGetServiceByCID(const nsCID& aCID) : mCID(aCID) {} + + nsresult NS_FASTCALL operator()(const nsIID&, void**) const; + +private: + const nsCID& mCID; +}; + +class nsGetServiceByCIDWithError final +{ +public: + nsGetServiceByCIDWithError(const nsCID& aCID, nsresult* aErrorPtr) + : mCID(aCID) + , mErrorPtr(aErrorPtr) + { + } + + nsresult NS_FASTCALL operator()(const nsIID&, void**) const; + +private: + const nsCID& mCID; + nsresult* mErrorPtr; +}; + +class nsGetServiceByContractID final +{ +public: + explicit nsGetServiceByContractID(const char* aContractID) + : mContractID(aContractID) + { + } + + nsresult NS_FASTCALL operator()(const nsIID&, void**) const; + +private: + const char* mContractID; +}; + +class nsGetServiceByContractIDWithError final +{ +public: + nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr) + : mContractID(aContractID) + , mErrorPtr(aErrorPtr) + { + } + + nsresult NS_FASTCALL operator()(const nsIID&, void**) const; + +private: + const char* mContractID; + nsresult* mErrorPtr; +}; + +/** + * Factors implementation for all template versions of nsCOMPtr. + * + * Here's the way people normally do things like this: + * + * template<class T> class Foo { ... }; + * template<> class Foo<void*> { ... }; + * template<class T> class Foo<T*> : private Foo<void*> { ... }; + */ +class nsCOMPtr_base +{ +public: + explicit nsCOMPtr_base(nsISupports* aRawPtr = nullptr) : mRawPtr(aRawPtr) {} + + NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base() + { + NSCAP_LOG_RELEASE(this, mRawPtr); + if (mRawPtr) { + NSCAP_RELEASE(this, mRawPtr); + } + } + + void NS_FASTCALL + assign_with_AddRef(nsISupports*); + void NS_FASTCALL + assign_from_qi(const nsQueryInterface, const nsIID&); + void NS_FASTCALL + assign_from_qi_with_error(const nsQueryInterfaceWithError&, const nsIID&); + void NS_FASTCALL + assign_from_gs_cid(const nsGetServiceByCID, const nsIID&); + void NS_FASTCALL + assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError&, const nsIID&); + void NS_FASTCALL + assign_from_gs_contractid(const nsGetServiceByContractID, const nsIID&); + void NS_FASTCALL + assign_from_gs_contractid_with_error(const nsGetServiceByContractIDWithError&, + const nsIID&); + void NS_FASTCALL + assign_from_helper(const nsCOMPtr_helper&, const nsIID&); + void** NS_FASTCALL + begin_assignment(); + +protected: + NS_MAY_ALIAS_PTR(nsISupports) MOZ_OWNING_REF mRawPtr; + + void assign_assuming_AddRef(nsISupports* aNewPtr) + { + // |AddRef()|ing the new value (before entering this function) before + // |Release()|ing the old lets us safely ignore the self-assignment case. + // We must, however, be careful only to |Release()| _after_ doing the + // assignment, in case the |Release()| leads to our _own_ destruction, + // which would, in turn, cause an incorrect second |Release()| of our old + // pointer. Thank <waterson@netscape.com> for discovering this. + nsISupports* oldPtr = mRawPtr; + mRawPtr = aNewPtr; + NSCAP_LOG_ASSIGNMENT(this, aNewPtr); + NSCAP_LOG_RELEASE(this, oldPtr); + if (oldPtr) { + NSCAP_RELEASE(this, oldPtr); + } + } +}; + +// template<class T> class nsGetterAddRefs; + +// Helper for assert_validity method +template<class T> +char (&TestForIID(decltype(&NS_GET_TEMPLATE_IID(T))))[2]; +template<class T> +char TestForIID(...); + +template<class T> +class nsCOMPtr final +#ifdef NSCAP_FEATURE_USE_BASE + : private nsCOMPtr_base +#endif +{ + +#ifdef NSCAP_FEATURE_USE_BASE + #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x) +#else + #define NSCAP_CTOR_BASE(x) mRawPtr(x) + +private: + void assign_with_AddRef(nsISupports*); + void assign_from_qi(const nsQueryInterface, const nsIID&); + void assign_from_qi_with_error(const nsQueryInterfaceWithError&, const nsIID&); + void assign_from_gs_cid(const nsGetServiceByCID, const nsIID&); + void assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError&, + const nsIID&); + void assign_from_gs_contractid(const nsGetServiceByContractID, const nsIID&); + void assign_from_gs_contractid_with_error( + const nsGetServiceByContractIDWithError&, const nsIID&); + void assign_from_helper(const nsCOMPtr_helper&, const nsIID&); + void** begin_assignment(); + + void assign_assuming_AddRef(T* aNewPtr) + { + T* oldPtr = mRawPtr; + mRawPtr = aNewPtr; + NSCAP_LOG_ASSIGNMENT(this, aNewPtr); + NSCAP_LOG_RELEASE(this, oldPtr); + if (oldPtr) { + NSCAP_RELEASE(this, oldPtr); + } + } + +private: + T* MOZ_OWNING_REF mRawPtr; +#endif + + void assert_validity() + { + static_assert(1 < sizeof(TestForIID<T>(nullptr)), "nsCOMPtr only works " + "for types with IIDs. Either use RefPtr; add an IID to " + "your type with NS_DECLARE_STATIC_IID_ACCESSOR/" + "NS_DEFINE_STATIC_IID_ACCESSOR; or make the nsCOMPtr point " + "to a base class with an IID."); + } + +public: + typedef T element_type; + +#ifndef NSCAP_FEATURE_USE_BASE + ~nsCOMPtr() + { + NSCAP_LOG_RELEASE(this, mRawPtr); + if (mRawPtr) { + NSCAP_RELEASE(this, mRawPtr); + } + } +#endif + +#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES + void Assert_NoQueryNeeded() + { + if (mRawPtr) { + nsCOMPtr<T> query_result(do_QueryInterface(mRawPtr)); + NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed"); + } + } + + #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded(); +#else + #define NSCAP_ASSERT_NO_QUERY_NEEDED() +#endif + + + // Constructors + + nsCOMPtr() + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + } + + MOZ_IMPLICIT nsCOMPtr(decltype(nullptr)) + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + } + + nsCOMPtr(const nsCOMPtr<T>& aSmartPtr) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) + { + assert_validity(); + if (mRawPtr) { + NSCAP_ADDREF(this, mRawPtr); + } + NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr); + } + + nsCOMPtr(nsCOMPtr<T>&& aSmartPtr) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) + { + assert_validity(); + aSmartPtr.mRawPtr = nullptr; + NSCAP_LOG_ASSIGNMENT(this, mRawPtr); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + MOZ_IMPLICIT nsCOMPtr(T* aRawPtr) + : NSCAP_CTOR_BASE(aRawPtr) + { + assert_validity(); + if (mRawPtr) { + NSCAP_ADDREF(this, mRawPtr); + } + NSCAP_LOG_ASSIGNMENT(this, aRawPtr); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + MOZ_IMPLICIT nsCOMPtr(already_AddRefed<T>& aSmartPtr) + : NSCAP_CTOR_BASE(aSmartPtr.take()) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, mRawPtr); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + // Construct from |otherComPtr.forget()|. + MOZ_IMPLICIT nsCOMPtr(already_AddRefed<T>&& aSmartPtr) + : NSCAP_CTOR_BASE(aSmartPtr.take()) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, mRawPtr); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + // Construct from |already_AddRefed|. + template<typename U> + MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>& aSmartPtr) + : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take())) + { + assert_validity(); + // But make sure that U actually inherits from T. + static_assert(mozilla::IsBaseOf<T, U>::value, + "U is not a subclass of T"); + NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr)); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + // Construct from |otherComPtr.forget()|. + template<typename U> + MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>&& aSmartPtr) + : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take())) + { + assert_validity(); + // But make sure that U actually inherits from T. + static_assert(mozilla::IsBaseOf<T, U>::value, + "U is not a subclass of T"); + NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr)); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + // Construct from |do_QueryInterface(expr)|. + MOZ_IMPLICIT nsCOMPtr(const nsQueryInterface aQI) + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_qi(aQI, NS_GET_TEMPLATE_IID(T)); + } + + // Construct from |do_QueryInterface(expr, &rv)|. + MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceWithError& aQI) + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_qi_with_error(aQI, NS_GET_TEMPLATE_IID(T)); + } + + // Construct from |do_GetService(cid_expr)|. + MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS) + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_gs_cid(aGS, NS_GET_TEMPLATE_IID(T)); + } + + // Construct from |do_GetService(cid_expr, &rv)|. + MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS) + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_gs_cid_with_error(aGS, NS_GET_TEMPLATE_IID(T)); + } + + // Construct from |do_GetService(contractid_expr)|. + MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS) + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_gs_contractid(aGS, NS_GET_TEMPLATE_IID(T)); + } + + // Construct from |do_GetService(contractid_expr, &rv)|. + MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS) + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_gs_contractid_with_error(aGS, NS_GET_TEMPLATE_IID(T)); + } + + // And finally, anything else we might need to construct from can exploit the + // nsCOMPtr_helper facility. + MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper) + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_helper(aHelper, NS_GET_TEMPLATE_IID(T)); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + // Defined in OwningNonNull.h + template<class U> + MOZ_IMPLICIT nsCOMPtr(const mozilla::OwningNonNull<U>& aOther); + + + // Assignment operators + + nsCOMPtr<T>& operator=(const nsCOMPtr<T>& aRhs) + { + assign_with_AddRef(aRhs.mRawPtr); + return *this; + } + + nsCOMPtr<T>& operator=(T* aRhs) + { + assign_with_AddRef(aRhs); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + return *this; + } + + nsCOMPtr<T>& operator=(decltype(nullptr)) + { + assign_assuming_AddRef(nullptr); + return *this; + } + + // Assign from |already_AddRefed|. + template<typename U> + nsCOMPtr<T>& operator=(already_AddRefed<U>& aRhs) + { + // Make sure that U actually inherits from T + static_assert(mozilla::IsBaseOf<T, U>::value, + "U is not a subclass of T"); + assign_assuming_AddRef(static_cast<T*>(aRhs.take())); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + return *this; + } + + // Assign from |otherComPtr.forget()|. + template<typename U> + nsCOMPtr<T>& operator=(already_AddRefed<U>&& aRhs) + { + // Make sure that U actually inherits from T + static_assert(mozilla::IsBaseOf<T, U>::value, + "U is not a subclass of T"); + assign_assuming_AddRef(static_cast<T*>(aRhs.take())); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + return *this; + } + + // Assign from |do_QueryInterface(expr)|. + nsCOMPtr<T>& operator=(const nsQueryInterface aRhs) + { + assign_from_qi(aRhs, NS_GET_TEMPLATE_IID(T)); + return *this; + } + + // Assign from |do_QueryInterface(expr, &rv)|. + nsCOMPtr<T>& operator=(const nsQueryInterfaceWithError& aRhs) + { + assign_from_qi_with_error(aRhs, NS_GET_TEMPLATE_IID(T)); + return *this; + } + + // Assign from |do_GetService(cid_expr)|. + nsCOMPtr<T>& operator=(const nsGetServiceByCID aRhs) + { + assign_from_gs_cid(aRhs, NS_GET_TEMPLATE_IID(T)); + return *this; + } + + // Assign from |do_GetService(cid_expr, &rv)|. + nsCOMPtr<T>& operator=(const nsGetServiceByCIDWithError& aRhs) + { + assign_from_gs_cid_with_error(aRhs, NS_GET_TEMPLATE_IID(T)); + return *this; + } + + // Assign from |do_GetService(contractid_expr)|. + nsCOMPtr<T>& operator=(const nsGetServiceByContractID aRhs) + { + assign_from_gs_contractid(aRhs, NS_GET_TEMPLATE_IID(T)); + return *this; + } + + // Assign from |do_GetService(contractid_expr, &rv)|. + nsCOMPtr<T>& operator=(const nsGetServiceByContractIDWithError& aRhs) + { + assign_from_gs_contractid_with_error(aRhs, NS_GET_TEMPLATE_IID(T)); + return *this; + } + + // And finally, anything else we might need to assign from can exploit the + // nsCOMPtr_helper facility. + nsCOMPtr<T>& operator=(const nsCOMPtr_helper& aRhs) + { + assign_from_helper(aRhs, NS_GET_TEMPLATE_IID(T)); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + return *this; + } + + // Defined in OwningNonNull.h + template<class U> + nsCOMPtr<T>& operator=(const mozilla::OwningNonNull<U>& aOther); + + // Exchange ownership with |aRhs|; can save a pair of refcount operations. + void swap(nsCOMPtr<T>& aRhs) + { +#ifdef NSCAP_FEATURE_USE_BASE + nsISupports* temp = aRhs.mRawPtr; +#else + T* temp = aRhs.mRawPtr; +#endif + NSCAP_LOG_ASSIGNMENT(&aRhs, mRawPtr); + NSCAP_LOG_ASSIGNMENT(this, temp); + NSCAP_LOG_RELEASE(this, mRawPtr); + NSCAP_LOG_RELEASE(&aRhs, temp); + aRhs.mRawPtr = mRawPtr; + mRawPtr = temp; + // |aRhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED| + } + + // Exchange ownership with |aRhs|; can save a pair of refcount operations. + void swap(T*& aRhs) + { +#ifdef NSCAP_FEATURE_USE_BASE + nsISupports* temp = aRhs; +#else + T* temp = aRhs; +#endif + NSCAP_LOG_ASSIGNMENT(this, temp); + NSCAP_LOG_RELEASE(this, mRawPtr); + aRhs = reinterpret_cast<T*>(mRawPtr); + mRawPtr = temp; + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + + // Other pointer operators + + // Return the value of mRawPtr and null out mRawPtr. Useful for + // already_AddRefed return values. + already_AddRefed<T> forget() + { + T* temp = nullptr; + swap(temp); + return already_AddRefed<T>(temp); + } + + // Set the target of aRhs to the value of mRawPtr and null out mRawPtr. + // Useful to avoid unnecessary AddRef/Release pairs with "out" parameters + // where aRhs bay be a T** or an I** where I is a base class of T. + template<typename I> + void forget(I** aRhs) + { + NS_ASSERTION(aRhs, "Null pointer passed to forget!"); + NSCAP_LOG_RELEASE(this, mRawPtr); + *aRhs = get(); + mRawPtr = nullptr; + } + + // Prefer the implicit conversion provided automatically by + // |operator T*() const|. Use |get()| to resolve ambiguity or to get a + // castable pointer. + T* get() const { return reinterpret_cast<T*>(mRawPtr); } + + // Makes an nsCOMPtr act like its underlying raw pointer type whenever it is + // used in a context where a raw pointer is expected. It is this operator + // that makes an nsCOMPtr substitutable for a raw pointer. + // + // Prefer the implicit use of this operator to calling |get()|, except where + // necessary to resolve ambiguity. + operator T*() const +#ifdef MOZ_HAVE_REF_QUALIFIERS + & +#endif + { return get(); } + +#ifdef MOZ_HAVE_REF_QUALIFIERS + // Don't allow implicit conversion of temporary nsCOMPtr to raw pointer, + // because the refcount might be one and the pointer will immediately become + // invalid. + operator T*() const && = delete; + + // Needed to avoid the deleted operator above + explicit operator bool() const { return !!mRawPtr; } +#endif + + T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN + { + MOZ_ASSERT(mRawPtr != nullptr, + "You can't dereference a NULL nsCOMPtr with operator->()."); + return get(); + } + + // These are not intended to be used by clients. See |address_of| below. + nsCOMPtr<T>* get_address() { return this; } + const nsCOMPtr<T>* get_address() const { return this; } + +public: + T& operator*() const + { + MOZ_ASSERT(mRawPtr != nullptr, + "You can't dereference a NULL nsCOMPtr with operator*()."); + return *get(); + } + + T** StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return reinterpret_cast<T**>(begin_assignment()); +#else + assign_assuming_AddRef(nullptr); + return reinterpret_cast<T**>(&mRawPtr); +#endif + } +}; + + +/* + * Specializing nsCOMPtr for nsISupports allows us to use nsCOMPtr<nsISupports> + * the same way people use nsISupports* and void*, i.e., as a `catch-all' + * pointing to any valid [XP]COM interface. Otherwise, an nsCOMPtr<nsISupports> + * would only be able to point to the single [XP]COM-correct nsISupports + * instance within an object; extra querying ensues. Clients need to be able to + * pass around arbitrary interface pointers, without hassles, through + * intermediary code that doesn't know the exact type. + */ +template<> +class nsCOMPtr<nsISupports> + : private nsCOMPtr_base +{ +public: + typedef nsISupports element_type; + + // Constructors + + nsCOMPtr() + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); + } + + MOZ_IMPLICIT nsCOMPtr(decltype(nullptr)) + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); + } + + nsCOMPtr(const nsCOMPtr<nsISupports>& aSmartPtr) + : nsCOMPtr_base(aSmartPtr.mRawPtr) + { + if (mRawPtr) { + NSCAP_ADDREF(this, mRawPtr); + } + NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr); + } + + MOZ_IMPLICIT nsCOMPtr(nsISupports* aRawPtr) + : nsCOMPtr_base(aRawPtr) + { + if (mRawPtr) { + NSCAP_ADDREF(this, mRawPtr); + } + NSCAP_LOG_ASSIGNMENT(this, aRawPtr); + } + + // Construct from |already_AddRefed|. + MOZ_IMPLICIT nsCOMPtr(already_AddRefed<nsISupports>& aSmartPtr) + : nsCOMPtr_base(aSmartPtr.take()) + { + NSCAP_LOG_ASSIGNMENT(this, mRawPtr); + } + + // Construct from |otherComPtr.forget()|. + MOZ_IMPLICIT nsCOMPtr(already_AddRefed<nsISupports>&& aSmartPtr) + : nsCOMPtr_base(aSmartPtr.take()) + { + NSCAP_LOG_ASSIGNMENT(this, mRawPtr); + } + + // Construct from |do_QueryInterface(expr)|. + MOZ_IMPLICIT nsCOMPtr(const nsQueryInterface aQI) + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_qi(aQI, NS_GET_IID(nsISupports)); + } + + // Construct from |do_QueryInterface(expr, &rv)|. + MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceWithError& aQI) + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_qi_with_error(aQI, NS_GET_IID(nsISupports)); + } + + // Construct from |do_GetService(cid_expr)|. + MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS) + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_gs_cid(aGS, NS_GET_IID(nsISupports)); + } + + // Construct from |do_GetService(cid_expr, &rv)|. + MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS) + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_gs_cid_with_error(aGS, NS_GET_IID(nsISupports)); + } + + // Construct from |do_GetService(contractid_expr)|. + MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS) + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_gs_contractid(aGS, NS_GET_IID(nsISupports)); + } + + // Construct from |do_GetService(contractid_expr, &rv)|. + MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS) + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_gs_contractid_with_error(aGS, NS_GET_IID(nsISupports)); + } + + // And finally, anything else we might need to construct from can exploit + // the |nsCOMPtr_helper| facility + MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper) + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); + assign_from_helper(aHelper, NS_GET_IID(nsISupports)); + } + + + // Assignment operators + + nsCOMPtr<nsISupports>& operator=(const nsCOMPtr<nsISupports>& aRhs) + { + assign_with_AddRef(aRhs.mRawPtr); + return *this; + } + + nsCOMPtr<nsISupports>& operator=(nsISupports* aRhs) + { + assign_with_AddRef(aRhs); + return *this; + } + + nsCOMPtr<nsISupports>& operator=(decltype(nullptr)) + { + assign_assuming_AddRef(nullptr); + return *this; + } + + // Assign from |already_AddRefed|. + nsCOMPtr<nsISupports>& operator=(already_AddRefed<nsISupports>& aRhs) + { + assign_assuming_AddRef(aRhs.take()); + return *this; + } + + // Assign from |otherComPtr.forget()|. + nsCOMPtr<nsISupports>& operator=(already_AddRefed<nsISupports>&& aRhs) + { + assign_assuming_AddRef(aRhs.take()); + return *this; + } + + // Assign from |do_QueryInterface(expr)|. + nsCOMPtr<nsISupports>& operator=(const nsQueryInterface aRhs) + { + assign_from_qi(aRhs, NS_GET_IID(nsISupports)); + return *this; + } + + // Assign from |do_QueryInterface(expr, &rv)|. + nsCOMPtr<nsISupports>& operator=(const nsQueryInterfaceWithError& aRhs) + { + assign_from_qi_with_error(aRhs, NS_GET_IID(nsISupports)); + return *this; + } + + // Assign from |do_GetService(cid_expr)|. + nsCOMPtr<nsISupports>& operator=(const nsGetServiceByCID aRhs) + { + assign_from_gs_cid(aRhs, NS_GET_IID(nsISupports)); + return *this; + } + + // Assign from |do_GetService(cid_expr, &rv)|. + nsCOMPtr<nsISupports>& operator=(const nsGetServiceByCIDWithError& aRhs) + { + assign_from_gs_cid_with_error(aRhs, NS_GET_IID(nsISupports)); + return *this; + } + + // Assign from |do_GetService(contractid_expr)|. + nsCOMPtr<nsISupports>& operator=(const nsGetServiceByContractID aRhs) + { + assign_from_gs_contractid(aRhs, NS_GET_IID(nsISupports)); + return *this; + } + + // Assign from |do_GetService(contractid_expr, &rv)|. + nsCOMPtr<nsISupports>& operator=(const nsGetServiceByContractIDWithError& aRhs) + { + assign_from_gs_contractid_with_error(aRhs, NS_GET_IID(nsISupports)); + return *this; + } + + // And finally, anything else we might need to assign from can exploit the + // nsCOMPtr_helper facility + nsCOMPtr<nsISupports>& operator=(const nsCOMPtr_helper& aRhs) + { + assign_from_helper(aRhs, NS_GET_IID(nsISupports)); + return *this; + } + + // Exchange ownership with |aRhs|; can save a pair of refcount operations. + void swap(nsCOMPtr<nsISupports>& aRhs) + { + nsISupports* temp = aRhs.mRawPtr; + NSCAP_LOG_ASSIGNMENT(&aRhs, mRawPtr); + NSCAP_LOG_ASSIGNMENT(this, temp); + NSCAP_LOG_RELEASE(this, mRawPtr); + NSCAP_LOG_RELEASE(&aRhs, temp); + aRhs.mRawPtr = mRawPtr; + mRawPtr = temp; + } + + // Exchange ownership with |aRhs|; can save a pair of refcount operations. + void swap(nsISupports*& aRhs) + { + nsISupports* temp = aRhs; + NSCAP_LOG_ASSIGNMENT(this, temp); + NSCAP_LOG_RELEASE(this, mRawPtr); + aRhs = mRawPtr; + mRawPtr = temp; + } + + // Return the value of mRawPtr and null out mRawPtr. Useful for + // already_AddRefed return values. + already_AddRefed<nsISupports> forget() + { + nsISupports* temp = nullptr; + swap(temp); + return already_AddRefed<nsISupports>(temp); + } + + // Set the target of aRhs to the value of mRawPtr and null out mRawPtr. + // Useful to avoid unnecessary AddRef/Release pairs with "out" + // parameters. + void forget(nsISupports** aRhs) + { + NS_ASSERTION(aRhs, "Null pointer passed to forget!"); + *aRhs = nullptr; + swap(*aRhs); + } + + // Other pointer operators + + // Prefer the implicit conversion provided automatically by + // |operator nsISupports*() const|. Use |get()| to resolve ambiguity or to + // get a castable pointer. + nsISupports* get() const { return reinterpret_cast<nsISupports*>(mRawPtr); } + + // Makes an nsCOMPtr act like its underlying raw pointer type whenever it is + // used in a context where a raw pointer is expected. It is this operator + // that makes an nsCOMPtr substitutable for a raw pointer. + // + // Prefer the implicit use of this operator to calling |get()|, except where + // necessary to resolve ambiguity/ + operator nsISupports* () const { return get(); } + + nsISupports* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN + { + MOZ_ASSERT(mRawPtr != nullptr, + "You can't dereference a NULL nsCOMPtr with operator->()."); + return get(); + } + + // These are not intended to be used by clients. See |address_of| below. + nsCOMPtr<nsISupports>* get_address() { return this; } + const nsCOMPtr<nsISupports>* get_address() const { return this; } + +public: + + nsISupports& operator*() const + { + MOZ_ASSERT(mRawPtr != nullptr, + "You can't dereference a NULL nsCOMPtr with operator*()."); + return *get(); + } + + nsISupports** StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return reinterpret_cast<nsISupports**>(begin_assignment()); +#else + assign_assuming_AddRef(nullptr); + return reinterpret_cast<nsISupports**>(&mRawPtr); +#endif + } +}; + +template<typename T> +inline void +ImplCycleCollectionUnlink(nsCOMPtr<T>& aField) +{ + aField = nullptr; +} + +template<typename T> +inline void +ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, + nsCOMPtr<T>& aField, + const char* aName, + uint32_t aFlags = 0) +{ + CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags); +} + +#ifndef NSCAP_FEATURE_USE_BASE +template<class T> +void +nsCOMPtr<T>::assign_with_AddRef(nsISupports* aRawPtr) +{ + if (aRawPtr) { + NSCAP_ADDREF(this, aRawPtr); + } + assign_assuming_AddRef(reinterpret_cast<T*>(aRawPtr)); +} + +template<class T> +void +nsCOMPtr<T>::assign_from_qi(const nsQueryInterface aQI, const nsIID& aIID) +{ + void* newRawPtr; + if (NS_FAILED(aQI(aIID, &newRawPtr))) { + newRawPtr = nullptr; + } + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); +} + +template<class T> +void +nsCOMPtr<T>::assign_from_qi_with_error(const nsQueryInterfaceWithError& aQI, + const nsIID& aIID) +{ + void* newRawPtr; + if (NS_FAILED(aQI(aIID, &newRawPtr))) { + newRawPtr = nullptr; + } + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); +} + +template<class T> +void +nsCOMPtr<T>::assign_from_gs_cid(const nsGetServiceByCID aGS, const nsIID& aIID) +{ + void* newRawPtr; + if (NS_FAILED(aGS(aIID, &newRawPtr))) { + newRawPtr = nullptr; + } + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); +} + +template<class T> +void +nsCOMPtr<T>::assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError& aGS, + const nsIID& aIID) +{ + void* newRawPtr; + if (NS_FAILED(aGS(aIID, &newRawPtr))) { + newRawPtr = nullptr; + } + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); +} + +template<class T> +void +nsCOMPtr<T>::assign_from_gs_contractid(const nsGetServiceByContractID aGS, + const nsIID& aIID) +{ + void* newRawPtr; + if (NS_FAILED(aGS(aIID, &newRawPtr))) { + newRawPtr = nullptr; + } + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); +} + +template<class T> +void +nsCOMPtr<T>::assign_from_gs_contractid_with_error( + const nsGetServiceByContractIDWithError& aGS, const nsIID& aIID) +{ + void* newRawPtr; + if (NS_FAILED(aGS(aIID, &newRawPtr))) { + newRawPtr = nullptr; + } + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); +} + +template<class T> +void +nsCOMPtr<T>::assign_from_helper(const nsCOMPtr_helper& helper, const nsIID& aIID) +{ + void* newRawPtr; + if (NS_FAILED(helper(aIID, &newRawPtr))) { + newRawPtr = nullptr; + } + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); +} + +template<class T> +void** +nsCOMPtr<T>::begin_assignment() +{ + assign_assuming_AddRef(nullptr); + union + { + T** mT; + void** mVoid; + } result; + result.mT = &mRawPtr; + return result.mVoid; +} +#endif + +template<class T> +inline nsCOMPtr<T>* +address_of(nsCOMPtr<T>& aPtr) +{ + return aPtr.get_address(); +} + +template<class T> +inline const nsCOMPtr<T>* +address_of(const nsCOMPtr<T>& aPtr) +{ + return aPtr.get_address(); +} + +/** + * This class is designed to be used for anonymous temporary objects in the + * argument list of calls that return COM interface pointers, e.g., + * + * nsCOMPtr<IFoo> fooP; + * ...->QueryInterface(iid, getter_AddRefs(fooP)) + * + * DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead. + * + * When initialized with a |nsCOMPtr|, as in the example above, it returns + * a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call + * (|QueryInterface| in this case) can fill in. + * + * This type should be a nested class inside |nsCOMPtr<T>|. + */ +template<class T> +class nsGetterAddRefs +{ +public: + explicit nsGetterAddRefs(nsCOMPtr<T>& aSmartPtr) + : mTargetSmartPtr(aSmartPtr) + { + } + +#if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT) + ~nsGetterAddRefs() + { +#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT + NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void*>(address_of(mTargetSmartPtr)), + mTargetSmartPtr.get()); +#endif + +#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES + mTargetSmartPtr.Assert_NoQueryNeeded(); +#endif + } +#endif + + operator void**() + { + return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment()); + } + + operator T**() { return mTargetSmartPtr.StartAssignment(); } + T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); } + +private: + nsCOMPtr<T>& mTargetSmartPtr; +}; + + +template<> +class nsGetterAddRefs<nsISupports> +{ +public: + explicit nsGetterAddRefs(nsCOMPtr<nsISupports>& aSmartPtr) + : mTargetSmartPtr(aSmartPtr) + { + } + +#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT + ~nsGetterAddRefs() + { + NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void*>(address_of(mTargetSmartPtr)), + mTargetSmartPtr.get()); + } +#endif + + operator void**() + { + return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment()); + } + + operator nsISupports**() { return mTargetSmartPtr.StartAssignment(); } + nsISupports*& operator*() { return *(mTargetSmartPtr.StartAssignment()); } + +private: + nsCOMPtr<nsISupports>& mTargetSmartPtr; +}; + +template<class T> +inline nsGetterAddRefs<T> +getter_AddRefs(nsCOMPtr<T>& aSmartPtr) +{ + return nsGetterAddRefs<T>(aSmartPtr); +} + +template<class T, class DestinationType> +inline nsresult +CallQueryInterface(T* aSource, nsGetterAddRefs<DestinationType> aDestination) +{ + return CallQueryInterface(aSource, + static_cast<DestinationType**>(aDestination)); +} + + +// Comparing two |nsCOMPtr|s + +template<class T, class U> +inline bool +operator==(const nsCOMPtr<T>& aLhs, const nsCOMPtr<U>& aRhs) +{ + return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get()); +} + + +template<class T, class U> +inline bool +operator!=(const nsCOMPtr<T>& aLhs, const nsCOMPtr<U>& aRhs) +{ + return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get()); +} + + +// Comparing an |nsCOMPtr| to a raw pointer + +template<class T, class U> +inline bool +operator==(const nsCOMPtr<T>& aLhs, const U* aRhs) +{ + return static_cast<const T*>(aLhs.get()) == aRhs; +} + +template<class T, class U> +inline bool +operator==(const U* aLhs, const nsCOMPtr<T>& aRhs) +{ + return aLhs == static_cast<const T*>(aRhs.get()); +} + +template<class T, class U> +inline bool +operator!=(const nsCOMPtr<T>& aLhs, const U* aRhs) +{ + return static_cast<const T*>(aLhs.get()) != aRhs; +} + +template<class T, class U> +inline bool +operator!=(const U* aLhs, const nsCOMPtr<T>& aRhs) +{ + return aLhs != static_cast<const T*>(aRhs.get()); +} + +template<class T, class U> +inline bool +operator==(const nsCOMPtr<T>& aLhs, U* aRhs) +{ + return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs); +} + +template<class T, class U> +inline bool +operator==(U* aLhs, const nsCOMPtr<T>& aRhs) +{ + return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get()); +} + +template<class T, class U> +inline bool +operator!=(const nsCOMPtr<T>& aLhs, U* aRhs) +{ + return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs); +} + +template<class T, class U> +inline bool +operator!=(U* aLhs, const nsCOMPtr<T>& aRhs) +{ + return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get()); +} + + + +// Comparing an |nsCOMPtr| to |nullptr| + +template<class T> +inline bool +operator==(const nsCOMPtr<T>& aLhs, decltype(nullptr)) +{ + return aLhs.get() == nullptr; +} + +template<class T> +inline bool +operator==(decltype(nullptr), const nsCOMPtr<T>& aRhs) +{ + return nullptr == aRhs.get(); +} + +template<class T> +inline bool +operator!=(const nsCOMPtr<T>& aLhs, decltype(nullptr)) +{ + return aLhs.get() != nullptr; +} + +template<class T> +inline bool +operator!=(decltype(nullptr), const nsCOMPtr<T>& aRhs) +{ + return nullptr != aRhs.get(); +} + + +// Comparing any two [XP]COM objects for identity + +inline bool +SameCOMIdentity(nsISupports* aLhs, nsISupports* aRhs) +{ + return nsCOMPtr<nsISupports>(do_QueryInterface(aLhs)) == + nsCOMPtr<nsISupports>(do_QueryInterface(aRhs)); +} + + + +template<class SourceType, class DestinationType> +inline nsresult +CallQueryInterface(nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr) +{ + return CallQueryInterface(aSourcePtr.get(), aDestPtr); +} + +template <class T> +RefPtr<T>::RefPtr(const nsCOMPtr_helper& aHelper) +{ + void* newRawPtr; + if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) { + newRawPtr = nullptr; + } + mRawPtr = static_cast<T*>(newRawPtr); +} + +template <class T> +RefPtr<T>& +RefPtr<T>::operator=(const nsCOMPtr_helper& aHelper) +{ + void* newRawPtr; + if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) { + newRawPtr = nullptr; + } + assign_assuming_AddRef(static_cast<T*>(newRawPtr)); + return *this; +} + + +#endif // !defined(nsCOMPtr_h___) |