parser/html/nsHtml5RefPtr.h

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef nsHtml5RefPtr_h
     7 #define nsHtml5RefPtr_h
     9 #include "nsThreadUtils.h"
    11 template <class T>
    12 class nsHtml5RefPtrReleaser : public nsRunnable
    13   {
    14     private:
    15       T* mPtr;
    16     public:
    17       nsHtml5RefPtrReleaser(T* aPtr)
    18           : mPtr(aPtr)
    19         {}
    20       NS_IMETHODIMP Run()
    21         {
    22           mPtr->Release();
    23           return NS_OK;
    24         }
    25   };
    27 // template <class T> class nsHtml5RefPtrGetterAddRefs;
    29 /**
    30  * Like nsRefPtr except release is proxied to the main thread. Mostly copied
    31  * from nsRefPtr.
    32  */
    33 template <class T>
    34 class nsHtml5RefPtr
    35   {
    36     private:
    38       void
    39       assign_with_AddRef( T* rawPtr )
    40         {
    41           if ( rawPtr )
    42             rawPtr->AddRef();
    43           assign_assuming_AddRef(rawPtr);
    44         }
    46       void**
    47       begin_assignment()
    48         {
    49           assign_assuming_AddRef(0);
    50           return reinterpret_cast<void**>(&mRawPtr);
    51         }
    53       void
    54       assign_assuming_AddRef( T* newPtr )
    55         {
    56           T* oldPtr = mRawPtr;
    57           mRawPtr = newPtr;
    58           if ( oldPtr )
    59             release(oldPtr);
    60         }
    62       void
    63       release( T* aPtr )
    64         {
    65           nsCOMPtr<nsIRunnable> releaser = new nsHtml5RefPtrReleaser<T>(aPtr);
    66           if (NS_FAILED(NS_DispatchToMainThread(releaser))) 
    67             {
    68               NS_WARNING("Failed to dispatch releaser event.");
    69             }
    70         }
    72     private:
    73       T* mRawPtr;
    75     public:
    76       typedef T element_type;
    78      ~nsHtml5RefPtr()
    79         {
    80           if ( mRawPtr )
    81             release(mRawPtr);
    82         }
    84         // Constructors
    86       nsHtml5RefPtr()
    87             : mRawPtr(0)
    88           // default constructor
    89         {
    90         }
    92       nsHtml5RefPtr( const nsHtml5RefPtr<T>& aSmartPtr )
    93             : mRawPtr(aSmartPtr.mRawPtr)
    94           // copy-constructor
    95         {
    96           if ( mRawPtr )
    97             mRawPtr->AddRef();
    98         }
   100       nsHtml5RefPtr( T* aRawPtr )
   101             : mRawPtr(aRawPtr)
   102           // construct from a raw pointer (of the right type)
   103         {
   104           if ( mRawPtr )
   105             mRawPtr->AddRef();
   106         }
   108       nsHtml5RefPtr( const already_AddRefed<T>& aSmartPtr )
   109             : mRawPtr(aSmartPtr.mRawPtr)
   110           // construct from |dont_AddRef(expr)|
   111         {
   112         }
   114         // Assignment operators
   116       nsHtml5RefPtr<T>&
   117       operator=( const nsHtml5RefPtr<T>& rhs )
   118           // copy assignment operator
   119         {
   120           assign_with_AddRef(rhs.mRawPtr);
   121           return *this;
   122         }
   124       nsHtml5RefPtr<T>&
   125       operator=( T* rhs )
   126           // assign from a raw pointer (of the right type)
   127         {
   128           assign_with_AddRef(rhs);
   129           return *this;
   130         }
   132       nsHtml5RefPtr<T>&
   133       operator=( const already_AddRefed<T>& rhs )
   134           // assign from |dont_AddRef(expr)|
   135         {
   136           assign_assuming_AddRef(rhs.mRawPtr);
   137           return *this;
   138         }
   140         // Other pointer operators
   142       void
   143       swap( nsHtml5RefPtr<T>& rhs )
   144           // ...exchange ownership with |rhs|; can save a pair of refcount operations
   145         {
   146           T* temp = rhs.mRawPtr;
   147           rhs.mRawPtr = mRawPtr;
   148           mRawPtr = temp;
   149         }
   151       void
   152       swap( T*& rhs )
   153           // ...exchange ownership with |rhs|; can save a pair of refcount operations
   154         {
   155           T* temp = rhs;
   156           rhs = mRawPtr;
   157           mRawPtr = temp;
   158         }
   160       already_AddRefed<T>
   161       forget()
   162           // return the value of mRawPtr and null out mRawPtr. Useful for
   163           // already_AddRefed return values.
   164         {
   165           T* temp = 0;
   166           swap(temp);
   167           return temp;
   168         }
   170       template <typename I>
   171       void
   172       forget( I** rhs)
   173           // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
   174           // Useful to avoid unnecessary AddRef/Release pairs with "out"
   175           // parameters where rhs bay be a T** or an I** where I is a base class
   176           // of T.
   177         {
   178           NS_ASSERTION(rhs, "Null pointer passed to forget!");
   179           *rhs = mRawPtr;
   180           mRawPtr = 0;
   181         }
   183       T*
   184       get() const
   185           /*
   186             Prefer the implicit conversion provided automatically by |operator T*() const|.
   187             Use |get()| to resolve ambiguity or to get a castable pointer.
   188           */
   189         {
   190           return const_cast<T*>(mRawPtr);
   191         }
   193       operator T*() const
   194           /*
   195             ...makes an |nsHtml5RefPtr| act like its underlying raw pointer type whenever it
   196             is used in a context where a raw pointer is expected.  It is this operator
   197             that makes an |nsHtml5RefPtr| substitutable for a raw pointer.
   199             Prefer the implicit use of this operator to calling |get()|, except where
   200             necessary to resolve ambiguity.
   201           */
   202         {
   203           return get();
   204         }
   206       T*
   207       operator->() const
   208         {
   209           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsHtml5RefPtr with operator->().");
   210           return get();
   211         }
   213       nsHtml5RefPtr<T>*
   214       get_address()
   215           // This is not intended to be used by clients.  See |address_of|
   216           // below.
   217         {
   218           return this;
   219         }
   221       const nsHtml5RefPtr<T>*
   222       get_address() const
   223           // This is not intended to be used by clients.  See |address_of|
   224           // below.
   225         {
   226           return this;
   227         }
   229     public:
   230       T&
   231       operator*() const
   232         {
   233           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsHtml5RefPtr with operator*().");
   234           return *get();
   235         }
   237       T**
   238       StartAssignment()
   239         {
   240 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
   241           return reinterpret_cast<T**>(begin_assignment());
   242 #else
   243           assign_assuming_AddRef(0);
   244           return reinterpret_cast<T**>(&mRawPtr);
   245 #endif
   246         }
   247   };
   249 template <class T>
   250 inline
   251 nsHtml5RefPtr<T>*
   252 address_of( nsHtml5RefPtr<T>& aPtr )
   253   {
   254     return aPtr.get_address();
   255   }
   257 template <class T>
   258 inline
   259 const nsHtml5RefPtr<T>*
   260 address_of( const nsHtml5RefPtr<T>& aPtr )
   261   {
   262     return aPtr.get_address();
   263   }
   265 template <class T>
   266 class nsHtml5RefPtrGetterAddRefs
   267     /*
   268       ...
   270       This class is designed to be used for anonymous temporary objects in the
   271       argument list of calls that return COM interface pointers, e.g.,
   273         nsHtml5RefPtr<IFoo> fooP;
   274         ...->GetAddRefedPointer(getter_AddRefs(fooP))
   276       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_AddRefs()| instead.
   278       When initialized with a |nsHtml5RefPtr|, as in the example above, it returns
   279       a |void**|, a |T**|, or an |nsISupports**| as needed, that the
   280       outer call (|GetAddRefedPointer| in this case) can fill in.
   282       This type should be a nested class inside |nsHtml5RefPtr<T>|.
   283     */
   284   {
   285     public:
   286       explicit
   287       nsHtml5RefPtrGetterAddRefs( nsHtml5RefPtr<T>& aSmartPtr )
   288           : mTargetSmartPtr(aSmartPtr)
   289         {
   290           // nothing else to do
   291         }
   293       operator void**()
   294         {
   295           return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
   296         }
   298       operator T**()
   299         {
   300           return mTargetSmartPtr.StartAssignment();
   301         }
   303       T*&
   304       operator*()
   305         {
   306           return *(mTargetSmartPtr.StartAssignment());
   307         }
   309     private:
   310       nsHtml5RefPtr<T>& mTargetSmartPtr;
   311   };
   313 template <class T>
   314 inline
   315 nsHtml5RefPtrGetterAddRefs<T>
   316 getter_AddRefs( nsHtml5RefPtr<T>& aSmartPtr )
   317     /*
   318       Used around a |nsHtml5RefPtr| when 
   319       ...makes the class |nsHtml5RefPtrGetterAddRefs<T>| invisible.
   320     */
   321   {
   322     return nsHtml5RefPtrGetterAddRefs<T>(aSmartPtr);
   323   }
   327   // Comparing two |nsHtml5RefPtr|s
   329 template <class T, class U>
   330 inline
   331 bool
   332 operator==( const nsHtml5RefPtr<T>& lhs, const nsHtml5RefPtr<U>& rhs )
   333   {
   334     return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
   335   }
   338 template <class T, class U>
   339 inline
   340 bool
   341 operator!=( const nsHtml5RefPtr<T>& lhs, const nsHtml5RefPtr<U>& rhs )
   342   {
   343     return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
   344   }
   347   // Comparing an |nsHtml5RefPtr| to a raw pointer
   349 template <class T, class U>
   350 inline
   351 bool
   352 operator==( const nsHtml5RefPtr<T>& lhs, const U* rhs )
   353   {
   354     return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs);
   355   }
   357 template <class T, class U>
   358 inline
   359 bool
   360 operator==( const U* lhs, const nsHtml5RefPtr<T>& rhs )
   361   {
   362     return static_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
   363   }
   365 template <class T, class U>
   366 inline
   367 bool
   368 operator!=( const nsHtml5RefPtr<T>& lhs, const U* rhs )
   369   {
   370     return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs);
   371   }
   373 template <class T, class U>
   374 inline
   375 bool
   376 operator!=( const U* lhs, const nsHtml5RefPtr<T>& rhs )
   377   {
   378     return static_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
   379   }
   381   // To avoid ambiguities caused by the presence of builtin |operator==|s
   382   // creating a situation where one of the |operator==| defined above
   383   // has a better conversion for one argument and the builtin has a
   384   // better conversion for the other argument, define additional
   385   // |operator==| without the |const| on the raw pointer.
   386   // See bug 65664 for details.
   388 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
   389 template <class T, class U>
   390 inline
   391 bool
   392 operator==( const nsHtml5RefPtr<T>& lhs, U* rhs )
   393   {
   394     return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
   395   }
   397 template <class T, class U>
   398 inline
   399 bool
   400 operator==( U* lhs, const nsHtml5RefPtr<T>& rhs )
   401   {
   402     return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
   403   }
   405 template <class T, class U>
   406 inline
   407 bool
   408 operator!=( const nsHtml5RefPtr<T>& lhs, U* rhs )
   409   {
   410     return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
   411   }
   413 template <class T, class U>
   414 inline
   415 bool
   416 operator!=( U* lhs, const nsHtml5RefPtr<T>& rhs )
   417   {
   418     return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
   419   }
   420 #endif
   424   // Comparing an |nsHtml5RefPtr| to |0|
   426 template <class T>
   427 inline
   428 bool
   429 operator==( const nsHtml5RefPtr<T>& lhs, NSCAP_Zero* rhs )
   430     // specifically to allow |smartPtr == 0|
   431   {
   432     return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
   433   }
   435 template <class T>
   436 inline
   437 bool
   438 operator==( NSCAP_Zero* lhs, const nsHtml5RefPtr<T>& rhs )
   439     // specifically to allow |0 == smartPtr|
   440   {
   441     return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
   442   }
   444 template <class T>
   445 inline
   446 bool
   447 operator!=( const nsHtml5RefPtr<T>& lhs, NSCAP_Zero* rhs )
   448     // specifically to allow |smartPtr != 0|
   449   {
   450     return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
   451   }
   453 template <class T>
   454 inline
   455 bool
   456 operator!=( NSCAP_Zero* lhs, const nsHtml5RefPtr<T>& rhs )
   457     // specifically to allow |0 != smartPtr|
   458   {
   459     return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
   460   }
   463 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
   465   // We need to explicitly define comparison operators for `int'
   466   // because the compiler is lame.
   468 template <class T>
   469 inline
   470 bool
   471 operator==( const nsHtml5RefPtr<T>& lhs, int rhs )
   472     // specifically to allow |smartPtr == 0|
   473   {
   474     return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
   475   }
   477 template <class T>
   478 inline
   479 bool
   480 operator==( int lhs, const nsHtml5RefPtr<T>& rhs )
   481     // specifically to allow |0 == smartPtr|
   482   {
   483     return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
   484   }
   486 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
   488 #endif // !defined(nsHtml5RefPtr_h)

mercurial