📄 nscomptr.h
字号:
: 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_helper( const nsCOMPtr_helper&, const nsIID& );
void** begin_assignment();
void
assign_assuming_AddRef( T* newPtr )
{
T* oldPtr = mRawPtr;
mRawPtr = newPtr;
NSCAP_LOG_ASSIGNMENT(this, newPtr);
NSCAP_LOG_RELEASE(this, oldPtr);
if ( oldPtr )
NSCAP_RELEASE(this, oldPtr);
}
private:
T* mRawPtr;
#endif
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(0)
// default constructor
{
NSCAP_LOG_ASSIGNMENT(this, 0);
}
nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
: NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
// copy-constructor
{
if ( mRawPtr )
NSCAP_ADDREF(this, mRawPtr);
NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
}
nsCOMPtr( T* aRawPtr )
: NSCAP_CTOR_BASE(aRawPtr)
// construct from a raw pointer (of the right type)
{
if ( mRawPtr )
NSCAP_ADDREF(this, mRawPtr);
NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
NSCAP_ASSERT_NO_QUERY_NEEDED();
}
nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
: NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
// construct from |dont_AddRef(expr)|
{
NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
NSCAP_ASSERT_NO_QUERY_NEEDED();
}
nsCOMPtr( const nsCOMPtr_helper& helper )
: NSCAP_CTOR_BASE(0)
// ...and finally, anything else we might need to construct from
// can exploit the |nsCOMPtr_helper| facility
{
NSCAP_LOG_ASSIGNMENT(this, 0);
assign_from_helper(helper, NS_GET_IID(T));
NSCAP_ASSERT_NO_QUERY_NEEDED();
}
#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
// For debug only --- this particular helper doesn't need to do the
// |NSCAP_ASSERT_NO_QUERY_NEEDED()| test. In fact, with the logging
// changes, skipping the query test prevents infinite recursion.
nsCOMPtr( const nsQueryInterface& helper )
: NSCAP_CTOR_BASE(0)
{
NSCAP_LOG_ASSIGNMENT(this, 0);
assign_from_helper(helper, NS_GET_IID(T));
}
#endif
// Assignment operators
nsCOMPtr<T>&
operator=( const nsCOMPtr<T>& rhs )
// copy assignment operator
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
nsCOMPtr<T>&
operator=( T* rhs )
// assign from a raw pointer (of the right type)
{
assign_with_AddRef(rhs);
NSCAP_ASSERT_NO_QUERY_NEEDED();
return *this;
}
nsCOMPtr<T>&
operator=( const already_AddRefed<T>& rhs )
// assign from |dont_AddRef(expr)|
{
assign_assuming_AddRef(rhs.mRawPtr);
NSCAP_ASSERT_NO_QUERY_NEEDED();
return *this;
}
nsCOMPtr<T>&
operator=( const nsCOMPtr_helper& rhs )
// ...and finally, anything else we might need to assign from
// can exploit the |nsCOMPtr_helper| facility.
{
assign_from_helper(rhs, NS_GET_IID(T));
NSCAP_ASSERT_NO_QUERY_NEEDED();
return *this;
}
#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
// For debug only --- this particular helper doesn't need to do the
// |NSCAP_ASSERT_NO_QUERY_NEEDED()| test. In fact, with the logging
// changes, skipping the query test prevents infinite recursion.
nsCOMPtr<T>&
operator=( const nsQueryInterface& rhs )
{
assign_from_helper(rhs, NS_GET_IID(T));
return *this;
}
#endif
void
swap( nsCOMPtr<T>& rhs )
// ...exchange ownership with |rhs|; can save a pair of refcount operations
{
#ifdef NSCAP_FEATURE_USE_BASE
nsISupports* temp = rhs.mRawPtr;
#else
T* temp = rhs.mRawPtr;
#endif
NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
NSCAP_LOG_ASSIGNMENT(this, temp);
NSCAP_LOG_RELEASE(this, mRawPtr);
NSCAP_LOG_RELEASE(&rhs, temp);
rhs.mRawPtr = mRawPtr;
mRawPtr = temp;
// |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
}
void
swap( T*& rhs )
// ...exchange ownership with |rhs|; can save a pair of refcount operations
{
#ifdef NSCAP_FEATURE_USE_BASE
nsISupports* temp = rhs;
#else
T* temp = rhs;
#endif
NSCAP_LOG_ASSIGNMENT(this, temp);
NSCAP_LOG_RELEASE(this, mRawPtr);
rhs = NS_REINTERPRET_CAST(T*, mRawPtr);
mRawPtr = temp;
NSCAP_ASSERT_NO_QUERY_NEEDED();
}
// Other pointer operators
nsDerivedSafe<T>*
get() const
/*
Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
Use |get()| _only_ to resolve ambiguity.
Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
*/
{
return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
}
operator nsDerivedSafe<T>*() const
/*
...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
and |delete|) 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.
*/
{
return get();
}
nsDerivedSafe<T>*
operator->() const
{
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
return get();
}
#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
// broken version for IRIX
nsCOMPtr<T>*
get_address() const
// This is not intended to be used by clients. See |address_of|
// below.
{
return NS_CONST_CAST(nsCOMPtr<T>*, this);
}
#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
nsCOMPtr<T>*
get_address()
// This is not intended to be used by clients. See |address_of|
// below.
{
return this;
}
const nsCOMPtr<T>*
get_address() const
// This is not intended to be used by clients. See |address_of|
// below.
{
return this;
}
#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
public:
nsDerivedSafe<T>&
operator*() const
{
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
return *get();
}
#if 0
private:
friend class nsGetterAddRefs<T>;
#endif
T**
StartAssignment()
{
#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
return NS_REINTERPRET_CAST(T**, begin_assignment());
#else
assign_assuming_AddRef(0);
return NS_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' pointer 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.
*/
NS_SPECIALIZE_TEMPLATE
class nsCOMPtr<nsISupports>
: private nsCOMPtr_base
{
public:
typedef nsISupports element_type;
// Constructors
nsCOMPtr()
: nsCOMPtr_base(0)
// default constructor
{
NSCAP_LOG_ASSIGNMENT(this, 0);
}
nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
// copy constructor
{
if ( mRawPtr )
NSCAP_ADDREF(this, mRawPtr);
NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
}
nsCOMPtr( nsISupports* aRawPtr )
: nsCOMPtr_base(aRawPtr)
// construct from a raw pointer (of the right type)
{
if ( mRawPtr )
NSCAP_ADDREF(this, mRawPtr);
NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
}
nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
// construct from |dont_AddRef(expr)|
{
NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
}
nsCOMPtr( const nsCOMPtr_helper& helper )
: nsCOMPtr_base(0)
// ...and finally, anything else we might need to construct from
// can exploit the |nsCOMPtr_helper| facility
{
NSCAP_LOG_ASSIGNMENT(this, 0);
assign_from_helper(helper, NS_GET_IID(nsISupports));
}
// Assignment operators
nsCOMPtr<nsISupports>&
operator=( const nsCOMPtr<nsISupports>& rhs )
// copy assignment operator
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
nsCOMPtr<nsISupports>&
operator=( nsISupports* rhs )
// assign from a raw pointer (of the right type)
{
assign_with_AddRef(rhs);
return *this;
}
nsCOMPtr<nsISupports>&
operator=( const already_AddRefed<nsISupports>& rhs )
// assign from |dont_AddRef(expr)|
{
assign_assuming_AddRef(rhs.mRawPtr);
return *this;
}
nsCOMPtr<nsISupports>&
operator=( const nsCOMPtr_helper& rhs )
// ...and finally, anything else we might need to assign from
// can exploit the |nsCOMPtr_helper| facility.
{
assign_from_helper(rhs, NS_GET_IID(nsISupports));
return *this;
}
void
swap( nsCOMPtr<nsISupports>& rhs )
// ...exchange ownership with |rhs|; can save a pair of refcount operations
{
nsISupports* temp = rhs.mRawPtr;
NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
NSCAP_LOG_ASSIGNMENT(this, temp);
NSCAP_LOG_RELEASE(this, mRawPtr);
NSCAP_LOG_RELEASE(&rhs, temp);
rhs.mRawPtr = mRawPtr;
mRawPtr = temp;
}
void
swap( nsISupports*& rhs )
// ...exchange ownership with |rhs|; can save a pair of refcount operations
{
nsISupports* temp = rhs;
NSCAP_LOG_ASSIGNMENT(this, temp);
NSCAP_LOG_RELEASE(this, mRawPtr);
rhs = mRawPtr;
mRawPtr = temp;
}
// Other pointer operators
nsDerivedSafe<nsISupports>*
get() const
/*
Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
Use |get()| _only_ to resolve ambiguity.
Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of |AddRef| and |Release|.
*/
{
return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr);
}
operator nsDerivedSafe<nsISupports>*() const
/*
...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
and |delete|) 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.
*/
{
return get();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -