Coverage Report

Created: 2018-09-25 14:53

/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