Bug 1686838 [wpt PR 27194] - [webcodecs] Deprecate VideoFrame.destroy()., a=testonly
[gecko.git] / xpcom / base / StaticPtr.h
bloba20ec71a64c91be992a90db6bc1a7c2cc3a9633f
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/AlreadyAddRefed.h"
11 #include "mozilla/Assertions.h"
12 #include "mozilla/Attributes.h"
13 #include "mozilla/RefPtr.h"
15 namespace mozilla {
17 /**
18 * StaticAutoPtr and StaticRefPtr are like UniquePtr and RefPtr, except they
19 * are suitable for use as global variables.
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).
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.
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.
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.
38 template <class T>
39 class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS 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() {
46 # ifdef __GNUC__
47 # pragma GCC diagnostic push
48 # pragma GCC diagnostic ignored "-Wuninitialized"
49 // False positive with gcc. See bug 1430729
50 # endif
51 MOZ_ASSERT(!mRawPtr);
52 # ifdef __GNUC__
53 # pragma GCC diagnostic pop
54 # endif
56 #endif
58 StaticAutoPtr<T>& operator=(T* aRhs) {
59 Assign(aRhs);
60 return *this;
63 T* get() const { return mRawPtr; }
65 operator T*() const { return get(); }
67 T* operator->() const {
68 MOZ_ASSERT(mRawPtr);
69 return get();
72 T& operator*() const { return *get(); }
74 T* forget() {
75 T* temp = mRawPtr;
76 mRawPtr = nullptr;
77 return temp;
80 private:
81 // Disallow copy constructor, but only in debug mode. We only define
82 // a default constructor in debug mode (see above); if we declared
83 // this constructor always, the compiler wouldn't generate a trivial
84 // default constructor for us in non-debug mode.
85 #ifdef DEBUG
86 StaticAutoPtr(StaticAutoPtr<T>& aOther);
87 #endif
89 void Assign(T* aNewPtr) {
90 MOZ_ASSERT(!aNewPtr || mRawPtr != aNewPtr);
91 T* oldPtr = mRawPtr;
92 mRawPtr = aNewPtr;
93 delete oldPtr;
96 T* mRawPtr;
99 template <class T>
100 class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticRefPtr {
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 # ifdef __GNUC__
108 # pragma GCC diagnostic push
109 # pragma GCC diagnostic ignored "-Wuninitialized"
110 // False positive with gcc. See bug 1430729
111 # endif
112 MOZ_ASSERT(!mRawPtr);
113 # ifdef __GNUC__
114 # pragma GCC diagnostic pop
115 # endif
117 #endif
119 StaticRefPtr<T>& operator=(T* aRhs) {
120 AssignWithAddref(aRhs);
121 return *this;
124 StaticRefPtr<T>& operator=(const StaticRefPtr<T>& aRhs) {
125 return (this = aRhs.mRawPtr);
128 StaticRefPtr<T>& operator=(already_AddRefed<T>& aRhs) {
129 AssignAssumingAddRef(aRhs.take());
130 return *this;
133 template <typename U>
134 StaticRefPtr<T>& operator=(RefPtr<U>&& aRhs) {
135 AssignAssumingAddRef(aRhs.forget().take());
136 return *this;
139 StaticRefPtr<T>& operator=(already_AddRefed<T>&& aRhs) {
140 AssignAssumingAddRef(aRhs.take());
141 return *this;
144 already_AddRefed<T> forget() {
145 T* temp = mRawPtr;
146 mRawPtr = nullptr;
147 return already_AddRefed<T>(temp);
150 T* get() const { return mRawPtr; }
152 operator T*() const { return get(); }
154 T* operator->() const {
155 MOZ_ASSERT(mRawPtr);
156 return get();
159 T& operator*() const { return *get(); }
161 private:
162 void AssignWithAddref(T* aNewPtr) {
163 if (aNewPtr) {
164 aNewPtr->AddRef();
166 AssignAssumingAddRef(aNewPtr);
169 void AssignAssumingAddRef(T* aNewPtr) {
170 T* oldPtr = mRawPtr;
171 mRawPtr = aNewPtr;
172 if (oldPtr) {
173 oldPtr->Release();
177 T* MOZ_OWNING_REF mRawPtr;
180 namespace StaticPtr_internal {
181 class Zero;
182 } // namespace StaticPtr_internal
184 #define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \
185 template <__VA_ARGS__> \
186 inline bool operator==(type1 lhs, type2 rhs) { \
187 return eq_fn; \
190 template <__VA_ARGS__> \
191 inline bool operator==(type2 lhs, type1 rhs) { \
192 return rhs == lhs; \
195 template <__VA_ARGS__> \
196 inline bool operator!=(type1 lhs, type2 rhs) { \
197 return !(lhs == rhs); \
200 template <__VA_ARGS__> \
201 inline bool operator!=(type2 lhs, type1 rhs) { \
202 return !(lhs == rhs); \
205 // StaticAutoPtr (in)equality operators
207 template <class T, class U>
208 inline bool operator==(const StaticAutoPtr<T>& aLhs,
209 const StaticAutoPtr<U>& aRhs) {
210 return aLhs.get() == aRhs.get();
213 template <class T, class U>
214 inline bool operator!=(const StaticAutoPtr<T>& aLhs,
215 const StaticAutoPtr<U>& aRhs) {
216 return !(aLhs == aRhs);
219 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, const U*,
220 lhs.get() == rhs, class T, class U)
222 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, U*, lhs.get() == rhs,
223 class T, class U)
225 // Let us compare StaticAutoPtr to 0.
226 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, StaticPtr_internal::Zero*,
227 lhs.get() == nullptr, class T)
229 // StaticRefPtr (in)equality operators
231 template <class T, class U>
232 inline bool operator==(const StaticRefPtr<T>& aLhs,
233 const StaticRefPtr<U>& aRhs) {
234 return aLhs.get() == aRhs.get();
237 template <class T, class U>
238 inline bool operator!=(const StaticRefPtr<T>& aLhs,
239 const StaticRefPtr<U>& aRhs) {
240 return !(aLhs == aRhs);
243 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, const U*, lhs.get() == rhs,
244 class T, class U)
246 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, U*, lhs.get() == rhs,
247 class T, class U)
249 // Let us compare StaticRefPtr to 0.
250 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, StaticPtr_internal::Zero*,
251 lhs.get() == nullptr, class T)
253 #undef REFLEXIVE_EQUALITY_OPERATORS
255 } // namespace mozilla
257 // Declared in mozilla/RefPtr.h
258 template <class T>
259 template <class U>
260 RefPtr<T>::RefPtr(const mozilla::StaticRefPtr<U>& aOther)
261 : RefPtr(aOther.get()) {}
263 template <class T>
264 template <class U>
265 RefPtr<T>& RefPtr<T>::operator=(const mozilla::StaticRefPtr<U>& aOther) {
266 return operator=(aOther.get());
269 template <class T>
270 inline already_AddRefed<T> do_AddRef(const mozilla::StaticRefPtr<T>& aObj) {
271 RefPtr<T> ref(aObj);
272 return ref.forget();
275 #endif