/src/mozilla-central/xpcom/base/StaticPtr.h
Line | Count | Source (jump to first uncovered line) |
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 | | StaticAutoPtr() |
47 | | { |
48 | | #ifdef __GNUC__ |
49 | | #pragma GCC diagnostic push |
50 | | #pragma GCC diagnostic ignored "-Wuninitialized" |
51 | | // False positive with gcc. See bug 1430729 |
52 | | #endif |
53 | | MOZ_ASSERT(!mRawPtr); |
54 | | #ifdef __GNUC__ |
55 | | #pragma GCC diagnostic pop |
56 | | #endif |
57 | | } |
58 | | #endif |
59 | | |
60 | | StaticAutoPtr<T>& operator=(T* aRhs) |
61 | 0 | { |
62 | 0 | Assign(aRhs); |
63 | 0 | return *this; |
64 | 0 | } Unexecuted instantiation: mozilla::StaticAutoPtr<mozilla::LinkedList<mozilla::dom::ContentParent> >::operator=(mozilla::LinkedList<mozilla::dom::ContentParent>*) Unexecuted instantiation: mozilla::StaticAutoPtr<mozilla::dom::ContentProcessManager>::operator=(mozilla::dom::ContentProcessManager*) |
65 | | |
66 | 0 | T* get() const { return mRawPtr; } |
67 | | |
68 | 0 | operator T*() const { return get(); } |
69 | | |
70 | | T* operator->() const |
71 | | { |
72 | | MOZ_ASSERT(mRawPtr); |
73 | | return get(); |
74 | | } |
75 | | |
76 | | T& operator*() const { return *get(); } |
77 | | |
78 | | T* forget() |
79 | | { |
80 | | T* temp = mRawPtr; |
81 | | mRawPtr = nullptr; |
82 | | return temp; |
83 | | } |
84 | | |
85 | | private: |
86 | | // Disallow copy constructor, but only in debug mode. We only define |
87 | | // a default constructor in debug mode (see above); if we declared |
88 | | // this constructor always, the compiler wouldn't generate a trivial |
89 | | // default constructor for us in non-debug mode. |
90 | | #ifdef DEBUG |
91 | | StaticAutoPtr(StaticAutoPtr<T>& aOther); |
92 | | #endif |
93 | | |
94 | | void Assign(T* aNewPtr) |
95 | 0 | { |
96 | 0 | MOZ_ASSERT(!aNewPtr || mRawPtr != aNewPtr); |
97 | 0 | T* oldPtr = mRawPtr; |
98 | 0 | mRawPtr = aNewPtr; |
99 | 0 | delete oldPtr; |
100 | 0 | } Unexecuted instantiation: mozilla::StaticAutoPtr<mozilla::LinkedList<mozilla::dom::ContentParent> >::Assign(mozilla::LinkedList<mozilla::dom::ContentParent>*) Unexecuted instantiation: mozilla::StaticAutoPtr<mozilla::dom::ContentProcessManager>::Assign(mozilla::dom::ContentProcessManager*) |
101 | | |
102 | | T* mRawPtr; |
103 | | }; |
104 | | |
105 | | template<class T> |
106 | | class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticRefPtr |
107 | | { |
108 | | public: |
109 | | // In debug builds, check that mRawPtr is initialized for us as we expect |
110 | | // by the compiler. In non-debug builds, don't declare a constructor |
111 | | // so that the compiler can see that the constructor is trivial. |
112 | | #ifdef DEBUG |
113 | | StaticRefPtr() |
114 | | { |
115 | | #ifdef __GNUC__ |
116 | | #pragma GCC diagnostic push |
117 | | #pragma GCC diagnostic ignored "-Wuninitialized" |
118 | | // False positive with gcc. See bug 1430729 |
119 | | #endif |
120 | | MOZ_ASSERT(!mRawPtr); |
121 | | #ifdef __GNUC__ |
122 | | #pragma GCC diagnostic pop |
123 | | #endif |
124 | | } |
125 | | #endif |
126 | | |
127 | | StaticRefPtr<T>& operator=(T* aRhs) |
128 | 3 | { |
129 | 3 | AssignWithAddref(aRhs); |
130 | 3 | return *this; |
131 | 3 | } Unexecuted instantiation: Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerImpl>::operator=((anonymous namespace)::ProcessPriorityManagerImpl*) Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerChild>::operator=((anonymous namespace)::ProcessPriorityManagerChild*) Line | Count | Source | 128 | 3 | { | 129 | 3 | AssignWithAddref(aRhs); | 130 | 3 | return *this; | 131 | 3 | } |
Unexecuted instantiation: mozilla::StaticRefPtr<mozilla::PreallocatedProcessManagerImpl>::operator=(mozilla::PreallocatedProcessManagerImpl*) |
132 | | |
133 | | StaticRefPtr<T>& operator=(const StaticRefPtr<T>& aRhs) |
134 | | { |
135 | | return (this = aRhs.mRawPtr); |
136 | | } |
137 | | |
138 | | StaticRefPtr<T>& operator=(already_AddRefed<T>& aRhs) |
139 | | { |
140 | | AssignAssumingAddRef(aRhs.take()); |
141 | | return *this; |
142 | | } |
143 | | |
144 | | StaticRefPtr<T>& operator=(already_AddRefed<T>&& aRhs) |
145 | | { |
146 | | AssignAssumingAddRef(aRhs.take()); |
147 | | return *this; |
148 | | } |
149 | | |
150 | | already_AddRefed<T> |
151 | | forget() |
152 | | { |
153 | | T* temp = mRawPtr; |
154 | | mRawPtr = nullptr; |
155 | | return already_AddRefed<T>(temp); |
156 | | } |
157 | | |
158 | 6 | T* get() const { return mRawPtr; } Unexecuted instantiation: Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerImpl>::get() const Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerChild>::get() const Line | Count | Source | 158 | 6 | T* get() const { return mRawPtr; } |
Unexecuted instantiation: mozilla::StaticRefPtr<mozilla::PreallocatedProcessManagerImpl>::get() const |
159 | | |
160 | 3 | operator T*() const { return get(); } Unexecuted instantiation: Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerImpl>::operator (anonymous namespace)::ProcessPriorityManagerImpl*() const Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerChild>::operator (anonymous namespace)::ProcessPriorityManagerChild*() const Line | Count | Source | 160 | 3 | operator T*() const { return get(); } |
Unexecuted instantiation: mozilla::StaticRefPtr<mozilla::PreallocatedProcessManagerImpl>::operator mozilla::PreallocatedProcessManagerImpl*() const |
161 | | |
162 | | T* operator->() const |
163 | 3 | { |
164 | 3 | MOZ_ASSERT(mRawPtr); |
165 | 3 | return get(); |
166 | 3 | } Unexecuted instantiation: Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerImpl>::operator->() const Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerChild>::operator->() const Line | Count | Source | 163 | 3 | { | 164 | 3 | MOZ_ASSERT(mRawPtr); | 165 | 3 | return get(); | 166 | 3 | } |
Unexecuted instantiation: mozilla::StaticRefPtr<mozilla::PreallocatedProcessManagerImpl>::operator->() const |
167 | | |
168 | | T& operator*() const { return *get(); } |
169 | | |
170 | | private: |
171 | | void AssignWithAddref(T* aNewPtr) |
172 | 3 | { |
173 | 3 | if (aNewPtr) { |
174 | 3 | aNewPtr->AddRef(); |
175 | 3 | } |
176 | 3 | AssignAssumingAddRef(aNewPtr); |
177 | 3 | } Unexecuted instantiation: Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerImpl>::AssignWithAddref((anonymous namespace)::ProcessPriorityManagerImpl*) Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerChild>::AssignWithAddref((anonymous namespace)::ProcessPriorityManagerChild*) Line | Count | Source | 172 | 3 | { | 173 | 3 | if (aNewPtr) { | 174 | 3 | aNewPtr->AddRef(); | 175 | 3 | } | 176 | 3 | AssignAssumingAddRef(aNewPtr); | 177 | 3 | } |
Unexecuted instantiation: mozilla::StaticRefPtr<mozilla::PreallocatedProcessManagerImpl>::AssignWithAddref(mozilla::PreallocatedProcessManagerImpl*) |
178 | | |
179 | | void AssignAssumingAddRef(T* aNewPtr) |
180 | 3 | { |
181 | 3 | T* oldPtr = mRawPtr; |
182 | 3 | mRawPtr = aNewPtr; |
183 | 3 | if (oldPtr) { |
184 | 0 | oldPtr->Release(); |
185 | 0 | } |
186 | 3 | } Unexecuted instantiation: Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerImpl>::AssignAssumingAddRef((anonymous namespace)::ProcessPriorityManagerImpl*) Unified_cpp_dom_ipc0.cpp:mozilla::StaticRefPtr<(anonymous namespace)::ProcessPriorityManagerChild>::AssignAssumingAddRef((anonymous namespace)::ProcessPriorityManagerChild*) Line | Count | Source | 180 | 3 | { | 181 | 3 | T* oldPtr = mRawPtr; | 182 | 3 | mRawPtr = aNewPtr; | 183 | 3 | if (oldPtr) { | 184 | 0 | oldPtr->Release(); | 185 | 0 | } | 186 | 3 | } |
Unexecuted instantiation: mozilla::StaticRefPtr<mozilla::PreallocatedProcessManagerImpl>::AssignAssumingAddRef(mozilla::PreallocatedProcessManagerImpl*) |
187 | | |
188 | | T* MOZ_OWNING_REF mRawPtr; |
189 | | }; |
190 | | |
191 | | namespace StaticPtr_internal { |
192 | | class Zero; |
193 | | } // namespace StaticPtr_internal |
194 | | |
195 | | #define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \ |
196 | | template<__VA_ARGS__> \ |
197 | | inline bool \ |
198 | | operator==(type1 lhs, type2 rhs) \ |
199 | | { \ |
200 | | return eq_fn; \ |
201 | | } \ |
202 | | \ |
203 | | template<__VA_ARGS__> \ |
204 | | inline bool \ |
205 | | operator==(type2 lhs, type1 rhs) \ |
206 | | { \ |
207 | | return rhs == lhs; \ |
208 | | } \ |
209 | | \ |
210 | | template<__VA_ARGS__> \ |
211 | | inline bool \ |
212 | | operator!=(type1 lhs, type2 rhs) \ |
213 | | { \ |
214 | | return !(lhs == rhs); \ |
215 | | } \ |
216 | | \ |
217 | | template<__VA_ARGS__> \ |
218 | | inline bool \ |
219 | | operator!=(type2 lhs, type1 rhs) \ |
220 | | { \ |
221 | | return !(lhs == rhs); \ |
222 | | } |
223 | | |
224 | | // StaticAutoPtr (in)equality operators |
225 | | |
226 | | template<class T, class U> |
227 | | inline bool |
228 | | operator==(const StaticAutoPtr<T>& aLhs, const StaticAutoPtr<U>& aRhs) |
229 | | { |
230 | | return aLhs.get() == aRhs.get(); |
231 | | } |
232 | | |
233 | | template<class T, class U> |
234 | | inline bool |
235 | | operator!=(const StaticAutoPtr<T>& aLhs, const StaticAutoPtr<U>& aRhs) |
236 | | { |
237 | | return !(aLhs == aRhs); |
238 | | } |
239 | | |
240 | | REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, const U*, |
241 | | lhs.get() == rhs, class T, class U) |
242 | | |
243 | | REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, U*, |
244 | | lhs.get() == rhs, class T, class U) |
245 | | |
246 | | // Let us compare StaticAutoPtr to 0. |
247 | | REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, StaticPtr_internal::Zero*, |
248 | | lhs.get() == nullptr, class T) |
249 | | |
250 | | // StaticRefPtr (in)equality operators |
251 | | |
252 | | template<class T, class U> |
253 | | inline bool |
254 | | operator==(const StaticRefPtr<T>& aLhs, const StaticRefPtr<U>& aRhs) |
255 | | { |
256 | | return aLhs.get() == aRhs.get(); |
257 | | } |
258 | | |
259 | | template<class T, class U> |
260 | | inline bool |
261 | | operator!=(const StaticRefPtr<T>& aLhs, const StaticRefPtr<U>& aRhs) |
262 | | { |
263 | | return !(aLhs == aRhs); |
264 | | } |
265 | | |
266 | | REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, const U*, |
267 | | lhs.get() == rhs, class T, class U) |
268 | | |
269 | | REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, U*, |
270 | | lhs.get() == rhs, class T, class U) |
271 | | |
272 | | // Let us compare StaticRefPtr to 0. |
273 | | REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, StaticPtr_internal::Zero*, |
274 | | lhs.get() == nullptr, class T) |
275 | | |
276 | | #undef REFLEXIVE_EQUALITY_OPERATORS |
277 | | |
278 | | } // namespace mozilla |
279 | | |
280 | | // Declared in mozilla/RefPtr.h |
281 | | template<class T> template<class U> |
282 | | RefPtr<T>::RefPtr(const mozilla::StaticRefPtr<U>& aOther) |
283 | | : RefPtr(aOther.get()) |
284 | | {} |
285 | | |
286 | | template<class T> template<class U> |
287 | | RefPtr<T>& |
288 | | RefPtr<T>::operator=(const mozilla::StaticRefPtr<U>& aOther) |
289 | | { |
290 | | return operator=(aOther.get()); |
291 | | } |
292 | | |
293 | | template <class T> |
294 | | inline already_AddRefed<T> |
295 | | do_AddRef(const mozilla::StaticRefPtr<T>& aObj) |
296 | | { |
297 | | RefPtr<T> ref(aObj); |
298 | | return ref.forget(); |
299 | | } |
300 | | |
301 | | #endif |