updated to new interface for nsCOMPtr

This commit is contained in:
scc%netscape.com 1999-02-17 01:58:25 +00:00
parent 149e9ed6e5
commit 42e1c10096
6 changed files with 612 additions and 1014 deletions

View File

@ -34,12 +34,14 @@
/*
TO DO...
+ Factor out some base behavior to reduce possible bloating
+ Find an alternative to the current illegal and non-functioning comparison operators
TO DO...
+ make alternative function for |getter_AddRefs| (or something)
+ make constructor for |nsQueryInterface| explicit (suddenly construct/assign from raw pointer becomes illegal)
+ Improve internal documentation
+ mention *&
+ alternatives for comparison
+ do_QueryInterface
*/
@ -152,7 +154,7 @@
Don't worry. It's a compile-time error if you forget to wrap it.
Compare the raw-pointer way...
Compare the raw-pointer way...
IFoo* foo = 0;
nsresult status = CreateIFoo(&foo);
@ -174,17 +176,17 @@
To the smart-pointer way...
To the smart-pointer way...
nsCOMPtr<IFoo> fooP;
nsresult status = CreateIFoo( getter_AddRefs(fooP) );
if ( NS_SUCCEEDED(status) )
if ( nsCOMPtr<IBar> barP( fooP ) )
{
nsCOMPtr<IFooBar> fooBarP;
if ( NS_SUCCEEDED(status = CreateIFooBar(fooP, barP, getter_AddRefs(fooBarP))) )
fooBarP->DoTheReallyHardThing();
}
nsCOMPtr<IFoo> fooP;
nsresult status = CreateIFoo( getter_AddRefs(fooP) );
if ( NS_SUCCEEDED(status) )
if ( nsCOMPtr<IBar> barP( fooP ) )
{
nsCOMPtr<IFooBar> fooBarP;
if ( NS_SUCCEEDED(status = CreateIFooBar(fooP, barP, getter_AddRefs(fooBarP))) )
fooBarP->DoTheReallyHardThing();
}
Is there an easy way to convert my current code?
@ -284,26 +286,25 @@
#endif
#ifdef NSCAP_FEATURE_DEBUG_MACROS
#define NSCAP_ADDREF(ptr) NS_ADDREF(ptr)
#define NSCAP_RELEASE(ptr) NS_RELEASE(ptr)
#define NSCAP_ADDREF(ptr) NS_ADDREF(ptr)
#define NSCAP_RELEASE(ptr) NS_RELEASE(ptr)
#else
#define NSCAP_ADDREF(ptr) (ptr)->AddRef()
#define NSCAP_RELEASE(ptr) (ptr)->Release()
#define NSCAP_ADDREF(ptr) (ptr)->AddRef()
#define NSCAP_RELEASE(ptr) (ptr)->Release()
#endif
/*
WARNING:
VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
in an order that satisfies:
nsDerivedSafe < nsCOMPtr
nsDontAddRef < nsCOMPtr
nsCOMPtr < nsGetterAddRefs
nsCOMPtr < nsGetterDoesntAddRef
/*
WARNING:
VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
in an order that satisfies:
nsDerivedSafe < nsCOMPtr
nsDontAddRef < nsCOMPtr
nsCOMPtr < nsGetterAddRefs
The other compilers probably won't complain, so please don't reorder these
classes, on pain of breaking 4.2 compatibility.
*/
The other compilers probably won't complain, so please don't reorder these
classes, on pain of breaking 4.2 compatibility.
*/
template <class T>
@ -325,11 +326,11 @@ class nsDerivedSafe : public T
nsrefcnt Release();
#endif
void operator delete( void* ); // NOT TO BE IMPLEMENTED
// declaring |operator delete| private makes calling delete on an interface pointer a compile error
void operator delete( void* ); // 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
// you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
nsDerivedSafe& operator=( const nsDerivedSafe& ); // NOT TO BE IMPLEMENTED
// you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
};
#if defined(NSCAP_NO_MEMBER_USING_DECLARATIONS) && defined(NSCAP_NEED_UNUSED_VIRTUAL_IMPLEMENTATIONS)
@ -352,6 +353,57 @@ nsDerivedSafe<T>::Release()
template <class T>
struct nsDontQueryInterface
/*
...
*/
{
explicit
nsDontQueryInterface( T* aRawPtr )
: mRawPtr(aRawPtr)
{
// nothing else to do here
}
T* mRawPtr;
};
template <class T>
inline
nsDontQueryInterface<T>
dont_QueryInterface( T* aRawPtr )
{
return nsDontQueryInterface<T>(aRawPtr);
}
struct nsQueryInterface
{
// explicit
nsQueryInterface( nsISupports* aRawPtr, nsresult* error = 0 )
: mRawPtr(aRawPtr),
mErrorPtr(error)
{
// nothing else to do here
}
nsISupports* mRawPtr;
nsresult* mErrorPtr;
};
inline
nsQueryInterface
do_QueryInterface( nsISupports* aRawPtr, nsresult* error = 0 )
{
return nsQueryInterface(aRawPtr, error);
}
template <class T>
struct nsDontAddRef
/*
@ -390,36 +442,35 @@ dont_AddRef( T* aRawPtr )
class nsCOMPtr_base
{
public:
template <class T>
struct nsDontQueryInterface
/*
...
*/
{
explicit
nsDontQueryInterface( T* aRawPtr )
: mRawPtr(aRawPtr)
{
// nothing else to do here
}
nsCOMPtr_base( nsISupports* rawPtr = 0 )
: mRawPtr(rawPtr)
{
// nothing else to do here
}
T* mRawPtr;
};
~nsCOMPtr_base()
{
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
}
template <class T>
inline
nsDontQueryInterface<T>
dont_QueryInterface( T* aRawPtr )
{
return nsDontQueryInterface<T>(aRawPtr);
}
NS_EXPORT void assign_with_AddRef( nsISupports* );
NS_EXPORT void assign_with_QueryInterface( nsISupports*, const nsIID&, nsresult* );
NS_EXPORT void** begin_assignment();
protected:
nsISupports* mRawPtr;
};
template <class T>
class nsCOMPtr
class nsCOMPtr : private nsCOMPtr_base
/*
...
*/
@ -427,144 +478,74 @@ class nsCOMPtr
public:
typedef T element_type;
/*
Note: the following constructor is only |explicit| because of a bug in egcs 1.0.
This bug prevents egcs from compiling statements like
nsCOMPtr<Y> y;
// ...
nsCOMPtr<X> x = y;
Using the parenthesis form of the constructor works fine. In an effort to
help other people not break the linux build, I am making this constructor
|explicit|. That prevents _any_ platform (that supports |explicit|) from compiling
the thing that egcs can't compile.
When egcs fixes this bug, and we have reasonable agreement that interested parties
have or will upgrade, the |explicit| will go away.
*/
explicit
nsCOMPtr( nsISupports* aRawPtr = 0 )
/*
...it's unfortunate, but negligable, that this does a |QueryInterface| even
when constructed from a |T*| but we can't tell the difference between a |T*|
and a pointer to some object derived from |class T|.
*/
{
nsresult status = NS_OK;
if ( !aRawPtr || !NS_SUCCEEDED( status = aRawPtr->QueryInterface(T::IID(), NSCAP_REINTERPRET_CAST(void**, &mRawPtr)) ) )
mRawPtr = 0; // ...in case they wrote |QueryInterface| wrong, and it returns an error _and_ a pointer
// ...and |QueryInterface| does the |AddRef| for us (if it returned a pointer)
mImplicitQueryInterfaceResult = status;
}
nsCOMPtr( const nsDontAddRef<T>& aSmartPtr )
: mRawPtr(aSmartPtr.mRawPtr),
mImplicitQueryInterfaceResult(NS_OK)
nsCOMPtr()
// : nsCOMPtr_base(0)
{
// nothing else to do here
}
nsCOMPtr( const nsDontQueryInterface<T>& aSmartPtr )
: mRawPtr(aSmartPtr.mRawPtr),
mImplicitQueryInterfaceResult(NS_OK)
{
if ( mRawPtr )
{
NSCAP_ADDREF(mRawPtr);
}
}
nsCOMPtr( const nsQueryInterface& aSmartPtr )
// : nsCOMPtr_base(0)
{
assign_with_QueryInterface(aSmartPtr.mRawPtr, T::IID(), aSmartPtr.mErrorPtr);
}
nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
: mRawPtr(aSmartPtr.mRawPtr),
mImplicitQueryInterfaceResult(NS_OK)
nsCOMPtr( const nsDontAddRef<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
// nothing else to do here
}
nsCOMPtr( const nsDontQueryInterface<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
if ( mRawPtr )
{
NSCAP_ADDREF(mRawPtr);
}
NSCAP_ADDREF(mRawPtr);
}
~nsCOMPtr()
nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
if ( mRawPtr )
NSCAP_ADDREF(mRawPtr);
}
nsCOMPtr&
operator=( nsISupports* rhs )
{
T* rawPtr;
nsresult status = NS_OK;
if ( !rhs || !NS_SUCCEEDED( status = rhs->QueryInterface(T::IID(), NSCAP_REINTERPRET_CAST(void**, &rawPtr)) ) )
rawPtr = 0;
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mRawPtr = rawPtr;
mImplicitQueryInterfaceResult = status;
return *this;
}
nsCOMPtr&
operator=( const nsDontAddRef<T>& rhs )
nsCOMPtr<T>&
operator=( const nsQueryInterface& rhs )
{
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mRawPtr = rhs.mRawPtr;
mImplicitQueryInterfaceResult = NS_OK;
assign_with_QueryInterface(rhs.mRawPtr, T::IID(), rhs.mErrorPtr);
return *this;
}
nsCOMPtr&
operator=( const nsDontQueryInterface<T>& rhs )
{
T* rawPtr = rhs.mRawPtr;
nsCOMPtr<T>&
operator=( const nsDontAddRef<T>& rhs )
{
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
mRawPtr = rhs.mRawPtr;
return *this;
}
if ( rawPtr )
{
NSCAP_ADDREF(rawPtr);
}
nsCOMPtr<T>&
operator=( const nsDontQueryInterface<T>& rhs )
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
nsCOMPtr<T>&
operator=( const nsCOMPtr& rhs )
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
mRawPtr = rawPtr;
mImplicitQueryInterfaceResult = NS_OK;
return *this;
}
nsCOMPtr&
operator=( const nsCOMPtr& rhs )
{
T* rawPtr = rhs.mRawPtr;
if ( rawPtr )
{
NSCAP_ADDREF(rawPtr);
}
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mRawPtr = rawPtr;
mImplicitQueryInterfaceResult = NS_OK;
return *this;
}
nsDerivedSafe<T>*
get() const
// returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|
{
return NSCAP_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
}
nsDerivedSafe<T>*
operator->() const
@ -587,110 +568,29 @@ class nsCOMPtr
return get();
}
nsDerivedSafe<T>*
get() const
// returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|
{
return NSCAP_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
}
nsresult
assignment_error() const
{
return mRawPtr ? NS_OK : mImplicitQueryInterfaceResult;
}
#if 0
private:
friend class nsGetterAddRefs<T>;
friend class nsGetterDoesntAddRef<T>;
/*
In a perfect world, the following two member functions, |StartAssignment| and
|FinishAssignment|, would be private. They are and should be only accessed by
the closely related classes |nsGetterAddRefs<T>| and |nsGetterDoesntAddRef<T>|.
In a perfect world, the following member function, |StartAssignment|, would be private.
It is and should be only accessed by the closely related class |nsGetterAddRefs<T>|.
Unfortunately, some compilers---most notably VC++5.0---fail to grok the
friend declarations above or in any alternate acceptable form. So, physically
they will be public (until our compilers get smarter); but they are not to be
friend declaration above or in any alternate acceptable form. So, physically
it will be public (until our compilers get smarter); but it is not to be
considered part of the logical public interface.
*/
#endif
T**
StartAssignment( NSCAP_BOOL awaiting_AddRef )
StartAssignment()
{
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mIsAwaitingAddRef = awaiting_AddRef;
mRawPtr = 0;
return &mRawPtr;
return NSCAP_REINTERPRET_CAST(T**, begin_assignment());
}
void
FinishAssignment()
{
if ( mRawPtr && mIsAwaitingAddRef )
{
NSCAP_ADDREF(mRawPtr);
}
mImplicitQueryInterfaceResult = NS_OK;
}
private:
T* mRawPtr;
union
{
NSCAP_BOOL mIsAwaitingAddRef;
nsresult mImplicitQueryInterfaceResult;
};
};
/*
The following functions make comparing |nsCOMPtr|s and raw pointers
more convenient.
*/
template <class T>
inline
NSCAP_BOOL
operator==( const nsCOMPtr<T>& lhs, const T*const rhs )
{
return lhs.get() == rhs;
}
template <class T>
inline
NSCAP_BOOL
operator!=( const nsCOMPtr<T>& lhs, const T*const rhs )
{
return lhs.get() != rhs;
}
template <class T>
inline
NSCAP_BOOL
operator==( const T*const lhs, const nsCOMPtr<T>& rhs )
{
return lhs == rhs.get();
}
template <class T>
inline
NSCAP_BOOL
operator!=( const T*const lhs, const nsCOMPtr<T>& rhs )
{
return lhs != rhs.get();
}
template <class T>
class nsGetterAddRefs
/*
@ -715,32 +615,32 @@ class nsGetterAddRefs
public:
explicit
nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
: mTargetSmartPtr(&aSmartPtr)
: mTargetSmartPtr(aSmartPtr)
{
// nothing else to do
}
operator void**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr->StartAssignment(0));
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
}
T*&
operator*()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return *(mTargetSmartPtr->StartAssignment(0));
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return *(mTargetSmartPtr.StartAssignment());
}
operator T**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return mTargetSmartPtr->StartAssignment(0);
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return mTargetSmartPtr.StartAssignment();
}
private:
nsCOMPtr<T>* mTargetSmartPtr;
nsCOMPtr<T>& mTargetSmartPtr;
};
template <class T>
@ -758,65 +658,4 @@ getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
template <class T>
class nsGetterDoesntAddRef
/*
...
*/
{
public:
explicit
nsGetterDoesntAddRef( nsCOMPtr<T>& aSmartPtr )
: mTargetSmartPtr(&aSmartPtr)
{
// nothing else to do
}
nsGetterDoesntAddRef( nsGetterDoesntAddRef<T>& F )
: mTargetSmartPtr(F.mTargetSmartPtr)
{
F.mTargetSmartPtr = 0;
}
~nsGetterDoesntAddRef()
{
if ( mTargetSmartPtr )
mTargetSmartPtr->FinishAssignment();
}
operator void**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_doesnt_AddRef into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr->StartAssignment(1));
}
T*&
operator*()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_doesnt_AddRef into no destination");
return *(mTargetSmartPtr->StartAssignment(1));
}
operator T**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_doesnt_AddRef into no destination");
return mTargetSmartPtr->StartAssignment(1);
}
private:
nsGetterDoesntAddRef<T> operator=( const nsGetterDoesntAddRef<T>& ); // not to be implemented
private:
nsCOMPtr<T>* mTargetSmartPtr;
};
template <class T>
inline
nsGetterDoesntAddRef<T>
getter_doesnt_AddRef( nsCOMPtr<T>& aSmartPtr )
{
return nsGetterDoesntAddRef<T>(aSmartPtr);
}
#endif // !defined(nsCOMPtr_h___)

