LCOV - code coverage report
Current view: directory - xpcom/glue - nsCOMPtr.h (source / functions) Found Hit Coverage
Test: app.info Lines: 189 124 65.6 %
Date: 2012-06-02 Functions: 374 97 25.9 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Scott Collins <scc@mozilla.org> (original author)
      24                 :  *   L. David Baron <dbaron@dbaron.org>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #ifndef nsCOMPtr_h___
      41                 : #define nsCOMPtr_h___
      42                 : 
      43                 : /*
      44                 :   Having problems?
      45                 :   
      46                 :   See the User Manual at:
      47                 :     http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
      48                 : 
      49                 : 
      50                 :   nsCOMPtr
      51                 :     better than a raw pointer
      52                 :   for owning objects
      53                 :                        -- scc
      54                 : */
      55                 : 
      56                 : #include "mozilla/Attributes.h"
      57                 : 
      58                 :   // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
      59                 : #ifndef nsDebug_h___
      60                 : #include "nsDebug.h"
      61                 :   // for |NS_ABORT_IF_FALSE|, |NS_ASSERTION|
      62                 : #endif
      63                 : 
      64                 : #ifndef nsISupportsUtils_h__
      65                 : #include "nsISupportsUtils.h"
      66                 :   // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
      67                 : #endif
      68                 : 
      69                 : #ifndef nscore_h___
      70                 : #include "nscore.h"
      71                 :   // for |NS_COM_GLUE|
      72                 : #endif
      73                 : 
      74                 : 
      75                 : /*
      76                 :   WARNING:
      77                 :     This file defines several macros for internal use only.  These macros begin with the
      78                 :     prefix |NSCAP_|.  Do not use these macros in your own code.  They are for internal use
      79                 :     only for cross-platform compatibility, and are subject to change without notice.
      80                 : */
      81                 : 
      82                 : 
      83                 : #ifdef _MSC_VER
      84                 :   #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
      85                 :     // under VC++, we win by inlining StartAssignment
      86                 : 
      87                 :     // Also under VC++, at the highest warning level, we are overwhelmed  with warnings
      88                 :     //  about (unused) inline functions being removed.  This is to be expected with
      89                 :     //  templates, so we disable the warning.
      90                 :   #pragma warning( disable: 4514 )
      91                 : #endif
      92                 : 
      93                 : #define NSCAP_FEATURE_USE_BASE
      94                 : 
      95                 : #ifdef NS_DEBUG
      96                 :   #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
      97                 :   #undef NSCAP_FEATURE_USE_BASE
      98                 : //#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
      99                 : #endif
     100                 : 
     101                 :   /*
     102                 :     |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is 
     103                 :     problematic on a select few of our platforms, e.g., QNX.  Therefore, I'm providing
     104                 :     a mechanism by which these features can be explicitly disabled from the command-line.
     105                 :   */
     106                 : 
     107                 : #ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
     108                 :   #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
     109                 : #endif
     110                 : 
     111                 : #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
     112                 :   // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
     113                 :   // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
     114                 :   // don't reorder instructions based on aliasing assumptions for
     115                 :   // this variable.  Fortunately, gcc versions < 3.3 do not do any
     116                 :   // optimizations that break nsCOMPtr.
     117                 : 
     118                 :   #define NS_MAY_ALIAS_PTR(t)    t*  __attribute__((__may_alias__))
     119                 : #else
     120                 :   #define NS_MAY_ALIAS_PTR(t)    t*
     121                 : #endif
     122                 : 
     123                 : #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
     124                 :   #define NSCAP_FEATURE_USE_BASE
     125                 : #endif
     126                 : 
     127                 :   /*
     128                 :     The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
     129                 :       allow external clients the ability to add logging or other interesting debug facilities.
     130                 :       In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
     131                 :       provide (e.g., in "nsTraceRefcnt.h") suitable definitions
     132                 : 
     133                 :         #define NSCAP_ADDREF(this, ptr)         NS_ADDREF(ptr)
     134                 :         #define NSCAP_RELEASE(this, ptr)        NS_RELEASE(ptr)
     135                 :   */
     136                 : 
     137                 : #ifndef NSCAP_ADDREF
     138                 :   #define NSCAP_ADDREF(this, ptr)     (ptr)->AddRef()
     139                 : #endif
     140                 : 
     141                 : #ifndef NSCAP_RELEASE
     142                 :   #define NSCAP_RELEASE(this, ptr)    (ptr)->Release()
     143                 : #endif
     144                 : 
     145                 :   // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
     146                 : #ifdef NSCAP_LOG_ASSIGNMENT
     147                 :     // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
     148                 :     //  to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
     149                 :     //  the |nsCOMPtr|.
     150                 :   #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
     151                 : #else
     152                 :     // ...otherwise, just strip it out of the code
     153                 :   #define NSCAP_LOG_ASSIGNMENT(this, ptr)
     154                 : #endif
     155                 : 
     156                 : #ifndef NSCAP_LOG_RELEASE
     157                 :   #define NSCAP_LOG_RELEASE(this, ptr)
     158                 : #endif
     159                 : 
     160                 : template <class T>
     161                 : struct already_AddRefed
     162                 :     /*
     163                 :       ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
     164                 :       |AddRef|ing it.  You might want to use this as a return type from a function
     165                 :       that produces an already |AddRef|ed pointer as a result.
     166                 : 
     167                 :       See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
     168                 : 
     169                 :       This type should be a nested class inside |nsCOMPtr<T>|.
     170                 : 
     171                 :       Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
     172                 :       avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
     173                 :       case, and perhaps worth the savings in time and space that its specific
     174                 :       implementation affords over the more general solution offered by
     175                 :       |nsCOMPtr_helper|.
     176                 :     */
     177                 :   {
     178          439167 :     already_AddRefed( T* aRawPtr )
     179          439167 :         : mRawPtr(aRawPtr)
     180                 :       {
     181                 :         // nothing else to do here
     182          439167 :       }
     183                 : 
     184           15521 :     T* get() const { return mRawPtr; }
     185                 : 
     186                 :     /**
     187                 :      * This helper is useful in cases like
     188                 :      *
     189                 :      *  already_AddRefed<BaseClass>
     190                 :      *  Foo()
     191                 :      *  {
     192                 :      *    nsRefPtr<SubClass> x = ...;
     193                 :      *    return x.forget();
     194                 :      *  }
     195                 :      *
     196                 :      * The autoconversion allows one to omit the idiom
     197                 :      *
     198                 :      *    nsRefPtr<BaseClass> y = x.forget();
     199                 :      *    return y.forget();
     200                 :      */
     201                 :     template<class U>
     202                 :     operator already_AddRefed<U>()
     203                 :     {
     204                 :       U* tmp = mRawPtr;
     205                 :       mRawPtr = NULL;
     206                 :       return tmp;
     207                 :     }
     208                 : 
     209                 :     T* mRawPtr;
     210                 :   };
     211                 : 
     212                 : template <class T>
     213                 : inline
     214                 : const already_AddRefed<T>
     215                 : getter_AddRefs( T* aRawPtr )
     216                 :     /*
     217                 :       ...makes typing easier, because it deduces the template type, e.g., 
     218                 :       you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
     219                 :     */
     220                 :   {
     221                 :     return already_AddRefed<T>(aRawPtr);
     222                 :   }
     223                 : 
     224                 : template <class T>
     225                 : inline
     226                 : const already_AddRefed<T>
     227                 : getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
     228                 :   {
     229                 :     return aAlreadyAddRefedPtr;
     230                 :   }
     231                 : 
     232                 : template <class T>
     233                 : inline
     234                 : const already_AddRefed<T>
     235                 : dont_AddRef( T* aRawPtr )
     236                 :   {
     237                 :     return already_AddRefed<T>(aRawPtr);
     238                 :   }
     239                 : 
     240                 : template <class T>
     241                 : inline
     242                 : const already_AddRefed<T>
     243                 : dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
     244                 :   {
     245                 :     return aAlreadyAddRefedPtr;
     246                 :   }
     247                 : 
     248                 : 
     249                 : 
     250                 : class nsCOMPtr_helper
     251                 :     /*
     252                 :       An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
     253                 :       that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
     254                 :       Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
     255                 : 
     256                 :       Here are the rules for a helper:
     257                 :         - it implements |operator()| to produce an interface pointer
     258                 :         - (except for its name) |operator()| is a valid [XP]COM `getter'
     259                 :         - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
     260                 :         - it matches the type requested with the supplied |nsIID| argument
     261                 :         - its constructor provides an optional |nsresult*| that |operator()| can fill
     262                 :           in with an error when it is executed
     263                 :           
     264                 :       See |class nsGetInterface| for an example.
     265                 :     */
     266                 :   {
     267                 :     public:
     268                 :       virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
     269                 :   };
     270                 : 
     271                 : /*
     272                 :   |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
     273                 :   avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
     274                 :   is called often enough that the codesize savings are big enough to
     275                 :   warrant the specialcasing.
     276                 : */
     277                 : 
     278                 : class
     279                 :   NS_COM_GLUE
     280                 :   NS_STACK_CLASS
     281                 : nsQueryInterface MOZ_FINAL
     282                 :   {
     283                 :     public:
     284                 :       explicit
     285              24 :       nsQueryInterface( nsISupports* aRawPtr )
     286              24 :           : mRawPtr(aRawPtr)
     287                 :         {
     288                 :           // nothing else to do here
     289              24 :         }
     290                 : 
     291                 :       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
     292                 : 
     293                 :     private:
     294                 :       nsISupports*  mRawPtr;
     295                 :   };
     296                 : 
     297                 : class NS_COM_GLUE nsQueryInterfaceWithError
     298                 :   {
     299                 :     public:
     300               1 :       nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
     301                 :           : mRawPtr(aRawPtr),
     302               1 :             mErrorPtr(error)
     303                 :         {
     304                 :           // nothing else to do here
     305               1 :         }
     306                 : 
     307                 :       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
     308                 : 
     309                 :     private:
     310                 :       nsISupports*  mRawPtr;
     311                 :       nsresult*     mErrorPtr;
     312                 :   };
     313                 : 
     314                 : inline
     315                 : nsQueryInterface
     316              24 : do_QueryInterface( nsISupports* aRawPtr )
     317                 :   {
     318              24 :     return nsQueryInterface(aRawPtr);
     319                 :   }
     320                 : 
     321                 : inline
     322                 : nsQueryInterfaceWithError
     323               1 : do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
     324                 :   {
     325               1 :     return nsQueryInterfaceWithError(aRawPtr, error);
     326                 :   }
     327                 : 
     328                 : template <class T>
     329                 : inline
     330                 : void
     331                 : do_QueryInterface( already_AddRefed<T>& )
     332                 :   {
     333                 :     // This signature exists solely to _stop_ you from doing the bad thing.
     334                 :     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
     335                 :     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
     336                 :   }
     337                 : 
     338                 : template <class T>
     339                 : inline
     340                 : void
     341                 : do_QueryInterface( already_AddRefed<T>&, nsresult* )
     342                 :   {
     343                 :     // This signature exists solely to _stop_ you from doing the bad thing.
     344                 :     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
     345                 :     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
     346                 :   }
     347                 : 
     348                 : 
     349                 : ////////////////////////////////////////////////////////////////////////////
     350                 : // Using servicemanager with COMPtrs
     351                 : class NS_COM_GLUE nsGetServiceByCID
     352                 : {
     353                 :  public:
     354                 :     explicit nsGetServiceByCID(const nsCID& aCID)
     355                 :         : mCID(aCID)
     356                 :         {
     357                 :             // nothing else to do
     358                 :         }
     359                 :     
     360                 :     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
     361                 :     
     362                 :  private:
     363                 :     const nsCID&                mCID;
     364                 : };
     365                 : 
     366                 : class NS_COM_GLUE nsGetServiceByCIDWithError
     367                 : {
     368                 :  public:
     369                 :     nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
     370                 :         : mCID(aCID),
     371                 :           mErrorPtr(aErrorPtr)
     372                 :         {
     373                 :             // nothing else to do
     374                 :         }
     375                 :     
     376                 :     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
     377                 :     
     378                 :  private:
     379                 :     const nsCID&                mCID;
     380                 :     nsresult*                   mErrorPtr;
     381                 : };
     382                 : 
     383                 : class NS_COM_GLUE nsGetServiceByContractID
     384                 : {
     385                 :  public:
     386              24 :     explicit nsGetServiceByContractID(const char* aContractID)
     387              24 :         : mContractID(aContractID)
     388                 :         {
     389                 :             // nothing else to do
     390              24 :         }
     391                 :     
     392                 :     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
     393                 :     
     394                 :  private:
     395                 :     const char*                 mContractID;
     396                 : };
     397                 : 
     398                 : class NS_COM_GLUE nsGetServiceByContractIDWithError
     399                 : {
     400                 :  public:
     401               0 :     nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
     402                 :         : mContractID(aContractID),
     403               0 :           mErrorPtr(aErrorPtr)
     404                 :         {
     405                 :             // nothing else to do
     406               0 :         }
     407                 :     
     408                 :     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
     409                 :     
     410                 :  private:
     411                 :     const char*                 mContractID;
     412                 :     nsresult*                   mErrorPtr;
     413                 : };
     414                 : 
     415                 : class
     416                 : nsCOMPtr_base
     417                 :     /*
     418                 :       ...factors implementation for all template versions of |nsCOMPtr|.
     419                 : 
     420                 :       This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
     421                 :       because unlike the
     422                 : 
     423                 :       Here's the way people normally do things like this
     424                 :       
     425                 :         template <class T> class Foo { ... };
     426                 :         template <> class Foo<void*> { ... };
     427                 :         template <class T> class Foo<T*> : private Foo<void*> { ... };
     428                 :     */
     429                 :   {
     430                 :     public:
     431                 : 
     432               0 :       nsCOMPtr_base( nsISupports* rawPtr = 0 )
     433               0 :           : mRawPtr(rawPtr)
     434                 :         {
     435                 :           // nothing else to do here
     436               0 :         }
     437                 : 
     438                 :       NS_COM_GLUE NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base();
     439                 : 
     440                 :       NS_COM_GLUE void NS_FASTCALL   assign_with_AddRef( nsISupports* );
     441                 :       NS_COM_GLUE void NS_FASTCALL   assign_from_qi( const nsQueryInterface, const nsIID& );
     442                 :       NS_COM_GLUE void NS_FASTCALL   assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
     443                 :       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
     444                 :       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
     445                 :       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
     446                 :       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
     447                 :       NS_COM_GLUE void NS_FASTCALL   assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
     448                 :       NS_COM_GLUE void** NS_FASTCALL begin_assignment();
     449                 : 
     450                 :     protected:
     451                 :       NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
     452                 : 
     453                 :       void
     454              13 :       assign_assuming_AddRef( nsISupports* newPtr )
     455                 :         {
     456                 :             /*
     457                 :               |AddRef()|ing the new value (before entering this function) before
     458                 :               |Release()|ing the old lets us safely ignore the self-assignment case.
     459                 :               We must, however, be careful only to |Release()| _after_ doing the
     460                 :               assignment, in case the |Release()| leads to our _own_ destruction,
     461                 :               which would, in turn, cause an incorrect second |Release()| of our old
     462                 :               pointer.  Thank <waterson@netscape.com> for discovering this.
     463                 :             */
     464              13 :           nsISupports* oldPtr = mRawPtr;
     465              13 :           mRawPtr = newPtr;
     466              13 :           NSCAP_LOG_ASSIGNMENT(this, newPtr);
     467              13 :           NSCAP_LOG_RELEASE(this, oldPtr);
     468              13 :           if ( oldPtr )
     469               0 :             NSCAP_RELEASE(this, oldPtr);
     470              13 :         }
     471                 :   };
     472                 : 
     473                 : // template <class T> class nsGetterAddRefs;
     474                 : 
     475                 : template <class T>
     476                 : class nsCOMPtr MOZ_FINAL
     477                 : #ifdef NSCAP_FEATURE_USE_BASE
     478                 :     : private nsCOMPtr_base
     479                 : #endif
     480                 :   {
     481                 : 
     482                 : #ifdef NSCAP_FEATURE_USE_BASE
     483                 :   #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
     484                 : #else
     485                 :   #define NSCAP_CTOR_BASE(x) mRawPtr(x)
     486                 : 
     487                 :     private:
     488                 :       void    assign_with_AddRef( nsISupports* );
     489                 :       void    assign_from_qi( const nsQueryInterface, const nsIID& );
     490                 :       void    assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
     491                 :       void    assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
     492                 :       void    assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
     493                 :       void    assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
     494                 :       void    assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
     495                 :       void    assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
     496                 :       void**  begin_assignment();
     497                 : 
     498                 :       void
     499          466432 :       assign_assuming_AddRef( T* newPtr )
     500                 :         {
     501          466432 :           T* oldPtr = mRawPtr;
     502          466432 :           mRawPtr = newPtr;
     503          466432 :           NSCAP_LOG_ASSIGNMENT(this, newPtr);
     504          466432 :           NSCAP_LOG_RELEASE(this, oldPtr);
     505          466432 :           if ( oldPtr )
     506               0 :             NSCAP_RELEASE(this, oldPtr);
     507          466432 :         }
     508                 : 
     509                 :     private:
     510                 :       T* mRawPtr;
     511                 : #endif
     512                 : 
     513                 :     public:
     514                 :       typedef T element_type;
     515                 :       
     516                 : #ifndef NSCAP_FEATURE_USE_BASE
     517          466432 :      ~nsCOMPtr()
     518                 :         {
     519          466432 :           NSCAP_LOG_RELEASE(this, mRawPtr);
     520          466432 :           if ( mRawPtr )
     521          458384 :             NSCAP_RELEASE(this, mRawPtr);
     522          466432 :         }
     523                 : #endif
     524                 : 
     525                 : #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
     526                 :       void
     527          149897 :       Assert_NoQueryNeeded()
     528                 :         {
     529          149897 :           if ( mRawPtr )
     530                 :             {
     531          299792 :               nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
     532          149896 :               NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
     533                 :             }
     534          149897 :         }
     535                 : 
     536                 :   #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
     537                 : #else
     538                 :   #define NSCAP_ASSERT_NO_QUERY_NEEDED()
     539                 : #endif
     540                 : 
     541                 : 
     542                 :         // Constructors
     543                 : 
     544          175256 :       nsCOMPtr()
     545          175256 :             : NSCAP_CTOR_BASE(0)
     546                 :           // default constructor
     547                 :         {
     548                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     549          175256 :         }
     550                 : 
     551               0 :       nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
     552               0 :             : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
     553                 :           // copy-constructor
     554                 :         {
     555               0 :           if ( mRawPtr )
     556               0 :             NSCAP_ADDREF(this, mRawPtr);
     557               0 :           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
     558               0 :         }
     559                 : 
     560            3054 :       nsCOMPtr( T* aRawPtr )
     561            3054 :             : NSCAP_CTOR_BASE(aRawPtr)
     562                 :           // construct from a raw pointer (of the right type)
     563                 :         {
     564            3054 :           if ( mRawPtr )
     565            3054 :             NSCAP_ADDREF(this, mRawPtr);
     566            3054 :           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
     567            3054 :           NSCAP_ASSERT_NO_QUERY_NEEDED();
     568            3054 :         }
     569                 : 
     570               0 :       nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
     571               0 :             : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
     572                 :           // construct from |dont_AddRef(expr)|
     573                 :         {
     574               0 :           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
     575               0 :           NSCAP_ASSERT_NO_QUERY_NEEDED();
     576               0 :         }
     577                 : 
     578          149896 :       nsCOMPtr( const nsQueryInterface qi )
     579          149896 :             : NSCAP_CTOR_BASE(0)
     580                 :           // construct from |do_QueryInterface(expr)|
     581                 :         {
     582                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     583          149896 :           assign_from_qi(qi, NS_GET_TEMPLATE_IID(T));
     584          149896 :         }
     585                 : 
     586               1 :       nsCOMPtr( const nsQueryInterfaceWithError& qi )
     587               1 :             : NSCAP_CTOR_BASE(0)
     588                 :           // construct from |do_QueryInterface(expr, &rv)|
     589                 :         {
     590                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     591               1 :           assign_from_qi_with_error(qi, NS_GET_TEMPLATE_IID(T));
     592               1 :         }
     593                 : 
     594                 :       nsCOMPtr( const nsGetServiceByCID gs )
     595                 :             : NSCAP_CTOR_BASE(0)
     596                 :           // construct from |do_GetService(cid_expr)|
     597                 :         {
     598                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     599                 :           assign_from_gs_cid(gs, NS_GET_TEMPLATE_IID(T));
     600                 :         }
     601                 : 
     602                 :       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
     603                 :             : NSCAP_CTOR_BASE(0)
     604                 :           // construct from |do_GetService(cid_expr, &rv)|
     605                 :         {
     606                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     607                 :           assign_from_gs_cid_with_error(gs, NS_GET_TEMPLATE_IID(T));
     608                 :         }
     609                 : 
     610          167846 :       nsCOMPtr( const nsGetServiceByContractID gs )
     611          167846 :             : NSCAP_CTOR_BASE(0)
     612                 :           // construct from |do_GetService(contractid_expr)|
     613                 :         {
     614                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     615          167846 :           assign_from_gs_contractid(gs, NS_GET_TEMPLATE_IID(T));
     616          167846 :         }
     617                 : 
     618             234 :       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
     619             234 :             : NSCAP_CTOR_BASE(0)
     620                 :           // construct from |do_GetService(contractid_expr, &rv)|
     621                 :         {
     622                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     623             234 :           assign_from_gs_contractid_with_error(gs, NS_GET_TEMPLATE_IID(T));
     624             234 :         }
     625                 : 
     626                 :       nsCOMPtr( const nsCOMPtr_helper& helper )
     627                 :             : NSCAP_CTOR_BASE(0)
     628                 :           // ...and finally, anything else we might need to construct from
     629                 :           //  can exploit the |nsCOMPtr_helper| facility
     630                 :         {
     631                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     632                 :           assign_from_helper(helper, NS_GET_TEMPLATE_IID(T));
     633                 :           NSCAP_ASSERT_NO_QUERY_NEEDED();
     634                 :         }
     635                 : 
     636                 : 
     637                 :         // Assignment operators
     638                 : 
     639                 :       nsCOMPtr<T>&
     640                 :       operator=( const nsCOMPtr<T>& rhs )
     641                 :           // copy assignment operator
     642                 :         {
     643                 :           assign_with_AddRef(rhs.mRawPtr);
     644                 :           return *this;
     645                 :         }
     646                 : 
     647                 :       nsCOMPtr<T>&
     648               0 :       operator=( T* rhs )
     649                 :           // assign from a raw pointer (of the right type)
     650                 :         {
     651               0 :           assign_with_AddRef(rhs);
     652               0 :           NSCAP_ASSERT_NO_QUERY_NEEDED();
     653               0 :           return *this;
     654                 :         }
     655                 : 
     656                 :       nsCOMPtr<T>&
     657               0 :       operator=( const already_AddRefed<T>& rhs )
     658                 :           // assign from |dont_AddRef(expr)|
     659                 :         {
     660               0 :           assign_assuming_AddRef(rhs.mRawPtr);
     661               0 :           NSCAP_ASSERT_NO_QUERY_NEEDED();
     662               0 :           return *this;
     663                 :         }
     664                 : 
     665                 :       nsCOMPtr<T>&
     666                 :       operator=( const nsQueryInterface rhs )
     667                 :           // assign from |do_QueryInterface(expr)|
     668                 :         {
     669                 :           assign_from_qi(rhs, NS_GET_TEMPLATE_IID(T));
     670                 :           return *this;
     671                 :         }
     672                 : 
     673                 :       nsCOMPtr<T>&
     674                 :       operator=( const nsQueryInterfaceWithError& rhs )
     675                 :           // assign from |do_QueryInterface(expr, &rv)|
     676                 :         {
     677                 :           assign_from_qi_with_error(rhs, NS_GET_TEMPLATE_IID(T));
     678                 :           return *this;
     679                 :         }
     680                 : 
     681                 :       nsCOMPtr<T>&
     682                 :       operator=( const nsGetServiceByCID rhs )
     683                 :           // assign from |do_GetService(cid_expr)|
     684                 :         {
     685                 :           assign_from_gs_cid(rhs, NS_GET_TEMPLATE_IID(T));
     686                 :           return *this;
     687                 :         }
     688                 : 
     689                 :       nsCOMPtr<T>&
     690                 :       operator=( const nsGetServiceByCIDWithError& rhs )
     691                 :           // assign from |do_GetService(cid_expr, &rv)|
     692                 :         {
     693                 :           assign_from_gs_cid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
     694                 :           return *this;
     695                 :         }
     696                 : 
     697                 :       nsCOMPtr<T>&
     698                 :       operator=( const nsGetServiceByContractID rhs )
     699                 :           // assign from |do_GetService(contractid_expr)|
     700                 :         {
     701                 :           assign_from_gs_contractid(rhs, NS_GET_TEMPLATE_IID(T));
     702                 :           return *this;
     703                 :         }
     704                 : 
     705                 :       nsCOMPtr<T>&
     706                 :       operator=( const nsGetServiceByContractIDWithError& rhs )
     707                 :           // assign from |do_GetService(contractid_expr, &rv)|
     708                 :         {
     709                 :           assign_from_gs_contractid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
     710                 :           return *this;
     711                 :         }
     712                 : 
     713                 :       nsCOMPtr<T>&
     714                 :       operator=( const nsCOMPtr_helper& rhs )
     715                 :           // ...and finally, anything else we might need to assign from
     716                 :           //  can exploit the |nsCOMPtr_helper| facility.
     717                 :         {
     718                 :           assign_from_helper(rhs, NS_GET_TEMPLATE_IID(T));
     719                 :           NSCAP_ASSERT_NO_QUERY_NEEDED();
     720                 :           return *this;
     721                 :         }
     722                 : 
     723                 :       void
     724                 :       swap( nsCOMPtr<T>& rhs )
     725                 :           // ...exchange ownership with |rhs|; can save a pair of refcount operations
     726                 :         {
     727                 : #ifdef NSCAP_FEATURE_USE_BASE
     728                 :           nsISupports* temp = rhs.mRawPtr;
     729                 : #else
     730                 :           T* temp = rhs.mRawPtr;
     731                 : #endif
     732                 :           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
     733                 :           NSCAP_LOG_ASSIGNMENT(this, temp);
     734                 :           NSCAP_LOG_RELEASE(this, mRawPtr);
     735                 :           NSCAP_LOG_RELEASE(&rhs, temp);
     736                 :           rhs.mRawPtr = mRawPtr;
     737                 :           mRawPtr = temp;
     738                 :           // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
     739                 :         }
     740                 : 
     741                 :       void
     742           24278 :       swap( T*& rhs )
     743                 :           // ...exchange ownership with |rhs|; can save a pair of refcount operations
     744                 :         {
     745                 : #ifdef NSCAP_FEATURE_USE_BASE
     746                 :           nsISupports* temp = rhs;
     747                 : #else
     748           24278 :           T* temp = rhs;
     749                 : #endif
     750           24278 :           NSCAP_LOG_ASSIGNMENT(this, temp);
     751           24278 :           NSCAP_LOG_RELEASE(this, mRawPtr);
     752           24278 :           rhs = reinterpret_cast<T*>(mRawPtr);
     753           24278 :           mRawPtr = temp;
     754           24278 :           NSCAP_ASSERT_NO_QUERY_NEEDED();
     755           24278 :         }
     756                 : 
     757                 : 
     758                 :         // Other pointer operators
     759                 : 
     760                 :       already_AddRefed<T>
     761           15521 :       forget()
     762                 :           // return the value of mRawPtr and null out mRawPtr. Useful for
     763                 :           // already_AddRefed return values.
     764                 :         {
     765           15521 :           T* temp = 0;
     766           15521 :           swap(temp);
     767           15521 :           return temp;
     768                 :         }
     769                 : 
     770                 :       template <typename I>
     771                 :       void
     772                 :       forget( I** rhs NS_OUTPARAM )
     773                 :           // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
     774                 :           // Useful to avoid unnecessary AddRef/Release pairs with "out"
     775                 :           // parameters where rhs bay be a T** or an I** where I is a base class
     776                 :           // of T.
     777                 :         {
     778                 :           NS_ASSERTION(rhs, "Null pointer passed to forget!");
     779                 :           *rhs = get();
     780                 :           mRawPtr = 0;
     781                 :         }
     782                 : 
     783                 :       T*
     784         1074368 :       get() const
     785                 :           /*
     786                 :             Prefer the implicit conversion provided automatically by |operator T*() const|.
     787                 :             Use |get()| to resolve ambiguity or to get a castable pointer.
     788                 :           */
     789                 :         {
     790         1074368 :           return reinterpret_cast<T*>(mRawPtr);
     791                 :         }
     792                 : 
     793          345849 :       operator T*() const
     794                 :           /*
     795                 :             ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it
     796                 :             is used in a context where a raw pointer is expected.  It is this operator
     797                 :             that makes an |nsCOMPtr| substitutable for a raw pointer.
     798                 : 
     799                 :             Prefer the implicit use of this operator to calling |get()|, except where
     800                 :             necessary to resolve ambiguity.
     801                 :           */
     802                 :         {
     803          345849 :           return get();
     804                 :         }
     805                 : 
     806                 :       T*
     807          336513 :       operator->() const
     808                 :         {
     809          336513 :           NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
     810          336513 :           return get();
     811                 :         }
     812                 : 
     813                 :       nsCOMPtr<T>*
     814          149896 :       get_address()
     815                 :           // This is not intended to be used by clients.  See |address_of|
     816                 :           // below.
     817                 :         {
     818          149896 :           return this;
     819                 :         }
     820                 : 
     821                 :       const nsCOMPtr<T>*
     822                 :       get_address() const
     823                 :           // This is not intended to be used by clients.  See |address_of|
     824                 :           // below.
     825                 :         {
     826                 :           return this;
     827                 :         }
     828                 : 
     829                 :     public:
     830                 :       T&
     831                 :       operator*() const
     832                 :         {
     833                 :           NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
     834                 :           return *get();
     835                 :         }
     836                 : 
     837                 :       T**
     838          149897 :       StartAssignment()
     839                 :         {
     840                 : #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
     841          149897 :           return reinterpret_cast<T**>(begin_assignment());
     842                 : #else
     843                 :           assign_assuming_AddRef(0);
     844                 :           return reinterpret_cast<T**>(&mRawPtr);
     845                 : #endif
     846                 :         }
     847                 :   };
     848                 : 
     849                 : 
     850                 : 
     851                 :   /*
     852                 :     Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
     853                 :     same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
     854                 :     to any valid [XP]COM interface.  Otherwise, an |nsCOMPtr<nsISupports>| would only be able
     855                 :     to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
     856                 :     querying ensues.  Clients need to be able to pass around arbitrary interface pointers,
     857                 :     without hassles, through intermediary code that doesn't know the exact type.
     858                 :   */
     859                 : 
     860                 : template <>
     861                 : class nsCOMPtr<nsISupports>
     862                 :     : private nsCOMPtr_base
     863               0 :   {
     864                 :     public:
     865                 :       typedef nsISupports element_type;
     866                 : 
     867                 :         // Constructors
     868                 : 
     869               0 :       nsCOMPtr()
     870               0 :             : nsCOMPtr_base(0)
     871                 :           // default constructor
     872                 :         {
     873                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     874               0 :         }
     875                 : 
     876                 :       nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
     877                 :             : nsCOMPtr_base(aSmartPtr.mRawPtr)
     878                 :           // copy constructor
     879                 :         {
     880                 :           if ( mRawPtr )
     881                 :             NSCAP_ADDREF(this, mRawPtr);
     882                 :           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
     883                 :         }
     884                 : 
     885                 :       nsCOMPtr( nsISupports* aRawPtr )
     886                 :             : nsCOMPtr_base(aRawPtr)
     887                 :           // construct from a raw pointer (of the right type)
     888                 :         {
     889                 :           if ( mRawPtr )
     890                 :             NSCAP_ADDREF(this, mRawPtr);
     891                 :           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
     892                 :         }
     893                 : 
     894                 :       nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
     895                 :             : nsCOMPtr_base(aSmartPtr.mRawPtr)
     896                 :           // construct from |dont_AddRef(expr)|
     897                 :         {
     898                 :           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
     899                 :         }
     900                 : 
     901               0 :       nsCOMPtr( const nsQueryInterface qi )
     902               0 :             : nsCOMPtr_base(0)
     903                 :           // assign from |do_QueryInterface(expr)|
     904                 :         {
     905                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     906               0 :           assign_from_qi(qi, NS_GET_IID(nsISupports));
     907               0 :         }
     908                 : 
     909                 :       nsCOMPtr( const nsQueryInterfaceWithError& qi )
     910                 :             : nsCOMPtr_base(0)
     911                 :           // assign from |do_QueryInterface(expr, &rv)|
     912                 :         {
     913                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     914                 :           assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
     915                 :         }
     916                 : 
     917                 :       nsCOMPtr( const nsGetServiceByCID gs )
     918                 :             : nsCOMPtr_base(0)
     919                 :           // assign from |do_GetService(cid_expr)|
     920                 :         {
     921                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     922                 :           assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
     923                 :         }
     924                 : 
     925                 :       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
     926                 :             : nsCOMPtr_base(0)
     927                 :           // assign from |do_GetService(cid_expr, &rv)|
     928                 :         {
     929                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     930                 :           assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
     931                 :         }
     932                 : 
     933                 :       nsCOMPtr( const nsGetServiceByContractID gs )
     934                 :             : nsCOMPtr_base(0)
     935                 :           // assign from |do_GetService(contractid_expr)|
     936                 :         {
     937                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     938                 :           assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
     939                 :         }
     940                 : 
     941                 :       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
     942                 :             : nsCOMPtr_base(0)
     943                 :           // assign from |do_GetService(contractid_expr, &rv)|
     944                 :         {
     945                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     946                 :           assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
     947                 :         }
     948                 : 
     949                 :       nsCOMPtr( const nsCOMPtr_helper& helper )
     950                 :             : nsCOMPtr_base(0)
     951                 :           // ...and finally, anything else we might need to construct from
     952                 :           //  can exploit the |nsCOMPtr_helper| facility
     953                 :         {
     954                 :           NSCAP_LOG_ASSIGNMENT(this, 0);
     955                 :           assign_from_helper(helper, NS_GET_IID(nsISupports));
     956                 :         }
     957                 : 
     958                 : 
     959                 :         // Assignment operators
     960                 : 
     961                 :       nsCOMPtr<nsISupports>&
     962                 :       operator=( const nsCOMPtr<nsISupports>& rhs )
     963                 :           // copy assignment operator
     964                 :         {
     965                 :           assign_with_AddRef(rhs.mRawPtr);
     966                 :           return *this;
     967                 :         }
     968                 : 
     969                 :       nsCOMPtr<nsISupports>&
     970                 :       operator=( nsISupports* rhs )
     971                 :           // assign from a raw pointer (of the right type)
     972                 :         {
     973                 :           assign_with_AddRef(rhs);
     974                 :           return *this;
     975                 :         }
     976                 : 
     977                 :       nsCOMPtr<nsISupports>&
     978                 :       operator=( const already_AddRefed<nsISupports>& rhs )
     979                 :           // assign from |dont_AddRef(expr)|
     980                 :         {
     981                 :           assign_assuming_AddRef(rhs.mRawPtr);
     982                 :           return *this;
     983                 :         }
     984                 : 
     985                 :       nsCOMPtr<nsISupports>&
     986                 :       operator=( const nsQueryInterface rhs )
     987                 :           // assign from |do_QueryInterface(expr)|
     988                 :         {
     989                 :           assign_from_qi(rhs, NS_GET_IID(nsISupports));
     990                 :           return *this;
     991                 :         }
     992                 : 
     993                 :       nsCOMPtr<nsISupports>&
     994                 :       operator=( const nsQueryInterfaceWithError& rhs )
     995                 :           // assign from |do_QueryInterface(expr, &rv)|
     996                 :         {
     997                 :           assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
     998                 :           return *this;
     999                 :         }
    1000                 : 
    1001                 :       nsCOMPtr<nsISupports>&
    1002                 :       operator=( const nsGetServiceByCID rhs )
    1003                 :           // assign from |do_GetService(cid_expr)|
    1004                 :         {
    1005                 :           assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
    1006                 :           return *this;
    1007                 :         }
    1008                 : 
    1009                 :       nsCOMPtr<nsISupports>&
    1010                 :       operator=( const nsGetServiceByCIDWithError& rhs )
    1011                 :           // assign from |do_GetService(cid_expr, &rv)|
    1012                 :         {
    1013                 :           assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
    1014                 :           return *this;
    1015                 :         }
    1016                 : 
    1017                 :       nsCOMPtr<nsISupports>&
    1018                 :       operator=( const nsGetServiceByContractID rhs )
    1019                 :           // assign from |do_GetService(contractid_expr)|
    1020                 :         {
    1021                 :           assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
    1022                 :           return *this;
    1023                 :         }
    1024                 : 
    1025                 :       nsCOMPtr<nsISupports>&
    1026                 :       operator=( const nsGetServiceByContractIDWithError& rhs )
    1027                 :           // assign from |do_GetService(contractid_expr, &rv)|
    1028                 :         {
    1029                 :           assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
    1030                 :           return *this;
    1031                 :         }
    1032                 : 
    1033                 :       nsCOMPtr<nsISupports>&
    1034                 :       operator=( const nsCOMPtr_helper& rhs )
    1035                 :           // ...and finally, anything else we might need to assign from
    1036                 :           //  can exploit the |nsCOMPtr_helper| facility.
    1037                 :         {
    1038                 :           assign_from_helper(rhs, NS_GET_IID(nsISupports));
    1039                 :           return *this;
    1040                 :         }
    1041                 : 
    1042                 :       void
    1043                 :       swap( nsCOMPtr<nsISupports>& rhs )
    1044                 :           // ...exchange ownership with |rhs|; can save a pair of refcount operations
    1045                 :         {
    1046                 :           nsISupports* temp = rhs.mRawPtr;
    1047                 :           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
    1048                 :           NSCAP_LOG_ASSIGNMENT(this, temp);
    1049                 :           NSCAP_LOG_RELEASE(this, mRawPtr);
    1050                 :           NSCAP_LOG_RELEASE(&rhs, temp);
    1051                 :           rhs.mRawPtr = mRawPtr;
    1052                 :           mRawPtr = temp;
    1053                 :         }
    1054                 : 
    1055                 :       void
    1056                 :       swap( nsISupports*& rhs )
    1057                 :           // ...exchange ownership with |rhs|; can save a pair of refcount operations
    1058                 :         {
    1059                 :           nsISupports* temp = rhs;
    1060                 :           NSCAP_LOG_ASSIGNMENT(this, temp);
    1061                 :           NSCAP_LOG_RELEASE(this, mRawPtr);
    1062                 :           rhs = mRawPtr;
    1063                 :           mRawPtr = temp;
    1064                 :         }
    1065                 : 
    1066                 :       already_AddRefed<nsISupports>
    1067                 :       forget()
    1068                 :           // return the value of mRawPtr and null out mRawPtr. Useful for
    1069                 :           // already_AddRefed return values.
    1070                 :         {
    1071                 :           nsISupports* temp = 0;
    1072                 :           swap(temp);
    1073                 :           return temp;
    1074                 :         }
    1075                 : 
    1076                 :       void
    1077                 :       forget( nsISupports** rhs NS_OUTPARAM )
    1078                 :           // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
    1079                 :           // Useful to avoid unnecessary AddRef/Release pairs with "out"
    1080                 :           // parameters.
    1081                 :         {
    1082                 :           NS_ASSERTION(rhs, "Null pointer passed to forget!");
    1083                 :           *rhs = 0;
    1084                 :           swap(*rhs);
    1085                 :         }
    1086                 : 
    1087                 :         // Other pointer operators
    1088                 : 
    1089                 :       nsISupports*
    1090               0 :       get() const
    1091                 :           /*
    1092                 :             Prefer the implicit conversion provided automatically by
    1093                 :             |operator nsISupports*() const|.
    1094                 :             Use |get()| to resolve ambiguity or to get a castable pointer.
    1095                 :           */
    1096                 :         {
    1097               0 :           return reinterpret_cast<nsISupports*>(mRawPtr);
    1098                 :         }
    1099                 : 
    1100               0 :       operator nsISupports*() const
    1101                 :           /*
    1102                 :             ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it
    1103                 :             is used in a context where a raw pointer is expected.  It is this operator
    1104                 :             that makes an |nsCOMPtr| substitutable for a raw pointer.
    1105                 : 
    1106                 :             Prefer the implicit use of this operator to calling |get()|, except where
    1107                 :             necessary to resolve ambiguity.
    1108                 :           */
    1109                 :         {
    1110               0 :           return get();
    1111                 :         }
    1112                 : 
    1113                 :       nsISupports*
    1114                 :       operator->() const
    1115                 :         {
    1116                 :           NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
    1117                 :           return get();
    1118                 :         }
    1119                 : 
    1120                 :       nsCOMPtr<nsISupports>*
    1121               0 :       get_address()
    1122                 :           // This is not intended to be used by clients.  See |address_of|
    1123                 :           // below.
    1124                 :         {
    1125               0 :           return this;
    1126                 :         }
    1127                 : 
    1128                 :       const nsCOMPtr<nsISupports>*
    1129                 :       get_address() const
    1130                 :           // This is not intended to be used by clients.  See |address_of|
    1131                 :           // below.
    1132                 :         {
    1133                 :           return this;
    1134                 :         }
    1135                 : 
    1136                 :     public:
    1137                 : 
    1138                 :       nsISupports&
    1139                 :       operator*() const
    1140                 :         {
    1141                 :           NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
    1142                 :           return *get();
    1143                 :         }
    1144                 : 
    1145                 :       nsISupports**
    1146               0 :       StartAssignment()
    1147                 :         {
    1148                 : #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
    1149               0 :           return reinterpret_cast<nsISupports**>(begin_assignment());
    1150                 : #else
    1151                 :           assign_assuming_AddRef(0);
    1152                 :           return reinterpret_cast<nsISupports**>(&mRawPtr);
    1153                 : #endif
    1154                 :         }
    1155                 :   };
    1156                 : 
    1157                 : #ifndef NSCAP_FEATURE_USE_BASE
    1158                 : template <class T>
    1159                 : void
    1160               0 : nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
    1161                 :   {
    1162               0 :     if ( rawPtr )
    1163               0 :       NSCAP_ADDREF(this, rawPtr);
    1164               0 :     assign_assuming_AddRef(reinterpret_cast<T*>(rawPtr));
    1165               0 :   }
    1166                 : 
    1167                 : template <class T>
    1168                 : void
    1169          149896 : nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
    1170                 :   {
    1171                 :     void* newRawPtr;
    1172          149896 :     if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
    1173               0 :       newRawPtr = 0;
    1174          149896 :     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1175          149896 :   }
    1176                 : 
    1177                 : template <class T>
    1178                 : void
    1179               1 : nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
    1180                 :   {
    1181                 :     void* newRawPtr;
    1182               1 :     if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
    1183               0 :       newRawPtr = 0;
    1184               1 :     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1185               1 :   }
    1186                 : 
    1187                 : template <class T>
    1188                 : void
    1189                 : nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
    1190                 :   {
    1191                 :     void* newRawPtr;
    1192                 :     if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
    1193                 :       newRawPtr = 0;
    1194                 :     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1195                 :   }
    1196                 : 
    1197                 : template <class T>
    1198                 : void
    1199                 : nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
    1200                 :   {
    1201                 :     void* newRawPtr;
    1202                 :     if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
    1203                 :       newRawPtr = 0;
    1204                 :     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1205                 :   }
    1206                 : 
    1207                 : template <class T>
    1208                 : void
    1209          167846 : nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
    1210                 :   {
    1211                 :     void* newRawPtr;
    1212          167846 :     if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
    1213            8047 :       newRawPtr = 0;
    1214          167846 :     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1215          167846 :   }
    1216                 : 
    1217                 : template <class T>
    1218                 : void
    1219             234 : nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
    1220                 :   {
    1221                 :     void* newRawPtr;
    1222             234 :     if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
    1223               0 :       newRawPtr = 0;
    1224             234 :     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1225             234 :   }
    1226                 : 
    1227                 : template <class T>
    1228                 : void
    1229                 : nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
    1230                 :   {
    1231                 :     void* newRawPtr;
    1232                 :     if ( NS_FAILED( helper(aIID, &newRawPtr) ) )
    1233                 :       newRawPtr = 0;
    1234                 :     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1235                 :   }
    1236                 : 
    1237                 : template <class T>
    1238                 : void**
    1239          149897 : nsCOMPtr<T>::begin_assignment()
    1240                 :   {
    1241          149897 :     assign_assuming_AddRef(0);
    1242                 :     union { T** mT; void** mVoid; } result;
    1243          149897 :     result.mT = &mRawPtr;
    1244          149897 :     return result.mVoid;
    1245                 :   }
    1246                 : #endif
    1247                 : 
    1248                 : template <class T>
    1249                 : inline
    1250                 : nsCOMPtr<T>*
    1251          149896 : address_of( nsCOMPtr<T>& aPtr )
    1252                 :   {
    1253          149896 :     return aPtr.get_address();
    1254                 :   }
    1255                 : 
    1256                 : template <class T>
    1257                 : inline
    1258                 : const nsCOMPtr<T>*
    1259                 : address_of( const nsCOMPtr<T>& aPtr )
    1260                 :   {
    1261                 :     return aPtr.get_address();
    1262                 :   }
    1263                 : 
    1264                 : template <class T>
    1265                 : class nsGetterAddRefs
    1266                 :     /*
    1267                 :       ...
    1268                 : 
    1269                 :       This class is designed to be used for anonymous temporary objects in the
    1270                 :       argument list of calls that return COM interface pointers, e.g.,
    1271                 : 
    1272                 :         nsCOMPtr<IFoo> fooP;
    1273                 :         ...->QueryInterface(iid, getter_AddRefs(fooP))
    1274                 : 
    1275                 :       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_AddRefs()| instead.
    1276                 : 
    1277                 :       When initialized with a |nsCOMPtr|, as in the example above, it returns
    1278                 :       a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
    1279                 :       case) can fill in.
    1280                 : 
    1281                 :       This type should be a nested class inside |nsCOMPtr<T>|.
    1282                 :     */
    1283                 :   {
    1284                 :     public:
    1285                 :       explicit
    1286          149897 :       nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
    1287          149897 :           : mTargetSmartPtr(aSmartPtr)
    1288                 :         {
    1289                 :           // nothing else to do
    1290          149897 :         }
    1291                 : 
    1292                 : #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
    1293          149897 :      ~nsGetterAddRefs()
    1294                 :         {
    1295                 : #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
    1296          149897 :           NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
    1297                 : #endif
    1298                 : 
    1299                 : #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
    1300          149897 :           mTargetSmartPtr.Assert_NoQueryNeeded();
    1301                 : #endif
    1302          149897 :         }
    1303                 : #endif
    1304                 : 
    1305               0 :       operator void**()
    1306                 :         {
    1307               0 :           return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
    1308                 :         }
    1309                 : 
    1310                 :       operator nsISupports**()
    1311                 :         {
    1312                 :           return reinterpret_cast<nsISupports**>(mTargetSmartPtr.StartAssignment());
    1313                 :         }
    1314                 : 
    1315          149897 :       operator T**()
    1316                 :         {
    1317          149897 :           return mTargetSmartPtr.StartAssignment();
    1318                 :         }
    1319                 : 
    1320                 :       T*&
    1321                 :       operator*()
    1322                 :         {
    1323                 :           return *(mTargetSmartPtr.StartAssignment());
    1324                 :         }
    1325                 : 
    1326                 :     private:
    1327                 :       nsCOMPtr<T>& mTargetSmartPtr;
    1328                 :   };
    1329                 : 
    1330                 : 
    1331                 : template <>
    1332                 : class nsGetterAddRefs<nsISupports>
    1333                 :   {
    1334                 :     public:
    1335                 :       explicit
    1336               0 :       nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
    1337               0 :           : mTargetSmartPtr(aSmartPtr)
    1338                 :         {
    1339                 :           // nothing else to do
    1340               0 :         }
    1341                 : 
    1342                 : #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
    1343               0 :      ~nsGetterAddRefs()
    1344                 :         {
    1345               0 :           NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
    1346               0 :         }
    1347                 : #endif
    1348                 : 
    1349                 :       operator void**()
    1350                 :         {
    1351                 :           return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
    1352                 :         }
    1353                 : 
    1354               0 :       operator nsISupports**()
    1355                 :         {
    1356               0 :           return mTargetSmartPtr.StartAssignment();
    1357                 :         }
    1358                 : 
    1359                 :       nsISupports*&
    1360                 :       operator*()
    1361                 :         {
    1362                 :           return *(mTargetSmartPtr.StartAssignment());
    1363                 :         }
    1364                 : 
    1365                 :     private:
    1366                 :       nsCOMPtr<nsISupports>& mTargetSmartPtr;
    1367                 :   };
    1368                 : 
    1369                 : 
    1370                 : template <class T>
    1371                 : inline
    1372                 : nsGetterAddRefs<T>
    1373          149897 : getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
    1374                 :     /*
    1375                 :       Used around a |nsCOMPtr| when 
    1376                 :       ...makes the class |nsGetterAddRefs<T>| invisible.
    1377                 :     */
    1378                 :   {
    1379          149897 :     return nsGetterAddRefs<T>(aSmartPtr);
    1380                 :   }
    1381                 : 
    1382                 : template <class T, class DestinationType>
    1383                 : inline
    1384                 : nsresult
    1385                 : CallQueryInterface( T* aSource, nsGetterAddRefs<DestinationType> aDestination )
    1386                 : {
    1387                 :     return CallQueryInterface(aSource,
    1388                 :                               static_cast<DestinationType**>(aDestination));
    1389                 : }
    1390                 : 
    1391                 : 
    1392                 :   // Comparing two |nsCOMPtr|s
    1393                 : 
    1394                 : template <class T, class U>
    1395                 : inline
    1396                 : bool
    1397               0 : operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
    1398                 :   {
    1399               0 :     return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
    1400                 :   }
    1401                 : 
    1402                 : 
    1403                 : template <class T, class U>
    1404                 : inline
    1405                 : bool
    1406                 : operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
    1407                 :   {
    1408                 :     return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
    1409                 :   }
    1410                 : 
    1411                 : 
    1412                 :   // Comparing an |nsCOMPtr| to a raw pointer
    1413                 : 
    1414                 : template <class T, class U>
    1415                 : inline
    1416                 : bool
    1417                 : operator==( const nsCOMPtr<T>& lhs, const U* rhs )
    1418                 :   {
    1419                 :     return static_cast<const T*>(lhs.get()) == rhs;
    1420                 :   }
    1421                 : 
    1422                 : template <class T, class U>
    1423                 : inline
    1424                 : bool
    1425                 : operator==( const U* lhs, const nsCOMPtr<T>& rhs )
    1426                 :   {
    1427                 :     return lhs == static_cast<const T*>(rhs.get());
    1428                 :   }
    1429                 : 
    1430                 : template <class T, class U>
    1431                 : inline
    1432                 : bool
    1433                 : operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
    1434                 :   {
    1435                 :     return static_cast<const T*>(lhs.get()) != rhs;
    1436                 :   }
    1437                 : 
    1438                 : template <class T, class U>
    1439                 : inline
    1440                 : bool
    1441                 : operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
    1442                 :   {
    1443                 :     return lhs != static_cast<const T*>(rhs.get());
    1444                 :   }
    1445                 : 
    1446                 :   // To avoid ambiguities caused by the presence of builtin |operator==|s
    1447                 :   // creating a situation where one of the |operator==| defined above
    1448                 :   // has a better conversion for one argument and the builtin has a
    1449                 :   // better conversion for the other argument, define additional
    1450                 :   // |operator==| without the |const| on the raw pointer.
    1451                 :   // See bug 65664 for details.
    1452                 : 
    1453                 : // This is defined by an autoconf test, but VC++ also has a bug that
    1454                 : // prevents us from using these.  (It also, fortunately, has the bug
    1455                 : // that we don't need them either.)
    1456                 : #if defined(_MSC_VER) && (_MSC_VER < 1310)
    1457                 : #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
    1458                 : #define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
    1459                 : #endif
    1460                 : #endif
    1461                 : 
    1462                 : #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
    1463                 : template <class T, class U>
    1464                 : inline
    1465                 : bool
    1466                 : operator==( const nsCOMPtr<T>& lhs, U* rhs )
    1467                 :   {
    1468                 :     return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
    1469                 :   }
    1470                 : 
    1471                 : template <class T, class U>
    1472                 : inline
    1473                 : bool
    1474                 : operator==( U* lhs, const nsCOMPtr<T>& rhs )
    1475                 :   {
    1476                 :     return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
    1477                 :   }
    1478                 : 
    1479                 : template <class T, class U>
    1480                 : inline
    1481                 : bool
    1482                 : operator!=( const nsCOMPtr<T>& lhs, U* rhs )
    1483                 :   {
    1484                 :     return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
    1485                 :   }
    1486                 : 
    1487                 : template <class T, class U>
    1488                 : inline
    1489                 : bool
    1490                 : operator!=( U* lhs, const nsCOMPtr<T>& rhs )
    1491                 :   {
    1492                 :     return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
    1493                 :   }
    1494                 : #endif
    1495                 : 
    1496                 : 
    1497                 : 
    1498                 :   // Comparing an |nsCOMPtr| to |0|
    1499                 : 
    1500                 : class NSCAP_Zero;
    1501                 : 
    1502                 : template <class T>
    1503                 : inline
    1504                 : bool
    1505                 : operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
    1506                 :     // specifically to allow |smartPtr == 0|
    1507                 :   {
    1508                 :     return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
    1509                 :   }
    1510                 : 
    1511                 : template <class T>
    1512                 : inline
    1513                 : bool
    1514                 : operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
    1515                 :     // specifically to allow |0 == smartPtr|
    1516                 :   {
    1517                 :     return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
    1518                 :   }
    1519                 : 
    1520                 : template <class T>
    1521                 : inline
    1522                 : bool
    1523                 : operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
    1524                 :     // specifically to allow |smartPtr != 0|
    1525                 :   {
    1526                 :     return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
    1527                 :   }
    1528                 : 
    1529                 : template <class T>
    1530                 : inline
    1531                 : bool
    1532                 : operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
    1533                 :     // specifically to allow |0 != smartPtr|
    1534                 :   {
    1535                 :     return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
    1536                 :   }
    1537                 : 
    1538                 : 
    1539                 : #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
    1540                 : 
    1541                 :   // We need to explicitly define comparison operators for `int'
    1542                 :   // because the compiler is lame.
    1543                 : 
    1544                 : template <class T>
    1545                 : inline
    1546                 : bool
    1547                 : operator==( const nsCOMPtr<T>& lhs, int rhs )
    1548                 :     // specifically to allow |smartPtr == 0|
    1549                 :   {
    1550                 :     return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
    1551                 :   }
    1552                 : 
    1553                 : template <class T>
    1554                 : inline
    1555                 : bool
    1556                 : operator==( int lhs, const nsCOMPtr<T>& rhs )
    1557                 :     // specifically to allow |0 == smartPtr|
    1558                 :   {
    1559                 :     return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
    1560                 :   }
    1561                 : 
    1562                 : #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
    1563                 : 
    1564                 :   // Comparing any two [XP]COM objects for identity
    1565                 : 
    1566                 : inline
    1567                 : bool
    1568                 : SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
    1569                 :   {
    1570                 :     return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
    1571                 :   }
    1572                 : 
    1573                 : 
    1574                 : 
    1575                 : template <class SourceType, class DestinationType>
    1576                 : inline
    1577                 : nsresult
    1578               0 : CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
    1579                 :   {
    1580               0 :     return CallQueryInterface(aSourcePtr.get(), aDestPtr);
    1581                 :   }
    1582                 : 
    1583                 : #endif // !defined(nsCOMPtr_h___)

Generated by: LCOV version 1.7