Wed, 31 Dec 2014 06:09:35 +0100
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