From a9bb3d6a1642e677a88ecab3033375c6059202a9 Mon Sep 17 00:00:00 2001 From: "scc%netscape.com" Date: Thu, 15 Jul 1999 03:59:09 +0000 Subject: [PATCH] new feature lets you `see past' |nsISupports| in |nsCOMPtr|s. Now in the debugger (in debug versions only) you will see the actual type of the object. This is enabled by defining the preprocessor symbol |NSCAP_FEATURE_DEBUG_PTR_TYPES|. It cannot be turned on in non-debug builds. It is currently on in debug builds by default. It may become a feature that has to be enabled with a build command line switch. NSCAP_FEATURE_ALLOW_RAW_POINTERS is now always the case and no longer optional; NSCAP_FEATURE_ALLOW_COMPARISONS is now always the case and no longer optional; cleaned up the previous definition and invocations of the |Assert_NoQueryNeeded| test. --- xpcom/base/nsCOMPtr.h | 184 ++++++++++++++++++++++++------------------ xpcom/glue/nsCOMPtr.h | 184 ++++++++++++++++++++++++------------------ 2 files changed, 212 insertions(+), 156 deletions(-) diff --git a/xpcom/base/nsCOMPtr.h b/xpcom/base/nsCOMPtr.h index fb0de3f7ec02..a2dab74d7aca 100644 --- a/xpcom/base/nsCOMPtr.h +++ b/xpcom/base/nsCOMPtr.h @@ -69,7 +69,6 @@ + Improve internal documentation + mention *& - + alternatives for comparison + do_QueryInterface */ @@ -114,12 +113,19 @@ // under VC++, we win by inlining StartAssignment #endif -#define NSCAP_FEATURE_ALLOW_RAW_POINTERS -#define NSCAP_FEATURE_ALLOW_COMPARISONS #define NSCAP_FEATURE_FACTOR_DESTRUCTOR #ifdef NS_DEBUG #define NSCAP_FEATURE_TEST_DONTQUERY_CASES + #define NSCAP_FEATURE_DEBUG_PTR_TYPES +#endif + +#ifndef NS_DEBUG + #undef NSCAP_FEATURE_DEBUG_PTR_TYPES +#endif + +#ifdef NSCAP_FEATURE_DEBUG_PTR_TYPES + #undef NSCAP_FEATURE_FACTOR_DESTRUCTOR #endif @@ -189,7 +195,8 @@ class nsDerivedSafe : public T void operator delete( void*, size_t ); // NOT TO BE IMPLEMENTED // declaring |operator delete| private makes calling delete on an interface pointer a compile error - nsDerivedSafe& operator=( const nsDerivedSafe& ); // NOT TO BE IMPLEMENTED + nsDerivedSafe& operator=( const nsDerivedSafe& ); // NOT TO BE IMPLEMENTED +// nsDerivedSafe& operator=( const T& ); // NOT TO BE IMPLEMENTED // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one }; @@ -219,6 +226,8 @@ struct nsDontQueryInterface ... DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |dont_QueryInterface()| instead. + + This type should be a nested class inside |nsCOMPtr|. */ { explicit @@ -268,26 +277,7 @@ do_QueryInterface( nsISupports* aRawPtr, nsresult* error = 0 ) return nsQueryInterface(aRawPtr, error); } -#ifdef NSCAP_FEATURE_ALLOW_RAW_POINTERS - - #define null_nsCOMPtr() (0) - -#else - - inline - const nsQueryInterface - null_nsCOMPtr() - /* - You can use this to assign |NULL| into an |nsCOMPtr|, e.g., - - myPtr = null_nsCOMPtr(); - */ - { - typedef nsISupports* nsISupports_Ptr; - return nsQueryInterface(nsISupports_Ptr(0)); - } - -#endif +#define null_nsCOMPtr() (0) @@ -303,6 +293,8 @@ struct nsDontAddRef |dont_AddRef()| instead. See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|. + + This type should be a nested class inside |nsCOMPtr|. */ { explicit @@ -354,14 +346,6 @@ class nsCOMPtr_base NS_EXPORT ~nsCOMPtr_base(); #endif -#if 0 - ~nsCOMPtr_base() - { - if ( mRawPtr ) - NSCAP_RELEASE(mRawPtr); - } -#endif - NS_EXPORT void assign_with_AddRef( nsISupports* ); NS_EXPORT void assign_with_QueryInterface( nsISupports*, const nsIID&, nsresult* ); NS_EXPORT void** begin_assignment(); @@ -373,19 +357,28 @@ class nsCOMPtr_base template -class nsCOMPtr : private nsCOMPtr_base - /* - ... - */ +class nsCOMPtr +#ifndef NSCAP_FEATURE_DEBUG_PTR_TYPES + : private nsCOMPtr_base +#endif { +#ifdef NSCAP_FEATURE_DEBUG_PTR_TYPES + private: + void assign_with_AddRef( nsISupports* ); + void assign_with_QueryInterface( nsISupports*, const nsIID&, nsresult* ); + void** begin_assignment(); + + private: + T* mRawPtr; + + #define NSCAP_CTOR_BASE(x) mRawPtr(x) +#else + #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x) +#endif + public: typedef T element_type; -#if 0 - typedef nsDerivedSafe* safe_ptr_t; - typedef T* safe_ptr_t; -#endif - #ifndef NSCAP_FEATURE_FACTOR_DESTRUCTOR ~nsCOMPtr() { @@ -395,13 +388,13 @@ class nsCOMPtr : private nsCOMPtr_base #endif nsCOMPtr() - // : nsCOMPtr_base(0) + : NSCAP_CTOR_BASE(0) { // nothing else to do here } nsCOMPtr( const nsQueryInterface& aSmartPtr ) - // : nsCOMPtr_base(0) + : NSCAP_CTOR_BASE(0) { assign_with_QueryInterface(aSmartPtr.mRawPtr, nsCOMTypeInfo::GetIID(), aSmartPtr.mErrorPtr); } @@ -410,62 +403,59 @@ class nsCOMPtr : private nsCOMPtr_base void Assert_NoQueryNeeded() { - if ( !mRawPtr ) - return; - T* query_result = 0; - nsresult status = CallQueryInterface(mRawPtr, &query_result); - NS_ASSERTION(query_result == mRawPtr, "QueryInterface needed"); - if ( NS_SUCCEEDED(status) ) - NSCAP_RELEASE(query_result); + if ( mRawPtr ) + { + T* query_result = 0; + nsresult status = CallQueryInterface(mRawPtr, &query_result); + NS_ASSERTION(query_result == mRawPtr, "QueryInterface needed"); + if ( NS_SUCCEEDED(status) ) + NSCAP_RELEASE(query_result); + } } + + #define NSCAP_ASSERT_NO_QUERY_NEEDED(); Assert_NoQueryNeeded(); +#else + #define NSCAP_ASSERT_NO_QUERY_NEEDED(); #endif nsCOMPtr( const nsDontAddRef& aSmartPtr ) - : nsCOMPtr_base(aSmartPtr.mRawPtr) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) { -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + NSCAP_ASSERT_NO_QUERY_NEEDED(); } nsCOMPtr( const nsDontQueryInterface& aSmartPtr ) - : nsCOMPtr_base(aSmartPtr.mRawPtr) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) { if ( mRawPtr ) NSCAP_ADDREF(mRawPtr); -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + + NSCAP_ASSERT_NO_QUERY_NEEDED(); } nsCOMPtr( const nsCOMPtr& aSmartPtr ) - : nsCOMPtr_base(aSmartPtr.mRawPtr) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) { if ( mRawPtr ) NSCAP_ADDREF(mRawPtr); } -#ifdef NSCAP_FEATURE_ALLOW_RAW_POINTERS nsCOMPtr( T* aRawPtr ) - : nsCOMPtr_base(aRawPtr) + : NSCAP_CTOR_BASE(aRawPtr) { if ( mRawPtr ) NSCAP_ADDREF(mRawPtr); -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + + NSCAP_ASSERT_NO_QUERY_NEEDED(); } nsCOMPtr& operator=( T* rhs ) { assign_with_AddRef(rhs); -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + NSCAP_ASSERT_NO_QUERY_NEEDED(); return *this; } -#endif nsCOMPtr& operator=( const nsQueryInterface& rhs ) @@ -480,9 +470,8 @@ class nsCOMPtr : private nsCOMPtr_base if ( mRawPtr ) NSCAP_RELEASE(mRawPtr); mRawPtr = rhs.mRawPtr; -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + + NSCAP_ASSERT_NO_QUERY_NEEDED(); return *this; } @@ -490,9 +479,7 @@ class nsCOMPtr : private nsCOMPtr_base operator=( const nsDontQueryInterface& rhs ) { assign_with_AddRef(rhs.mRawPtr); -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + NSCAP_ASSERT_NO_QUERY_NEEDED(); return *this; } @@ -560,6 +547,49 @@ class nsCOMPtr : private nsCOMPtr_base } }; +#ifdef NSCAP_FEATURE_DEBUG_PTR_TYPES +template +void +nsCOMPtr::assign_with_AddRef( nsISupports* rawPtr ) + { + if ( rawPtr ) + NSCAP_ADDREF(rawPtr); + if ( mRawPtr ) + NSCAP_RELEASE(mRawPtr); + mRawPtr = NS_REINTERPRET_CAST(T*, rawPtr); + } + +template +void +nsCOMPtr::assign_with_QueryInterface( nsISupports* rawPtr, const nsIID& iid, nsresult* result ) + { + nsresult status = NS_ERROR_NULL_POINTER; + if ( !rawPtr || !NS_SUCCEEDED( status = rawPtr->QueryInterface(iid, NSCAP_REINTERPRET_CAST(void**, &rawPtr)) ) ) + rawPtr = 0; + + if ( mRawPtr ) + NSCAP_RELEASE(mRawPtr); + + mRawPtr = NS_REINTERPRET_CAST(T*, rawPtr); + + if ( result ) + *result = status; + } + +template +void** +nsCOMPtr::begin_assignment() + { + if ( mRawPtr ) + { + NSCAP_RELEASE(mRawPtr); + mRawPtr = 0; + } + + return NSCAP_REINTERPRET_CAST(void**, &mRawPtr); + } +#endif + template class nsGetterAddRefs @@ -577,6 +607,8 @@ class nsGetterAddRefs When initialized with a |nsCOMPtr|, as in the example above, it returns a |void**| (or |T**| if needed) that the outer call (|QueryInterface| in this case) can fill in. + + This type should be a nested class inside |nsCOMPtr|. */ { public: @@ -620,8 +652,6 @@ getter_AddRefs( nsCOMPtr& aSmartPtr ) } -#ifdef NSCAP_FEATURE_ALLOW_COMPARISONS - class NSCAP_Zero; template @@ -715,8 +745,6 @@ SameCOMIdentity( nsISupports* lhs, nsISupports* rhs ) return nsCOMPtr( do_QueryInterface(lhs) ) == nsCOMPtr( do_QueryInterface(rhs) ); } -#endif // defined(NSCAP_FEATURE_ALLOW_COMPARISONS) - template inline diff --git a/xpcom/glue/nsCOMPtr.h b/xpcom/glue/nsCOMPtr.h index fb0de3f7ec02..a2dab74d7aca 100644 --- a/xpcom/glue/nsCOMPtr.h +++ b/xpcom/glue/nsCOMPtr.h @@ -69,7 +69,6 @@ + Improve internal documentation + mention *& - + alternatives for comparison + do_QueryInterface */ @@ -114,12 +113,19 @@ // under VC++, we win by inlining StartAssignment #endif -#define NSCAP_FEATURE_ALLOW_RAW_POINTERS -#define NSCAP_FEATURE_ALLOW_COMPARISONS #define NSCAP_FEATURE_FACTOR_DESTRUCTOR #ifdef NS_DEBUG #define NSCAP_FEATURE_TEST_DONTQUERY_CASES + #define NSCAP_FEATURE_DEBUG_PTR_TYPES +#endif + +#ifndef NS_DEBUG + #undef NSCAP_FEATURE_DEBUG_PTR_TYPES +#endif + +#ifdef NSCAP_FEATURE_DEBUG_PTR_TYPES + #undef NSCAP_FEATURE_FACTOR_DESTRUCTOR #endif @@ -189,7 +195,8 @@ class nsDerivedSafe : public T void operator delete( void*, size_t ); // NOT TO BE IMPLEMENTED // declaring |operator delete| private makes calling delete on an interface pointer a compile error - nsDerivedSafe& operator=( const nsDerivedSafe& ); // NOT TO BE IMPLEMENTED + nsDerivedSafe& operator=( const nsDerivedSafe& ); // NOT TO BE IMPLEMENTED +// nsDerivedSafe& operator=( const T& ); // NOT TO BE IMPLEMENTED // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one }; @@ -219,6 +226,8 @@ struct nsDontQueryInterface ... DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |dont_QueryInterface()| instead. + + This type should be a nested class inside |nsCOMPtr|. */ { explicit @@ -268,26 +277,7 @@ do_QueryInterface( nsISupports* aRawPtr, nsresult* error = 0 ) return nsQueryInterface(aRawPtr, error); } -#ifdef NSCAP_FEATURE_ALLOW_RAW_POINTERS - - #define null_nsCOMPtr() (0) - -#else - - inline - const nsQueryInterface - null_nsCOMPtr() - /* - You can use this to assign |NULL| into an |nsCOMPtr|, e.g., - - myPtr = null_nsCOMPtr(); - */ - { - typedef nsISupports* nsISupports_Ptr; - return nsQueryInterface(nsISupports_Ptr(0)); - } - -#endif +#define null_nsCOMPtr() (0) @@ -303,6 +293,8 @@ struct nsDontAddRef |dont_AddRef()| instead. See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|. + + This type should be a nested class inside |nsCOMPtr|. */ { explicit @@ -354,14 +346,6 @@ class nsCOMPtr_base NS_EXPORT ~nsCOMPtr_base(); #endif -#if 0 - ~nsCOMPtr_base() - { - if ( mRawPtr ) - NSCAP_RELEASE(mRawPtr); - } -#endif - NS_EXPORT void assign_with_AddRef( nsISupports* ); NS_EXPORT void assign_with_QueryInterface( nsISupports*, const nsIID&, nsresult* ); NS_EXPORT void** begin_assignment(); @@ -373,19 +357,28 @@ class nsCOMPtr_base template -class nsCOMPtr : private nsCOMPtr_base - /* - ... - */ +class nsCOMPtr +#ifndef NSCAP_FEATURE_DEBUG_PTR_TYPES + : private nsCOMPtr_base +#endif { +#ifdef NSCAP_FEATURE_DEBUG_PTR_TYPES + private: + void assign_with_AddRef( nsISupports* ); + void assign_with_QueryInterface( nsISupports*, const nsIID&, nsresult* ); + void** begin_assignment(); + + private: + T* mRawPtr; + + #define NSCAP_CTOR_BASE(x) mRawPtr(x) +#else + #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x) +#endif + public: typedef T element_type; -#if 0 - typedef nsDerivedSafe* safe_ptr_t; - typedef T* safe_ptr_t; -#endif - #ifndef NSCAP_FEATURE_FACTOR_DESTRUCTOR ~nsCOMPtr() { @@ -395,13 +388,13 @@ class nsCOMPtr : private nsCOMPtr_base #endif nsCOMPtr() - // : nsCOMPtr_base(0) + : NSCAP_CTOR_BASE(0) { // nothing else to do here } nsCOMPtr( const nsQueryInterface& aSmartPtr ) - // : nsCOMPtr_base(0) + : NSCAP_CTOR_BASE(0) { assign_with_QueryInterface(aSmartPtr.mRawPtr, nsCOMTypeInfo::GetIID(), aSmartPtr.mErrorPtr); } @@ -410,62 +403,59 @@ class nsCOMPtr : private nsCOMPtr_base void Assert_NoQueryNeeded() { - if ( !mRawPtr ) - return; - T* query_result = 0; - nsresult status = CallQueryInterface(mRawPtr, &query_result); - NS_ASSERTION(query_result == mRawPtr, "QueryInterface needed"); - if ( NS_SUCCEEDED(status) ) - NSCAP_RELEASE(query_result); + if ( mRawPtr ) + { + T* query_result = 0; + nsresult status = CallQueryInterface(mRawPtr, &query_result); + NS_ASSERTION(query_result == mRawPtr, "QueryInterface needed"); + if ( NS_SUCCEEDED(status) ) + NSCAP_RELEASE(query_result); + } } + + #define NSCAP_ASSERT_NO_QUERY_NEEDED(); Assert_NoQueryNeeded(); +#else + #define NSCAP_ASSERT_NO_QUERY_NEEDED(); #endif nsCOMPtr( const nsDontAddRef& aSmartPtr ) - : nsCOMPtr_base(aSmartPtr.mRawPtr) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) { -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + NSCAP_ASSERT_NO_QUERY_NEEDED(); } nsCOMPtr( const nsDontQueryInterface& aSmartPtr ) - : nsCOMPtr_base(aSmartPtr.mRawPtr) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) { if ( mRawPtr ) NSCAP_ADDREF(mRawPtr); -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + + NSCAP_ASSERT_NO_QUERY_NEEDED(); } nsCOMPtr( const nsCOMPtr& aSmartPtr ) - : nsCOMPtr_base(aSmartPtr.mRawPtr) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) { if ( mRawPtr ) NSCAP_ADDREF(mRawPtr); } -#ifdef NSCAP_FEATURE_ALLOW_RAW_POINTERS nsCOMPtr( T* aRawPtr ) - : nsCOMPtr_base(aRawPtr) + : NSCAP_CTOR_BASE(aRawPtr) { if ( mRawPtr ) NSCAP_ADDREF(mRawPtr); -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + + NSCAP_ASSERT_NO_QUERY_NEEDED(); } nsCOMPtr& operator=( T* rhs ) { assign_with_AddRef(rhs); -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + NSCAP_ASSERT_NO_QUERY_NEEDED(); return *this; } -#endif nsCOMPtr& operator=( const nsQueryInterface& rhs ) @@ -480,9 +470,8 @@ class nsCOMPtr : private nsCOMPtr_base if ( mRawPtr ) NSCAP_RELEASE(mRawPtr); mRawPtr = rhs.mRawPtr; -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + + NSCAP_ASSERT_NO_QUERY_NEEDED(); return *this; } @@ -490,9 +479,7 @@ class nsCOMPtr : private nsCOMPtr_base operator=( const nsDontQueryInterface& rhs ) { assign_with_AddRef(rhs.mRawPtr); -#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES - Assert_NoQueryNeeded(); -#endif + NSCAP_ASSERT_NO_QUERY_NEEDED(); return *this; } @@ -560,6 +547,49 @@ class nsCOMPtr : private nsCOMPtr_base } }; +#ifdef NSCAP_FEATURE_DEBUG_PTR_TYPES +template +void +nsCOMPtr::assign_with_AddRef( nsISupports* rawPtr ) + { + if ( rawPtr ) + NSCAP_ADDREF(rawPtr); + if ( mRawPtr ) + NSCAP_RELEASE(mRawPtr); + mRawPtr = NS_REINTERPRET_CAST(T*, rawPtr); + } + +template +void +nsCOMPtr::assign_with_QueryInterface( nsISupports* rawPtr, const nsIID& iid, nsresult* result ) + { + nsresult status = NS_ERROR_NULL_POINTER; + if ( !rawPtr || !NS_SUCCEEDED( status = rawPtr->QueryInterface(iid, NSCAP_REINTERPRET_CAST(void**, &rawPtr)) ) ) + rawPtr = 0; + + if ( mRawPtr ) + NSCAP_RELEASE(mRawPtr); + + mRawPtr = NS_REINTERPRET_CAST(T*, rawPtr); + + if ( result ) + *result = status; + } + +template +void** +nsCOMPtr::begin_assignment() + { + if ( mRawPtr ) + { + NSCAP_RELEASE(mRawPtr); + mRawPtr = 0; + } + + return NSCAP_REINTERPRET_CAST(void**, &mRawPtr); + } +#endif + template class nsGetterAddRefs @@ -577,6 +607,8 @@ class nsGetterAddRefs When initialized with a |nsCOMPtr|, as in the example above, it returns a |void**| (or |T**| if needed) that the outer call (|QueryInterface| in this case) can fill in. + + This type should be a nested class inside |nsCOMPtr|. */ { public: @@ -620,8 +652,6 @@ getter_AddRefs( nsCOMPtr& aSmartPtr ) } -#ifdef NSCAP_FEATURE_ALLOW_COMPARISONS - class NSCAP_Zero; template @@ -715,8 +745,6 @@ SameCOMIdentity( nsISupports* lhs, nsISupports* rhs ) return nsCOMPtr( do_QueryInterface(lhs) ) == nsCOMPtr( do_QueryInterface(rhs) ); } -#endif // defined(NSCAP_FEATURE_ALLOW_COMPARISONS) - template inline