📄 nscomptr.h
字号:
: private nsCOMPtr_base#endif { enum { _force_even_compliant_compilers_to_fail_ = sizeof(T) }; /* The declaration above exists specifically to make |nsCOMPtr<T>| _not_ compile with only a forward declaration of |T|. This should prevent Windows and Mac engineers from breaking Solaris and other compilers that naturally have this behavior. Thank <law@netscape.com> for inventing this specific trick. Of course, if you're using |nsCOMPtr| outside the scope of wanting to compile on Solaris and old GCC, you probably want to remove the enum so you can exploit forward declarations. */#ifdef NSCAP_FEATURE_DEBUG_PTR_TYPES 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; #define NSCAP_CTOR_BASE(x) mRawPtr(x)#else #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)#endif public: typedef T element_type; #ifndef NSCAP_FEATURE_FACTOR_DESTRUCTOR ~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_DEBUG_PTR_TYPES T* temp = rhs.mRawPtr;#else nsISupports* 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_DEBUG_PTR_TYPES T* temp = rhs;#else nsISupports* 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_TEMPLATEclass nsCOMPtr<nsISupports> : private nsCOMPtr_base { public: typedef nsISupports element_type;#ifndef NSCAP_FEATURE_FACTOR_DESTRUCTOR ~nsCOMPtr() { NSCAP_LOG_RELEASE(this, mRawPtr); if ( mRawPtr ) NSCAP_RELEASE(this, mRawPtr); }#endif // 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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -