Bug 1867190 - Add prefs for PHC probablities r=glandium
[gecko.git] / xpcom / base / StaticPtr.h
blob38fcd82f972b7c23a89996bc3c3e14a006ae5e6b
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.
24 * Since the compiler guarantees that all global variables are initialized to
25 * 0, the default constexpr constructors will result in no actual code being
26 * generated. Since we rely on this, the clang plugin, run as part of our
27 * "static analysis" builds, makes it a compile-time error to use
28 * Static{Auto,Ref}Ptr as anything except a global variable.
30 * Static{Auto,Ref}Ptr have a limited interface as compared to ns{Auto,Ref}Ptr;
31 * this is intentional, since their range of acceptable uses is smaller.
34 template <class T>
35 class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticAutoPtr {
36 public:
37 constexpr StaticAutoPtr() = default;
38 StaticAutoPtr(const StaticAutoPtr&) = delete;
40 StaticAutoPtr<T>& operator=(T* aRhs) {
41 Assign(aRhs);
42 return *this;
45 T* get() const { return mRawPtr; }
47 operator T*() const { return get(); }
49 T* operator->() const {
50 MOZ_ASSERT(mRawPtr);
51 return get();
54 T& operator*() const { return *get(); }
56 T* forget() {
57 T* temp = mRawPtr;
58 mRawPtr = nullptr;
59 return temp;
62 private:
63 void Assign(T* aNewPtr) {
64 MOZ_ASSERT(!aNewPtr || mRawPtr != aNewPtr);
65 T* oldPtr = mRawPtr;
66 mRawPtr = aNewPtr;
67 delete oldPtr;
70 T* mRawPtr = nullptr;
73 template <class T>
74 class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticRefPtr {
75 public:
76 constexpr StaticRefPtr() = default;
77 StaticRefPtr(const StaticRefPtr&) = delete;
79 StaticRefPtr<T>& operator=(T* aRhs) {
80 AssignWithAddref(aRhs);
81 return *this;
84 StaticRefPtr<T>& operator=(const StaticRefPtr<T>& aRhs) {
85 return (this = aRhs.mRawPtr);
88 StaticRefPtr<T>& operator=(already_AddRefed<T>& aRhs) {
89 AssignAssumingAddRef(aRhs.take());
90 return *this;
93 template <typename U>
94 StaticRefPtr<T>& operator=(RefPtr<U>&& aRhs) {
95 AssignAssumingAddRef(aRhs.forget().take());
96 return *this;
99 StaticRefPtr<T>& operator=(already_AddRefed<T>&& aRhs) {
100 AssignAssumingAddRef(aRhs.take());
101 return *this;
104 already_AddRefed<T> forget() {
105 T* temp = mRawPtr;
106 mRawPtr = nullptr;
107 return already_AddRefed<T>(temp);
110 T* get() const { return mRawPtr; }
112 operator T*() const { return get(); }
114 T* operator->() const {
115 MOZ_ASSERT(mRawPtr);
116 return get();
119 T& operator*() const { return *get(); }
121 private:
122 void AssignWithAddref(T* aNewPtr) {
123 if (aNewPtr) {
124 RefPtrTraits<T>::AddRef(aNewPtr);
126 AssignAssumingAddRef(aNewPtr);
129 void AssignAssumingAddRef(T* aNewPtr) {
130 T* oldPtr = mRawPtr;
131 mRawPtr = aNewPtr;
132 if (oldPtr) {
133 RefPtrTraits<T>::Release(oldPtr);
137 T* MOZ_OWNING_REF mRawPtr = nullptr;
140 namespace StaticPtr_internal {
141 class Zero;
142 } // namespace StaticPtr_internal
144 #define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \
145 template <__VA_ARGS__> \
146 inline bool operator==(type1 lhs, type2 rhs) { \
147 return eq_fn; \
150 template <__VA_ARGS__> \
151 inline bool operator==(type2 lhs, type1 rhs) { \
152 return rhs == lhs; \
155 template <__VA_ARGS__> \
156 inline bool operator!=(type1 lhs, type2 rhs) { \
157 return !(lhs == rhs); \
160 template <__VA_ARGS__> \
161 inline bool operator!=(type2 lhs, type1 rhs) { \
162 return !(lhs == rhs); \
165 // StaticAutoPtr (in)equality operators
167 template <class T, class U>
168 inline bool operator==(const StaticAutoPtr<T>& aLhs,
169 const StaticAutoPtr<U>& aRhs) {
170 return aLhs.get() == aRhs.get();
173 template <class T, class U>
174 inline bool operator!=(const StaticAutoPtr<T>& aLhs,
175 const StaticAutoPtr<U>& aRhs) {
176 return !(aLhs == aRhs);
179 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, const U*,
180 lhs.get() == rhs, class T, class U)
182 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, U*, lhs.get() == rhs,
183 class T, class U)
185 // Let us compare StaticAutoPtr to 0.
186 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, StaticPtr_internal::Zero*,
187 lhs.get() == nullptr, class T)
189 // StaticRefPtr (in)equality operators
191 template <class T, class U>
192 inline bool operator==(const StaticRefPtr<T>& aLhs,
193 const StaticRefPtr<U>& aRhs) {
194 return aLhs.get() == aRhs.get();
197 template <class T, class U>
198 inline bool operator!=(const StaticRefPtr<T>& aLhs,
199 const StaticRefPtr<U>& aRhs) {
200 return !(aLhs == aRhs);
203 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, const U*, lhs.get() == rhs,
204 class T, class U)
206 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, U*, lhs.get() == rhs,
207 class T, class U)
209 // Let us compare StaticRefPtr to 0.
210 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, StaticPtr_internal::Zero*,
211 lhs.get() == nullptr, class T)
213 #undef REFLEXIVE_EQUALITY_OPERATORS
215 } // namespace mozilla
217 // Declared in mozilla/RefPtr.h
218 template <class T>
219 template <class U>
220 RefPtr<T>::RefPtr(const mozilla::StaticRefPtr<U>& aOther)
221 : RefPtr(aOther.get()) {}
223 template <class T>
224 template <class U>
225 RefPtr<T>& RefPtr<T>::operator=(const mozilla::StaticRefPtr<U>& aOther) {
226 return operator=(aOther.get());
229 template <class T>
230 inline already_AddRefed<T> do_AddRef(const mozilla::StaticRefPtr<T>& aObj) {
231 RefPtr<T> ref(aObj);
232 return ref.forget();
235 #endif