View File

@ -34,12 +34,14 @@
/*
TO DO...
+ Factor out some base behavior to reduce possible bloating
+ Find an alternative to the current illegal and non-functioning comparison operators
TO DO...
+ make alternative function for |getter_AddRefs| (or something)
+ make constructor for |nsQueryInterface| explicit (suddenly construct/assign from raw pointer becomes illegal)
+ Improve internal documentation
+ mention *&
+ alternatives for comparison
+ do_QueryInterface
*/
@ -152,7 +154,7 @@
Don't worry. It's a compile-time error if you forget to wrap it.
Compare the raw-pointer way...
Compare the raw-pointer way...
IFoo* foo = 0;
nsresult status = CreateIFoo(&foo);
@ -174,17 +176,17 @@
To the smart-pointer way...
To the smart-pointer way...
nsCOMPtr<IFoo> fooP;
nsresult status = CreateIFoo( getter_AddRefs(fooP) );
if ( NS_SUCCEEDED(status) )
if ( nsCOMPtr<IBar> barP( fooP ) )
{
nsCOMPtr<IFooBar> fooBarP;
if ( NS_SUCCEEDED(status = CreateIFooBar(fooP, barP, getter_AddRefs(fooBarP))) )
fooBarP->DoTheReallyHardThing();
}
nsCOMPtr<IFoo> fooP;
nsresult status = CreateIFoo( getter_AddRefs(fooP) );
if ( NS_SUCCEEDED(status) )
if ( nsCOMPtr<IBar> barP( fooP ) )
{
nsCOMPtr<IFooBar> fooBarP;
if ( NS_SUCCEEDED(status = CreateIFooBar(fooP, barP, getter_AddRefs(fooBarP))) )
fooBarP->DoTheReallyHardThing();
}
Is there an easy way to convert my current code?
@ -284,26 +286,25 @@
#endif
#ifdef NSCAP_FEATURE_DEBUG_MACROS
#define NSCAP_ADDREF(ptr) NS_ADDREF(ptr)
#define NSCAP_RELEASE(ptr) NS_RELEASE(ptr)
#define NSCAP_ADDREF(ptr) NS_ADDREF(ptr)
#define NSCAP_RELEASE(ptr) NS_RELEASE(ptr)
#else
#define NSCAP_ADDREF(ptr) (ptr)->AddRef()
#define NSCAP_RELEASE(ptr) (ptr)->Release()
#define NSCAP_ADDREF(ptr) (ptr)->AddRef()
#define NSCAP_RELEASE(ptr) (ptr)->Release()
#endif
/*
WARNING:
VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
in an order that satisfies:
nsDerivedSafe < nsCOMPtr
nsDontAddRef < nsCOMPtr
nsCOMPtr < nsGetterAddRefs
nsCOMPtr < nsGetterDoesntAddRef
/*
WARNING:
VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
in an order that satisfies:
nsDerivedSafe < nsCOMPtr
nsDontAddRef < nsCOMPtr
nsCOMPtr < nsGetterAddRefs
The other compilers probably won't complain, so please don't reorder these
classes, on pain of breaking 4.2 compatibility.
*/
The other compilers probably won't complain, so please don't reorder these
classes, on pain of breaking 4.2 compatibility.
*/
template <class T>
@ -325,11 +326,11 @@ class nsDerivedSafe : public T
nsrefcnt Release();
#endif
void operator delete( void* ); // NOT TO BE IMPLEMENTED
// declaring |operator delete| private makes calling delete on an interface pointer a compile error
void operator delete( void* ); // 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
// you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
nsDerivedSafe& operator=( const nsDerivedSafe& ); // NOT TO BE IMPLEMENTED
// you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
};
#if defined(NSCAP_NO_MEMBER_USING_DECLARATIONS) && defined(NSCAP_NEED_UNUSED_VIRTUAL_IMPLEMENTATIONS)
@ -352,6 +353,57 @@ nsDerivedSafe<T>::Release()
template <class T>
struct nsDontQueryInterface
/*
...
*/
{
explicit
nsDontQueryInterface( T* aRawPtr )
: mRawPtr(aRawPtr)
{
// nothing else to do here
}
T* mRawPtr;
};
template <class T>
inline
nsDontQueryInterface<T>
dont_QueryInterface( T* aRawPtr )
{
return nsDontQueryInterface<T>(aRawPtr);
}
struct nsQueryInterface
{
// explicit
nsQueryInterface( nsISupports* aRawPtr, nsresult* error = 0 )
: mRawPtr(aRawPtr),
mErrorPtr(error)
{
// nothing else to do here
}
nsISupports* mRawPtr;
nsresult* mErrorPtr;
};
inline
nsQueryInterface
do_QueryInterface( nsISupports* aRawPtr, nsresult* error = 0 )
{
return nsQueryInterface(aRawPtr, error);
}
template <class T>
struct nsDontAddRef
/*
@ -390,36 +442,35 @@ dont_AddRef( T* aRawPtr )
class nsCOMPtr_base
{
public:
template <class T>
struct nsDontQueryInterface
/*
...
*/
{
explicit
nsDontQueryInterface( T* aRawPtr )
: mRawPtr(aRawPtr)
{
// nothing else to do here
}
nsCOMPtr_base( nsISupports* rawPtr = 0 )
: mRawPtr(rawPtr)
{
// nothing else to do here
}
T* mRawPtr;
};
~nsCOMPtr_base()
{
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
}
template <class T>
inline
nsDontQueryInterface<T>
dont_QueryInterface( T* aRawPtr )
{
return nsDontQueryInterface<T>(aRawPtr);
}
NS_EXPORT void assign_with_AddRef( nsISupports* );
NS_EXPORT void assign_with_QueryInterface( nsISupports*, const nsIID&, nsresult* );
NS_EXPORT void** begin_assignment();
protected:
nsISupports* mRawPtr;
};
template <class T>
class nsCOMPtr
class nsCOMPtr : private nsCOMPtr_base
/*
...
*/
@ -427,144 +478,74 @@ class nsCOMPtr
public:
typedef T element_type;
/*
Note: the following constructor is only |explicit| because of a bug in egcs 1.0.
This bug prevents egcs from compiling statements like
nsCOMPtr<Y> y;
// ...
nsCOMPtr<X> x = y;
Using the parenthesis form of the constructor works fine. In an effort to
help other people not break the linux build, I am making this constructor
|explicit|. That prevents _any_ platform (that supports |explicit|) from compiling
the thing that egcs can't compile.
When egcs fixes this bug, and we have reasonable agreement that interested parties
have or will upgrade, the |explicit| will go away.
*/
explicit
nsCOMPtr( nsISupports* aRawPtr = 0 )
/*
...it's unfortunate, but negligable, that this does a |QueryInterface| even
when constructed from a |T*| but we can't tell the difference between a |T*|
and a pointer to some object derived from |class T|.
*/
{
nsresult status = NS_OK;
if ( !aRawPtr || !NS_SUCCEEDED( status = aRawPtr->QueryInterface(T::IID(), NSCAP_REINTERPRET_CAST(void**, &mRawPtr)) ) )
mRawPtr = 0; // ...in case they wrote |QueryInterface| wrong, and it returns an error _and_ a pointer
// ...and |QueryInterface| does the |AddRef| for us (if it returned a pointer)
mImplicitQueryInterfaceResult = status;
}
nsCOMPtr( const nsDontAddRef<T>& aSmartPtr )
: mRawPtr(aSmartPtr.mRawPtr),
mImplicitQueryInterfaceResult(NS_OK)
nsCOMPtr()
// : nsCOMPtr_base(0)
{
// nothing else to do here
}
nsCOMPtr( const nsDontQueryInterface<T>& aSmartPtr )
: mRawPtr(aSmartPtr.mRawPtr),
mImplicitQueryInterfaceResult(NS_OK)
{
if ( mRawPtr )
{
NSCAP_ADDREF(mRawPtr);
}
}
nsCOMPtr( const nsQueryInterface& aSmartPtr )
// : nsCOMPtr_base(0)
{
assign_with_QueryInterface(aSmartPtr.mRawPtr, T::IID(), aSmartPtr.mErrorPtr);
}
nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
: mRawPtr(aSmartPtr.mRawPtr),
mImplicitQueryInterfaceResult(NS_OK)
nsCOMPtr( const nsDontAddRef<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
// nothing else to do here
}
nsCOMPtr( const nsDontQueryInterface<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
if ( mRawPtr )
{
NSCAP_ADDREF(mRawPtr);
}
NSCAP_ADDREF(mRawPtr);
}
~nsCOMPtr()
nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
if ( mRawPtr )
NSCAP_ADDREF(mRawPtr);
}
nsCOMPtr&
operator=( nsISupports* rhs )
{
T* rawPtr;
nsresult status = NS_OK;
if ( !rhs || !NS_SUCCEEDED( status = rhs->QueryInterface(T::IID(), NSCAP_REINTERPRET_CAST(void**, &rawPtr)) ) )
rawPtr = 0;
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mRawPtr = rawPtr;
mImplicitQueryInterfaceResult = status;
return *this;
}
nsCOMPtr&
operator=( const nsDontAddRef<T>& rhs )
nsCOMPtr<T>&
operator=( const nsQueryInterface& rhs )
{
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mRawPtr = rhs.mRawPtr;
mImplicitQueryInterfaceResult = NS_OK;
assign_with_QueryInterface(rhs.mRawPtr, T::IID(), rhs.mErrorPtr);
return *this;
}
nsCOMPtr&
operator=( const nsDontQueryInterface<T>& rhs )
{
T* rawPtr = rhs.mRawPtr;
nsCOMPtr<T>&
operator=( const nsDontAddRef<T>& rhs )
{
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
mRawPtr = rhs.mRawPtr;
return *this;
}
if ( rawPtr )
{
NSCAP_ADDREF(rawPtr);
}
nsCOMPtr<T>&
operator=( const nsDontQueryInterface<T>& rhs )
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
nsCOMPtr<T>&
operator=( const nsCOMPtr& rhs )
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
mRawPtr = rawPtr;
mImplicitQueryInterfaceResult = NS_OK;
return *this;
}
nsCOMPtr&
operator=( const nsCOMPtr& rhs )
{
T* rawPtr = rhs.mRawPtr;
if ( rawPtr )
{
NSCAP_ADDREF(rawPtr);
}
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mRawPtr = rawPtr;
mImplicitQueryInterfaceResult = NS_OK;
return *this;
}
nsDerivedSafe<T>*
get() const
// returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|
{
return NSCAP_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
}
nsDerivedSafe<T>*
operator->() const
@ -587,110 +568,29 @@ class nsCOMPtr
return get();
}
nsDerivedSafe<T>*
get() const
// returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|
{
return NSCAP_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
}
nsresult
assignment_error() const
{
return mRawPtr ? NS_OK : mImplicitQueryInterfaceResult;
}
#if 0
private:
friend class nsGetterAddRefs<T>;
friend class nsGetterDoesntAddRef<T>;
/*
In a perfect world, the following two member functions, |StartAssignment| and
|FinishAssignment|, would be private. They are and should be only accessed by
the closely related classes |nsGetterAddRefs<T>| and |nsGetterDoesntAddRef<T>|.
In a perfect world, the following member function, |StartAssignment|, would be private.
It is and should be only accessed by the closely related class |nsGetterAddRefs<T>|.
Unfortunately, some compilers---most notably VC++5.0---fail to grok the
friend declarations above or in any alternate acceptable form. So, physically
they will be public (until our compilers get smarter); but they are not to be
friend declaration above or in any alternate acceptable form. So, physically
it will be public (until our compilers get smarter); but it is not to be
considered part of the logical public interface.
*/
#endif
T**
StartAssignment( NSCAP_BOOL awaiting_AddRef )
StartAssignment()
{
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mIsAwaitingAddRef = awaiting_AddRef;
mRawPtr = 0;
return &mRawPtr;
return NSCAP_REINTERPRET_CAST(T**, begin_assignment());
}
void
FinishAssignment()
{
if ( mRawPtr && mIsAwaitingAddRef )
{
NSCAP_ADDREF(mRawPtr);
}
mImplicitQueryInterfaceResult = NS_OK;
}
private:
T* mRawPtr;
union
{
NSCAP_BOOL mIsAwaitingAddRef;
nsresult mImplicitQueryInterfaceResult;
};
};
/*
The following functions make comparing |nsCOMPtr|s and raw pointers
more convenient.
*/
template <class T>
inline
NSCAP_BOOL
operator==( const nsCOMPtr<T>& lhs, const T*const rhs )
{
return lhs.get() == rhs;
}
template <class T>
inline
NSCAP_BOOL
operator!=( const nsCOMPtr<T>& lhs, const T*const rhs )
{
return lhs.get() != rhs;
}
template <class T>
inline
NSCAP_BOOL
operator==( const T*const lhs, const nsCOMPtr<T>& rhs )
{
return lhs == rhs.get();
}
template <class T>
inline
NSCAP_BOOL
operator!=( const T*const lhs, const nsCOMPtr<T>& rhs )
{
return lhs != rhs.get();
}
template <class T>
class nsGetterAddRefs
/*
@ -715,32 +615,32 @@ class nsGetterAddRefs
public:
explicit
nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
: mTargetSmartPtr(&aSmartPtr)
: mTargetSmartPtr(aSmartPtr)
{
// nothing else to do
}
operator void**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr->StartAssignment(0));
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
}
T*&
operator*()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return *(mTargetSmartPtr->StartAssignment(0));
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return *(mTargetSmartPtr.StartAssignment());
}
operator T**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return mTargetSmartPtr->StartAssignment(0);
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return mTargetSmartPtr.StartAssignment();
}
private:
nsCOMPtr<T>* mTargetSmartPtr;
nsCOMPtr<T>& mTargetSmartPtr;
};
template <class T>
@ -758,65 +658,4 @@ getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
template <class T>
class nsGetterDoesntAddRef
/*
...
*/
{
public:
explicit
nsGetterDoesntAddRef( nsCOMPtr<T>& aSmartPtr )
: mTargetSmartPtr(&aSmartPtr)
{
// nothing else to do
}
nsGetterDoesntAddRef( nsGetterDoesntAddRef<T>& F )
: mTargetSmartPtr(F.mTargetSmartPtr)
{
F.mTargetSmartPtr = 0;
}
~nsGetterDoesntAddRef()
{
if ( mTargetSmartPtr )
mTargetSmartPtr->FinishAssignment();
}
operator void**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_doesnt_AddRef into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr->StartAssignment(1));
}
T*&
operator*()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_doesnt_AddRef into no destination");
return *(mTargetSmartPtr->StartAssignment(1));
}
operator T**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_doesnt_AddRef into no destination");
return mTargetSmartPtr->StartAssignment(1);
}
private:
nsGetterDoesntAddRef<T> operator=( const nsGetterDoesntAddRef<T>& ); // not to be implemented
private:
nsCOMPtr<T>* mTargetSmartPtr;
};
template <class T>
inline
nsGetterDoesntAddRef<T>
getter_doesnt_AddRef( nsCOMPtr<T>& aSmartPtr )
{
return nsGetterDoesntAddRef<T>(aSmartPtr);
}
#endif // !defined(nsCOMPtr_h___)

