xpcom/base/StaticPtr.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set sw=2 ts=8 et ft=cpp : */
     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/. */
     7 #ifndef mozilla_StaticPtr_h
     8 #define mozilla_StaticPtr_h
    10 #include "mozilla/Assertions.h"
    11 #include "mozilla/NullPtr.h"
    13 namespace mozilla {
    15 /**
    16  * StaticAutoPtr and StaticRefPtr are like nsAutoPtr and nsRefPtr, except they
    17  * are suitable for use as global variables.
    18  *
    19  * In particular, a global instance of Static{Auto,Ref}Ptr doesn't cause the
    20  * compiler to emit  a static initializer (in release builds, anyway).
    21  *
    22  * In order to accomplish this, Static{Auto,Ref}Ptr must have a trivial
    23  * constructor and destructor.  As a consequence, it cannot initialize its raw
    24  * pointer to 0 on construction, and it cannot delete/release its raw pointer
    25  * upon destruction.
    26  *
    27  * Since the compiler guarantees that all global variables are initialized to
    28  * 0, these trivial constructors are safe, so long as you use
    29  * Static{Auto,Ref}Ptr as a global variable.  If you use Static{Auto,Ref}Ptr as
    30  * a stack variable or as a class instance variable, you will get what you
    31  * deserve.
    32  *
    33  * Static{Auto,Ref}Ptr have a limited interface as compared to ns{Auto,Ref}Ptr;
    34  * this is intentional, since their range of acceptable uses is smaller.
    35  */
    37 template<class T>
    38 class StaticAutoPtr
    39 {
    40   public:
    41     // In debug builds, check that mRawPtr is initialized for us as we expect
    42     // by the compiler.  In non-debug builds, don't declare a constructor
    43     // so that the compiler can see that the constructor is trivial.
    44 #ifdef DEBUG
    45     StaticAutoPtr()
    46     {
    47       MOZ_ASSERT(!mRawPtr);
    48     }
    49 #endif
    51     StaticAutoPtr<T>& operator=(T* rhs)
    52     {
    53       Assign(rhs);
    54       return *this;
    55     }
    57     T* get() const
    58     {
    59       return mRawPtr;
    60     }
    62     operator T*() const
    63     {
    64       return get();
    65     }
    67     T* operator->() const
    68     {
    69       MOZ_ASSERT(mRawPtr);
    70       return get();
    71     }
    73     T& operator*() const
    74     {
    75       return *get();
    76     }
    78   private:
    79     // Disallow copy constructor, but only in debug mode.  We only define
    80     // a default constructor in debug mode (see above); if we declared
    81     // this constructor always, the compiler wouldn't generate a trivial
    82     // default constructor for us in non-debug mode.
    83 #ifdef DEBUG
    84     StaticAutoPtr(StaticAutoPtr<T> &other);
    85 #endif
    87     void Assign(T* newPtr)
    88     {
    89       MOZ_ASSERT(!newPtr || mRawPtr != newPtr);
    90       T* oldPtr = mRawPtr;
    91       mRawPtr = newPtr;
    92       delete oldPtr;
    93     }
    95     T* mRawPtr;
    96 };
    98 template<class T>
    99 class StaticRefPtr
   100 {
   101 public:
   102   // In debug builds, check that mRawPtr is initialized for us as we expect
   103   // by the compiler.  In non-debug builds, don't declare a constructor
   104   // so that the compiler can see that the constructor is trivial.
   105 #ifdef DEBUG
   106   StaticRefPtr()
   107   {
   108     MOZ_ASSERT(!mRawPtr);
   109   }
   110 #endif
   112   StaticRefPtr<T>& operator=(T* rhs)
   113   {
   114     AssignWithAddref(rhs);
   115     return *this;
   116   }
   118   StaticRefPtr<T>& operator=(const StaticRefPtr<T>& rhs)
   119   {
   120     return (this = rhs.mRawPtr);
   121   }
   123   T* get() const
   124   {
   125     return mRawPtr;
   126   }
   128   operator T*() const
   129   {
   130     return get();
   131   }
   133   T* operator->() const
   134   {
   135     MOZ_ASSERT(mRawPtr);
   136     return get();
   137   }
   139   T& operator*() const
   140   {
   141     return *get();
   142   }
   144 private:
   145   void AssignWithAddref(T* newPtr)
   146   {
   147     if (newPtr) {
   148       newPtr->AddRef();
   149     }
   150     AssignAssumingAddRef(newPtr);
   151   }
   153   void AssignAssumingAddRef(T* newPtr)
   154   {
   155     T* oldPtr = mRawPtr;
   156     mRawPtr = newPtr;
   157     if (oldPtr) {
   158       oldPtr->Release();
   159     }
   160   }
   162   T* mRawPtr;
   163 };
   165 namespace StaticPtr_internal {
   166 class Zero;
   167 } // namespace StaticPtr_internal
   169 #define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \
   170   template<__VA_ARGS__>                                        \
   171   inline bool                                                  \
   172   operator==(type1 lhs, type2 rhs)                             \
   173   {                                                            \
   174     return eq_fn;                                              \
   175   }                                                            \
   176                                                                \
   177   template<__VA_ARGS__>                                        \
   178   inline bool                                                  \
   179   operator==(type2 lhs, type1 rhs)                             \
   180   {                                                            \
   181     return rhs == lhs;                                         \
   182   }                                                            \
   183                                                                \
   184   template<__VA_ARGS__>                                        \
   185   inline bool                                                  \
   186   operator!=(type1 lhs, type2 rhs)                             \
   187   {                                                            \
   188     return !(lhs == rhs);                                      \
   189   }                                                            \
   190                                                                \
   191   template<__VA_ARGS__>                                        \
   192   inline bool                                                  \
   193   operator!=(type2 lhs, type1 rhs)                             \
   194   {                                                            \
   195     return !(lhs == rhs);                                      \
   196   }
   198 // StaticAutoPtr (in)equality operators
   200 template<class T, class U>
   201 inline bool
   202 operator==(const StaticAutoPtr<T>& lhs, const StaticAutoPtr<U>& rhs)
   203 {
   204   return lhs.get() == rhs.get();
   205 }
   207 template<class T, class U>
   208 inline bool
   209 operator!=(const StaticAutoPtr<T>& lhs, const StaticAutoPtr<U>& rhs)
   210 {
   211   return !(lhs == rhs);
   212 }
   214 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, const U*,
   215                              lhs.get() == rhs, class T, class U)
   217 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, U*,
   218                              lhs.get() == rhs, class T, class U)
   220 // Let us compare StaticAutoPtr to 0.
   221 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, StaticPtr_internal::Zero*,
   222                              lhs.get() == nullptr, class T)
   224 // StaticRefPtr (in)equality operators
   226 template<class T, class U>
   227 inline bool
   228 operator==(const StaticRefPtr<T>& lhs, const StaticRefPtr<U>& rhs)
   229 {
   230   return lhs.get() == rhs.get();
   231 }
   233 template<class T, class U>
   234 inline bool
   235 operator!=(const StaticRefPtr<T>& lhs, const StaticRefPtr<U>& rhs)
   236 {
   237   return !(lhs == rhs);
   238 }
   240 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, const U*,
   241                              lhs.get() == rhs, class T, class U)
   243 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, U*,
   244                              lhs.get() == rhs, class T, class U)
   246 // Let us compare StaticRefPtr to 0.
   247 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, StaticPtr_internal::Zero*,
   248                              lhs.get() == nullptr, class T)
   250 #undef REFLEXIVE_EQUALITY_OPERATORS
   252 } // namespace mozilla
   254 #endif

mercurial