Bumping manifests a=b2g-bump
[gecko.git] / xpcom / base / StaticPtr.h
blob05a1351cf5b6b6971a1561353175e05f6a0186ed
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/. */
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.
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).
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.
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.
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.
37 template<class T>
38 class StaticAutoPtr
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()
47 MOZ_ASSERT(!mRawPtr);
49 #endif
51 StaticAutoPtr<T>& operator=(T* aRhs)
53 Assign(aRhs);
54 return *this;
57 T* get() const { return mRawPtr; }
59 operator T*() const { return get(); }
61 T* operator->() const
63 MOZ_ASSERT(mRawPtr);
64 return get();
67 T& operator*() const { return *get(); }
69 private:
70 // Disallow copy constructor, but only in debug mode. We only define
71 // a default constructor in debug mode (see above); if we declared
72 // this constructor always, the compiler wouldn't generate a trivial
73 // default constructor for us in non-debug mode.
74 #ifdef DEBUG
75 StaticAutoPtr(StaticAutoPtr<T>& aOther);
76 #endif
78 void Assign(T* aNewPtr)
80 MOZ_ASSERT(!aNewPtr || mRawPtr != aNewPtr);
81 T* oldPtr = mRawPtr;
82 mRawPtr = aNewPtr;
83 delete oldPtr;
86 T* mRawPtr;
89 template<class T>
90 class StaticRefPtr
92 public:
93 // In debug builds, check that mRawPtr is initialized for us as we expect
94 // by the compiler. In non-debug builds, don't declare a constructor
95 // so that the compiler can see that the constructor is trivial.
96 #ifdef DEBUG
97 StaticRefPtr()
99 MOZ_ASSERT(!mRawPtr);
101 #endif
103 StaticRefPtr<T>& operator=(T* aRhs)
105 AssignWithAddref(aRhs);
106 return *this;
109 StaticRefPtr<T>& operator=(const StaticRefPtr<T>& aRhs)
111 return (this = aRhs.mRawPtr);
114 T* get() const { return mRawPtr; }
116 operator T*() const { return get(); }
118 T* operator->() const
120 MOZ_ASSERT(mRawPtr);
121 return get();
124 T& operator*() const { return *get(); }
126 private:
127 void AssignWithAddref(T* aNewPtr)
129 if (aNewPtr) {
130 aNewPtr->AddRef();
132 AssignAssumingAddRef(aNewPtr);
135 void AssignAssumingAddRef(T* aNewPtr)
137 T* oldPtr = mRawPtr;
138 mRawPtr = aNewPtr;
139 if (oldPtr) {
140 oldPtr->Release();
144 T* mRawPtr;
147 namespace StaticPtr_internal {
148 class Zero;
149 } // namespace StaticPtr_internal
151 #define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \
152 template<__VA_ARGS__> \
153 inline bool \
154 operator==(type1 lhs, type2 rhs) \
156 return eq_fn; \
159 template<__VA_ARGS__> \
160 inline bool \
161 operator==(type2 lhs, type1 rhs) \
163 return rhs == lhs; \
166 template<__VA_ARGS__> \
167 inline bool \
168 operator!=(type1 lhs, type2 rhs) \
170 return !(lhs == rhs); \
173 template<__VA_ARGS__> \
174 inline bool \
175 operator!=(type2 lhs, type1 rhs) \
177 return !(lhs == rhs); \
180 // StaticAutoPtr (in)equality operators
182 template<class T, class U>
183 inline bool
184 operator==(const StaticAutoPtr<T>& aLhs, const StaticAutoPtr<U>& aRhs)
186 return aLhs.get() == aRhs.get();
189 template<class T, class U>
190 inline bool
191 operator!=(const StaticAutoPtr<T>& aLhs, const StaticAutoPtr<U>& aRhs)
193 return !(aLhs == aRhs);
196 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, const U*,
197 lhs.get() == rhs, class T, class U)
199 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, U*,
200 lhs.get() == rhs, class T, class U)
202 // Let us compare StaticAutoPtr to 0.
203 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, StaticPtr_internal::Zero*,
204 lhs.get() == nullptr, class T)
206 // StaticRefPtr (in)equality operators
208 template<class T, class U>
209 inline bool
210 operator==(const StaticRefPtr<T>& aLhs, const StaticRefPtr<U>& aRhs)
212 return aLhs.get() == aRhs.get();
215 template<class T, class U>
216 inline bool
217 operator!=(const StaticRefPtr<T>& aLhs, const StaticRefPtr<U>& aRhs)
219 return !(aLhs == aRhs);
222 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, const U*,
223 lhs.get() == rhs, class T, class U)
225 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, U*,
226 lhs.get() == rhs, class T, class U)
228 // Let us compare StaticRefPtr to 0.
229 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, StaticPtr_internal::Zero*,
230 lhs.get() == nullptr, class T)
232 #undef REFLEXIVE_EQUALITY_OPERATORS
234 } // namespace mozilla
236 #endif