Binary file not shown.

View File

@ -34,12 +34,14 @@
/*
TO DO...
+ Factor out some base behavior to reduce possible bloating
+ Find an alternative to the current illegal and non-functioning comparison operators
TO DO...
+ make alternative function for |getter_AddRefs| (or something)
+ make constructor for |nsQueryInterface| explicit (suddenly construct/assign from raw pointer becomes illegal)
+ Improve internal documentation
+ mention *&
+ alternatives for comparison
+ do_QueryInterface
*/
@ -152,7 +154,7 @@
Don't worry. It's a compile-time error if you forget to wrap it.
Compare the raw-pointer way...
Compare the raw-pointer way...
IFoo* foo = 0;
nsresult status = CreateIFoo(&foo);
@ -174,17 +176,17 @@
To the smart-pointer way...
To the smart-pointer way...
nsCOMPtr<IFoo> fooP;
nsresult status = CreateIFoo( getter_AddRefs(fooP) );
if ( NS_SUCCEEDED(status) )
if ( nsCOMPtr<IBar> barP( fooP ) )
{
nsCOMPtr<IFooBar> fooBarP;
if ( NS_SUCCEEDED(status = CreateIFooBar(fooP, barP, getter_AddRefs(fooBarP))) )
fooBarP->DoTheReallyHardThing();
}
nsCOMPtr<IFoo> fooP;
nsresult status = CreateIFoo( getter_AddRefs(fooP) );
if ( NS_SUCCEEDED(status) )
if ( nsCOMPtr<IBar> barP( fooP ) )
{
nsCOMPtr<IFooBar> fooBarP;
if ( NS_SUCCEEDED(status = CreateIFooBar(fooP, barP, getter_AddRefs(fooBarP))) )
fooBarP->DoTheReallyHardThing();
}
Is there an easy way to convert my current code?
@ -284,26 +286,25 @@
#endif
#ifdef NSCAP_FEATURE_DEBUG_MACROS
#define NSCAP_ADDREF(ptr) NS_ADDREF(ptr)
#define NSCAP_RELEASE(ptr) NS_RELEASE(ptr)
#define NSCAP_ADDREF(ptr) NS_ADDREF(ptr)
#define NSCAP_RELEASE(ptr) NS_RELEASE(ptr)
#else
#define NSCAP_ADDREF(ptr) (ptr)->AddRef()
#define NSCAP_RELEASE(ptr) (ptr)->Release()
#define NSCAP_ADDREF(ptr) (ptr)->AddRef()
#define NSCAP_RELEASE(ptr) (ptr)->Release()
#endif
/*
WARNING:
VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
in an order that satisfies:
nsDerivedSafe < nsCOMPtr
nsDontAddRef < nsCOMPtr
nsCOMPtr < nsGetterAddRefs
nsCOMPtr < nsGetterDoesntAddRef
/*
WARNING:
VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
in an order that satisfies:
nsDerivedSafe < nsCOMPtr
nsDontAddRef < nsCOMPtr
nsCOMPtr < nsGetterAddRefs
The other compilers probably won't complain, so please don't reorder these
classes, on pain of breaking 4.2 compatibility.
*/
The other compilers probably won't complain, so please don't reorder these
classes, on pain of breaking 4.2 compatibility.
*/
template <class T>
@ -325,11 +326,11 @@ class nsDerivedSafe : public T
nsrefcnt Release();
#endif
void operator delete( void* ); // NOT TO BE IMPLEMENTED
// declaring |operator delete| private makes calling delete on an interface pointer a compile error
void operator delete( void* ); // 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
// you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
nsDerivedSafe& operator=( const nsDerivedSafe& ); // NOT TO BE IMPLEMENTED
// you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
};
#if defined(NSCAP_NO_MEMBER_USING_DECLARATIONS) && defined(NSCAP_NEED_UNUSED_VIRTUAL_IMPLEMENTATIONS)
@ -352,6 +353,57 @@ nsDerivedSafe<T>::Release()
template <class T>
struct nsDontQueryInterface
/*
...
*/
{
explicit
nsDontQueryInterface( T* aRawPtr )
: mRawPtr(aRawPtr)
{
// nothing else to do here
}
T* mRawPtr;
};
template <class T>
inline
nsDontQueryInterface<T>
dont_QueryInterface( T* aRawPtr )
{
return nsDontQueryInterface<T>(aRawPtr);
}
struct nsQueryInterface
{
// explicit
nsQueryInterface( nsISupports* aRawPtr, nsresult* error = 0 )
: mRawPtr(aRawPtr),
mErrorPtr(error)
{
// nothing else to do here
}
nsISupports* mRawPtr;
nsresult* mErrorPtr;
};
inline
nsQueryInterface
do_QueryInterface( nsISupports* aRawPtr, nsresult* error = 0 )
{
return nsQueryInterface(aRawPtr, error);
}
template <class T>
struct nsDontAddRef
/*
@ -390,36 +442,35 @@ dont_AddRef( T* aRawPtr )
class nsCOMPtr_base
{
public:
template <class T>
struct nsDontQueryInterface
/*
...
*/
{
explicit
nsDontQueryInterface( T* aRawPtr )
: mRawPtr(aRawPtr)
{
// nothing else to do here
}
nsCOMPtr_base( nsISupports* rawPtr = 0 )
: mRawPtr(rawPtr)
{
// nothing else to do here
}
T* mRawPtr;
};
~nsCOMPtr_base()
{
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
}
template <class T>
inline
nsDontQueryInterface<T>
dont_QueryInterface( T* aRawPtr )
{
return nsDontQueryInterface<T>(aRawPtr);
}
NS_EXPORT void assign_with_AddRef( nsISupports* );
NS_EXPORT void assign_with_QueryInterface( nsISupports*, const nsIID&, nsresult* );
NS_EXPORT void** begin_assignment();
protected:
nsISupports* mRawPtr;
};
template <class T>
class nsCOMPtr
class nsCOMPtr : private nsCOMPtr_base
/*
...
*/
@ -427,144 +478,74 @@ class nsCOMPtr
public:
typedef T element_type;
/*
Note: the following constructor is only |explicit| because of a bug in egcs 1.0.
This bug prevents egcs from compiling statements like
nsCOMPtr<Y> y;
// ...
nsCOMPtr<X> x = y;
Using the parenthesis form of the constructor works fine. In an effort to
help other people not break the linux build, I am making this constructor
|explicit|. That prevents _any_ platform (that supports |explicit|) from compiling
the thing that egcs can't compile.
When egcs fixes this bug, and we have reasonable agreement that interested parties
have or will upgrade, the |explicit| will go away.
*/
explicit
nsCOMPtr( nsISupports* aRawPtr = 0 )
/*
...it's unfortunate, but negligable, that this does a |QueryInterface| even
when constructed from a |T*| but we can't tell the difference between a |T*|
and a pointer to some object derived from |class T|.
*/
{
nsresult status = NS_OK;
if ( !aRawPtr || !NS_SUCCEEDED( status = aRawPtr->QueryInterface(T::IID(), NSCAP_REINTERPRET_CAST(void**, &mRawPtr)) ) )
mRawPtr = 0; // ...in case they wrote |QueryInterface| wrong, and it returns an error _and_ a pointer
// ...and |QueryInterface| does the |AddRef| for us (if it returned a pointer)
mImplicitQueryInterfaceResult = status;
}
nsCOMPtr( const nsDontAddRef<T>& aSmartPtr )
: mRawPtr(aSmartPtr.mRawPtr),
mImplicitQueryInterfaceResult(NS_OK)
nsCOMPtr()
// : nsCOMPtr_base(0)
{
// nothing else to do here
}
nsCOMPtr( const nsDontQueryInterface<T>& aSmartPtr )
: mRawPtr(aSmartPtr.mRawPtr),
mImplicitQueryInterfaceResult(NS_OK)
{
if ( mRawPtr )
{
NSCAP_ADDREF(mRawPtr);
}
}
nsCOMPtr( const nsQueryInterface& aSmartPtr )
// : nsCOMPtr_base(0)
{
assign_with_QueryInterface(aSmartPtr.mRawPtr, T::IID(), aSmartPtr.mErrorPtr);
}
nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
: mRawPtr(aSmartPtr.mRawPtr),
mImplicitQueryInterfaceResult(NS_OK)
nsCOMPtr( const nsDontAddRef<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
// nothing else to do here
}
nsCOMPtr( const nsDontQueryInterface<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
if ( mRawPtr )
{
NSCAP_ADDREF(mRawPtr);
}
NSCAP_ADDREF(mRawPtr);
}
~nsCOMPtr()
nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
if ( mRawPtr )
NSCAP_ADDREF(mRawPtr);
}
nsCOMPtr&
operator=( nsISupports* rhs )
{
T* rawPtr;
nsresult status = NS_OK;
if ( !rhs || !NS_SUCCEEDED( status = rhs->QueryInterface(T::IID(), NSCAP_REINTERPRET_CAST(void**, &rawPtr)) ) )
rawPtr = 0;
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mRawPtr = rawPtr;
mImplicitQueryInterfaceResult = status;
return *this;
}
nsCOMPtr&
operator=( const nsDontAddRef<T>& rhs )
nsCOMPtr<T>&
operator=( const nsQueryInterface& rhs )
{
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mRawPtr = rhs.mRawPtr;
mImplicitQueryInterfaceResult = NS_OK;
assign_with_QueryInterface(rhs.mRawPtr, T::IID(), rhs.mErrorPtr);
return *this;
}
nsCOMPtr&
operator=( const nsDontQueryInterface<T>& rhs )
{
T* rawPtr = rhs.mRawPtr;
nsCOMPtr<T>&
operator=( const nsDontAddRef<T>& rhs )
{
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
mRawPtr = rhs.mRawPtr;
return *this;
}
if ( rawPtr )
{
NSCAP_ADDREF(rawPtr);
}
nsCOMPtr<T>&
operator=( const nsDontQueryInterface<T>& rhs )
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
nsCOMPtr<T>&
operator=( const nsCOMPtr& rhs )
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
mRawPtr = rawPtr;
mImplicitQueryInterfaceResult = NS_OK;
return *this;
}
nsCOMPtr&
operator=( const nsCOMPtr& rhs )
{
T* rawPtr = rhs.mRawPtr;
if ( rawPtr )
{
NSCAP_ADDREF(rawPtr);
}
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mRawPtr = rawPtr;
mImplicitQueryInterfaceResult = NS_OK;
return *this;
}
nsDerivedSafe<T>*
get() const
// returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|
{
return NSCAP_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
}
nsDerivedSafe<T>*
operator->() const
@ -587,110 +568,29 @@ class nsCOMPtr
return get();
}
nsDerivedSafe<T>*
get() const
// returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|
{
return NSCAP_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
}
nsresult
assignment_error() const
{
return mRawPtr ? NS_OK : mImplicitQueryInterfaceResult;
}
#if 0
private:
friend class nsGetterAddRefs<T>;
friend class nsGetterDoesntAddRef<T>;
/*
In a perfect world, the following two member functions, |StartAssignment| and
|FinishAssignment|, would be private. They are and should be only accessed by
the closely related classes |nsGetterAddRefs<T>| and |nsGetterDoesntAddRef<T>|.
In a perfect world, the following member function, |StartAssignment|, would be private.
It is and should be only accessed by the closely related class |nsGetterAddRefs<T>|.
Unfortunately, some compilers---most notably VC++5.0---fail to grok the
friend declarations above or in any alternate acceptable form. So, physically
they will be public (until our compilers get smarter); but they are not to be
friend declaration above or in any alternate acceptable form. So, physically
it will be public (until our compilers get smarter); but it is not to be
considered part of the logical public interface.
*/
#endif
T**
StartAssignment( NSCAP_BOOL awaiting_AddRef )
StartAssignment()
{
if ( mRawPtr && !mIsAwaitingAddRef )
{
NSCAP_RELEASE(mRawPtr);
}
mIsAwaitingAddRef = awaiting_AddRef;
mRawPtr = 0;
return &mRawPtr;
return NSCAP_REINTERPRET_CAST(T**, begin_assignment());
}
void
FinishAssignment()
{
if ( mRawPtr && mIsAwaitingAddRef )
{
NSCAP_ADDREF(mRawPtr);
}
mImplicitQueryInterfaceResult = NS_OK;
}
private:
T* mRawPtr;
union
{
NSCAP_BOOL mIsAwaitingAddRef;
nsresult mImplicitQueryInterfaceResult;
};
};
/*
The following functions make comparing |nsCOMPtr|s and raw pointers
more convenient.
*/
template <class T>
inline
NSCAP_BOOL
operator==( const nsCOMPtr<T>& lhs, const T*const rhs )
{
return lhs.get() == rhs;
}
template <class T>
inline
NSCAP_BOOL
operator!=( const nsCOMPtr<T>& lhs, const T*const rhs )
{
return lhs.get() != rhs;
}
template <class T>
inline
NSCAP_BOOL
operator==( const T*const lhs, const nsCOMPtr<T>& rhs )
{
return lhs == rhs.get();
}
template <class T>
inline
NSCAP_BOOL
operator!=( const T*const lhs, const nsCOMPtr<T>& rhs )
{
return lhs != rhs.get();
}
template <class T>
class nsGetterAddRefs
/*
@ -715,32 +615,32 @@ class nsGetterAddRefs
public:
explicit
nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
: mTargetSmartPtr(&aSmartPtr)
: mTargetSmartPtr(aSmartPtr)
{
// nothing else to do
}
operator void**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr->StartAssignment(0));
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
}
T*&
operator*()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return *(mTargetSmartPtr->StartAssignment(0));
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return *(mTargetSmartPtr.StartAssignment());
}
operator T**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return mTargetSmartPtr->StartAssignment(0);
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return mTargetSmartPtr.StartAssignment();
}
private:
nsCOMPtr<T>* mTargetSmartPtr;
nsCOMPtr<T>& mTargetSmartPtr;
};
template <class T>
@ -758,65 +658,4 @@ getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
template <class T>
class nsGetterDoesntAddRef
/*
...
*/
{
public:
explicit
nsGetterDoesntAddRef( nsCOMPtr<T>& aSmartPtr )
: mTargetSmartPtr(&aSmartPtr)
{
// nothing else to do
}
nsGetterDoesntAddRef( nsGetterDoesntAddRef<T>& F )
: mTargetSmartPtr(F.mTargetSmartPtr)
{
F.mTargetSmartPtr = 0;
}
~nsGetterDoesntAddRef()
{
if ( mTargetSmartPtr )
mTargetSmartPtr->FinishAssignment();
}
operator void**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_doesnt_AddRef into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr->StartAssignment(1));
}
T*&
operator*()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_doesnt_AddRef into no destination");
return *(mTargetSmartPtr->StartAssignment(1));
}
operator T**()
{
NS_PRECONDITION(mTargetSmartPtr != 0, "getter_doesnt_AddRef into no destination");
return mTargetSmartPtr->StartAssignment(1);
}
private:
nsGetterDoesntAddRef<T> operator=( const nsGetterDoesntAddRef<T>& ); // not to be implemented
private:
nsCOMPtr<T>* mTargetSmartPtr;
};
template <class T>
inline
nsGetterDoesntAddRef<T>
getter_doesnt_AddRef( nsCOMPtr<T>& aSmartPtr )
{
return nsGetterDoesntAddRef<T>(aSmartPtr);
}
#endif // !defined(nsCOMPtr_h___)

