LCOV - code coverage report
Current view: top level - xpcom/base - StaticPtr.h (source / functions) Hit Total Coverage
Test: output.info Lines: 56 61 91.8 %
Date: 2017-07-14 16:53:18 Functions: 703 1180 59.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_StaticPtr_h
       8             : #define mozilla_StaticPtr_h
       9             : 
      10             : #include "mozilla/AlreadyAddRefed.h"
      11             : #include "mozilla/Assertions.h"
      12             : #include "mozilla/Attributes.h"
      13             : #include "mozilla/RefPtr.h"
      14             : 
      15             : namespace mozilla {
      16             : 
      17             : /**
      18             :  * StaticAutoPtr and StaticRefPtr are like nsAutoPtr and nsRefPtr, except they
      19             :  * are suitable for use as global variables.
      20             :  *
      21             :  * In particular, a global instance of Static{Auto,Ref}Ptr doesn't cause the
      22             :  * compiler to emit  a static initializer (in release builds, anyway).
      23             :  *
      24             :  * In order to accomplish this, Static{Auto,Ref}Ptr must have a trivial
      25             :  * constructor and destructor.  As a consequence, it cannot initialize its raw
      26             :  * pointer to 0 on construction, and it cannot delete/release its raw pointer
      27             :  * upon destruction.
      28             :  *
      29             :  * Since the compiler guarantees that all global variables are initialized to
      30             :  * 0, these trivial constructors are safe.  Since we rely on this, the clang
      31             :  * plugin, run as part of our "static analysis" builds, makes it a compile-time
      32             :  * error to use Static{Auto,Ref}Ptr as anything except a global variable.
      33             :  *
      34             :  * Static{Auto,Ref}Ptr have a limited interface as compared to ns{Auto,Ref}Ptr;
      35             :  * this is intentional, since their range of acceptable uses is smaller.
      36             :  */
      37             : 
      38             : template<class T>
      39             : class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticAutoPtr
      40             : {
      41             : public:
      42             :   // In debug builds, check that mRawPtr is initialized for us as we expect
      43             :   // by the compiler.  In non-debug builds, don't declare a constructor
      44             :   // so that the compiler can see that the constructor is trivial.
      45             : #ifdef DEBUG
      46         195 :   StaticAutoPtr()
      47             :   {
      48         195 :     MOZ_ASSERT(!mRawPtr);
      49         195 :   }
      50             : #endif
      51             : 
      52          68 :   StaticAutoPtr<T>& operator=(T* aRhs)
      53             :   {
      54          68 :     Assign(aRhs);
      55          68 :     return *this;
      56             :   }
      57             : 
      58       21372 :   T* get() const { return mRawPtr; }
      59             : 
      60        8461 :   operator T*() const { return get(); }
      61             : 
      62       11489 :   T* operator->() const
      63             :   {
      64       11489 :     MOZ_ASSERT(mRawPtr);
      65       11489 :     return get();
      66             :   }
      67             : 
      68        1140 :   T& operator*() const { return *get(); }
      69             : 
      70           0 :   T* forget()
      71             :   {
      72           0 :     T* temp = mRawPtr;
      73           0 :     mRawPtr = nullptr;
      74           0 :     return temp;
      75             :   }
      76             : 
      77             : private:
      78             :   // Disallow copy constructor, but only in debug mode.  We only define
      79             :   // a default constructor in debug mode (see above); if we declared
      80             :   // this constructor always, the compiler wouldn't generate a trivial
      81             :   // default constructor for us in non-debug mode.
      82             : #ifdef DEBUG
      83             :   StaticAutoPtr(StaticAutoPtr<T>& aOther);
      84             : #endif
      85             : 
      86          68 :   void Assign(T* aNewPtr)
      87             :   {
      88          68 :     MOZ_ASSERT(!aNewPtr || mRawPtr != aNewPtr);
      89          68 :     T* oldPtr = mRawPtr;
      90          68 :     mRawPtr = aNewPtr;
      91          57 :     delete oldPtr;
      92          68 :   }
      93             : 
      94             :   T* mRawPtr;
      95             : };
      96             : 
      97             : template<class T>
      98             : class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticRefPtr
      99             : {
     100             : public:
     101             :   // In debug builds, check that mRawPtr is initialized for us as we expect
     102             :   // by the compiler.  In non-debug builds, don't declare a constructor
     103             :   // so that the compiler can see that the constructor is trivial.
     104             : #ifdef DEBUG
     105         423 :   StaticRefPtr()
     106             :   {
     107         423 :     MOZ_ASSERT(!mRawPtr);
     108         423 :   }
     109             : #endif
     110             : 
     111         139 :   StaticRefPtr<T>& operator=(T* aRhs)
     112             :   {
     113         139 :     AssignWithAddref(aRhs);
     114         139 :     return *this;
     115             :   }
     116             : 
     117             :   StaticRefPtr<T>& operator=(const StaticRefPtr<T>& aRhs)
     118             :   {
     119             :     return (this = aRhs.mRawPtr);
     120             :   }
     121             : 
     122             :   StaticRefPtr<T>& operator=(already_AddRefed<T>& aRhs)
     123             :   {
     124             :     AssignAssumingAddRef(aRhs.take());
     125             :     return *this;
     126             :   }
     127             : 
     128           9 :   StaticRefPtr<T>& operator=(already_AddRefed<T>&& aRhs)
     129             :   {
     130           9 :     AssignAssumingAddRef(aRhs.take());
     131           9 :     return *this;
     132             :   }
     133             : 
     134             :   already_AddRefed<T>
     135           2 :   forget()
     136             :   {
     137           2 :     T* temp = mRawPtr;
     138           2 :     mRawPtr = nullptr;
     139           2 :     return already_AddRefed<T>(temp);
     140             :   }
     141             : 
     142       67836 :   T* get() const { return mRawPtr; }
     143             : 
     144       41647 :   operator T*() const { return get(); }
     145             : 
     146       23456 :   T* operator->() const
     147             :   {
     148       23456 :     MOZ_ASSERT(mRawPtr);
     149       23456 :     return get();
     150             :   }
     151             : 
     152           9 :   T& operator*() const { return *get(); }
     153             : 
     154             : private:
     155         139 :   void AssignWithAddref(T* aNewPtr)
     156             :   {
     157         139 :     if (aNewPtr) {
     158         122 :       aNewPtr->AddRef();
     159             :     }
     160         139 :     AssignAssumingAddRef(aNewPtr);
     161         139 :   }
     162             : 
     163         148 :   void AssignAssumingAddRef(T* aNewPtr)
     164             :   {
     165         148 :     T* oldPtr = mRawPtr;
     166         148 :     mRawPtr = aNewPtr;
     167         148 :     if (oldPtr) {
     168           5 :       oldPtr->Release();
     169             :     }
     170         148 :   }
     171             : 
     172             :   T* MOZ_OWNING_REF mRawPtr;
     173             : };
     174             : 
     175             : namespace StaticPtr_internal {
     176             : class Zero;
     177             : } // namespace StaticPtr_internal
     178             : 
     179             : #define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \
     180             :   template<__VA_ARGS__>                                        \
     181             :   inline bool                                                  \
     182             :   operator==(type1 lhs, type2 rhs)                             \
     183             :   {                                                            \
     184             :     return eq_fn;                                              \
     185             :   }                                                            \
     186             :                                                                \
     187             :   template<__VA_ARGS__>                                        \
     188             :   inline bool                                                  \
     189             :   operator==(type2 lhs, type1 rhs)                             \
     190             :   {                                                            \
     191             :     return rhs == lhs;                                         \
     192             :   }                                                            \
     193             :                                                                \
     194             :   template<__VA_ARGS__>                                        \
     195             :   inline bool                                                  \
     196             :   operator!=(type1 lhs, type2 rhs)                             \
     197             :   {                                                            \
     198             :     return !(lhs == rhs);                                      \
     199             :   }                                                            \
     200             :                                                                \
     201             :   template<__VA_ARGS__>                                        \
     202             :   inline bool                                                  \
     203             :   operator!=(type2 lhs, type1 rhs)                             \
     204             :   {                                                            \
     205             :     return !(lhs == rhs);                                      \
     206             :   }
     207             : 
     208             : // StaticAutoPtr (in)equality operators
     209             : 
     210             : template<class T, class U>
     211             : inline bool
     212             : operator==(const StaticAutoPtr<T>& aLhs, const StaticAutoPtr<U>& aRhs)
     213             : {
     214             :   return aLhs.get() == aRhs.get();
     215             : }
     216             : 
     217             : template<class T, class U>
     218             : inline bool
     219             : operator!=(const StaticAutoPtr<T>& aLhs, const StaticAutoPtr<U>& aRhs)
     220             : {
     221             :   return !(aLhs == aRhs);
     222             : }
     223             : 
     224             : REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, const U*,
     225             :                              lhs.get() == rhs, class T, class U)
     226             : 
     227             : REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, U*,
     228             :                              lhs.get() == rhs, class T, class U)
     229             : 
     230             : // Let us compare StaticAutoPtr to 0.
     231         404 : REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, StaticPtr_internal::Zero*,
     232             :                              lhs.get() == nullptr, class T)
     233             : 
     234             : // StaticRefPtr (in)equality operators
     235             : 
     236             : template<class T, class U>
     237             : inline bool
     238             : operator==(const StaticRefPtr<T>& aLhs, const StaticRefPtr<U>& aRhs)
     239             : {
     240             :   return aLhs.get() == aRhs.get();
     241             : }
     242             : 
     243             : template<class T, class U>
     244             : inline bool
     245             : operator!=(const StaticRefPtr<T>& aLhs, const StaticRefPtr<U>& aRhs)
     246             : {
     247             :   return !(aLhs == aRhs);
     248             : }
     249             : 
     250           0 : REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, const U*,
     251             :                              lhs.get() == rhs, class T, class U)
     252             : 
     253          37 : REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, U*,
     254             :                              lhs.get() == rhs, class T, class U)
     255             : 
     256             : // Let us compare StaticRefPtr to 0.
     257         314 : REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, StaticPtr_internal::Zero*,
     258             :                              lhs.get() == nullptr, class T)
     259             : 
     260             : #undef REFLEXIVE_EQUALITY_OPERATORS
     261             : 
     262             : } // namespace mozilla
     263             : 
     264             : // Declared in mozilla/RefPtr.h
     265             : template<class T> template<class U>
     266         372 : RefPtr<T>::RefPtr(const mozilla::StaticRefPtr<U>& aOther)
     267         372 :   : RefPtr(aOther.get())
     268         372 : {}
     269             : 
     270             : template<class T> template<class U>
     271             : RefPtr<T>&
     272          12 : RefPtr<T>::operator=(const mozilla::StaticRefPtr<U>& aOther)
     273             : {
     274          12 :   return operator=(aOther.get());
     275             : }
     276             : 
     277             : #endif

Generated by: LCOV version 1.13