View File

@ -25,8 +25,10 @@
#ifndef NSCAP_NO_NEW_CASTS
#define STATIC_CAST(T,x) static_cast<T>(x)
#define REINTERPRET_CAST(T,x) reinterpret_cast<T>(x)
#else
#define STATIC_CAST(T,x) ((T)(x))
#define REINTERPRET_CAST(T,x) ((T)(x))
#endif
@ -289,6 +291,87 @@ AVoidPtrPtrContext( void** )
static
nsresult
TestBloat_Raw()
{
IBar* barP = 0;
nsresult result = CreateIBar(REINTERPRET_CAST(void**, &barP));
if ( barP )
{
try
{
IFoo* fooP = 0;
if ( NS_SUCCEEDED( result = barP->QueryInterface(IFoo::IID(), REINTERPRET_CAST(void**, &fooP)) ) )
{
try
{
fooP->print_totals();
}
catch( ... )
{
NS_RELEASE(fooP);
throw;
}
NS_RELEASE(fooP);
}
}
catch( ... )
{
NS_RELEASE(barP);
throw;
}
NS_RELEASE(barP);
}
return result;
}
static
nsresult
TestBloat_Raw_Unsafe()
{
IBar* barP = 0;
nsresult result = CreateIBar(REINTERPRET_CAST(void**, &barP));
if ( barP )
{
IFoo* fooP = 0;
if ( NS_SUCCEEDED( result = barP->QueryInterface(IFoo::IID(), REINTERPRET_CAST(void**, &fooP)) ) )
{
fooP->print_totals();
NS_RELEASE(fooP);
}
NS_RELEASE(barP);
}
return result;
}
static
nsresult
TestBloat_Smart()
{
nsCOMPtr<IBar> barP;
nsresult result = CreateIBar( getter_AddRefs(barP) );
nsCOMPtr<IFoo> fooP( do_QueryInterface(barP, &result) );
if ( fooP )
fooP->print_totals();
return result;
}
nsCOMPtr<IFoo> gFoop;
@ -299,6 +382,10 @@ main()
cout << "sizeof(nsCOMPtr<IFoo>) --> " << sizeof(nsCOMPtr<IFoo>) << endl;
TestBloat_Raw();
TestBloat_Raw_Unsafe();
TestBloat_Smart();
{
cout << endl << "### Test 1: will a |nsCOMPtr| call |AddRef| on a pointer assigned into it?" << endl;
@ -348,7 +435,7 @@ main()
IFoo* raw_foo2p = foo2p.get();
cout << endl << "### Test 8: can you compare a |nsCOMPtr| with a raw interface pointer [!=]?" << endl;
if ( foo1p != raw_foo2p )
if ( foo1p.get() != raw_foo2p )
cout << "foo1p != raw_foo2p" << endl;
else
cout << "foo1p == raw_foo2p" << endl;
@ -364,11 +451,19 @@ main()
cout << "foo1p != foo2p" << endl;
cout << endl << "### Test 11: can you compare a |nsCOMPtr| with a raw interface pointer [==]?" << endl;
if ( raw_foo2p == foo2p )
if ( raw_foo2p == foo2p.get() )
cout << "raw_foo2p == foo2p" << endl;
else
cout << "raw_foo2p != foo2p" << endl;
#if 1
cout << endl << "### Test 11.5: can you compare a |nsCOMPtr| with a raw interface pointer [==]?" << endl;
if ( nsCOMPtr<IFoo>( dont_QueryInterface(raw_foo2p) ) == foo2p )
cout << "raw_foo2p == foo2p" << endl;
else
cout << "raw_foo2p != foo2p" << endl;
#endif
cout << endl << "### Test 12: bare pointer test?" << endl;
if ( foo1p )
cout << "foo1p is not NULL" << endl;
@ -463,7 +558,7 @@ main()
cout << "### Test 23: is |QueryInterface| called when assigning in a smart-pointer of a different type?" << endl;
nsCOMPtr<IFoo> fooP( barP );
nsCOMPtr<IFoo> fooP( do_QueryInterface(barP) );
if ( fooP )
cout << "an IBar* is an IFoo*" << endl;
}
@ -482,21 +577,7 @@ main()
cout << "### End Test 24" << endl;
{
cout << endl << "### setup for Test 25" << endl;
nsCOMPtr<IFoo> fooP( new IFoo );
nsCOMPtr<IBar> barP;
cout << "### Test 25: will an assignment fail when the interface is not supported, is the error available?" << endl;
barP = fooP;
cout << "barP.assignment_error() --> " << barP.assignment_error() << endl;
cout << "### cleanup for Test 25" << endl;
}
cout << "### End Test 25" << endl;
cout << endl << "### Test 26: will a static |nsCOMPtr| |Release| before program termination?" << endl;
cout << endl << "### Test 25: will a static |nsCOMPtr| |Release| before program termination?" << endl;
gFoop = new IFoo;
cout << "<<main()" << endl;

Binary file not shown.