Bug 1893155 - Part 1: Make Calendar{WeekOfYear,YearOfWeek} return undefined. r=spider...
[gecko.git] / xpcom / base / StaticLocalPtr.h
blob2e2fc035bdc7c8bf0a323d6b0ee71ad4969d23f8
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 https://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_StaticLocalPtr_h
8 #define mozilla_StaticLocalPtr_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 * StaticLocalAutoPtr and StaticLocalRefPtr are like UniquePtr and RefPtr,
19 * except they are suitable for use as "magic static" local variables -- that
20 * is, they are able to take advantage of C++11's guarantee of thread safety
21 * during initialization by atomically constructing both the smart pointer
22 * itself as well as the object being pointed to.
24 * A static local instance of StaticLocal{Auto,Ref}Ptr does not cause the
25 * compiler to emit any atexit calls. In order to accomplish this,
26 * StaticLocal{Auto,Ref}Ptr must have a trivial destructor. As a consequence,
27 * it does not delete/release its raw pointer upon destruction.
29 * The clang plugin, run as part of our "static analysis" builds, makes it a
30 * compile-time error to use StaticLocal{Auto,Ref}Ptr as anything except a
31 * static local variable.
33 * StaticLocal{Auto,Ref}Ptr have a limited interface as compared to
34 * ns{Auto,Ref}Ptr; this is intentional, since their range of acceptable uses is
35 * smaller.
38 template <typename T>
39 class MOZ_STATIC_LOCAL_CLASS StaticLocalAutoPtr final {
40 public:
41 explicit StaticLocalAutoPtr(T* aRawPtr) : mRawPtr(aRawPtr) {}
43 StaticLocalAutoPtr(StaticLocalAutoPtr<T>&& aOther) : mRawPtr(aOther.mRawPtr) {
44 aOther.mRawPtr = nullptr;
47 StaticLocalAutoPtr<T>& operator=(T* aRhs) {
48 Assign(aRhs);
49 return *this;
52 T* get() const { return mRawPtr; }
54 operator T*() const { return get(); }
56 T* operator->() const {
57 MOZ_ASSERT(mRawPtr);
58 return get();
61 T& operator*() const { return *get(); }
63 T* forget() {
64 T* temp = mRawPtr;
65 mRawPtr = nullptr;
66 return temp;
69 private:
70 StaticLocalAutoPtr(const StaticLocalAutoPtr<T>& aOther) = delete;
72 // We do not allow assignment as the intention of this class is to only
73 // assign to mRawPtr during construction.
74 StaticLocalAutoPtr& operator=(const StaticLocalAutoPtr<T>& aOther) = delete;
75 StaticLocalAutoPtr& operator=(StaticLocalAutoPtr<T>&&) = delete;
77 void Assign(T* aNewPtr) {
78 MOZ_ASSERT(!aNewPtr || mRawPtr != aNewPtr);
79 T* oldPtr = mRawPtr;
80 mRawPtr = aNewPtr;
81 delete oldPtr;
84 T* mRawPtr;
87 template <typename T>
88 class MOZ_STATIC_LOCAL_CLASS StaticLocalRefPtr final {
89 public:
90 explicit StaticLocalRefPtr(T* aRawPtr) : mRawPtr(nullptr) {
91 AssignWithAddref(aRawPtr);
94 explicit StaticLocalRefPtr(already_AddRefed<T>& aPtr) : mRawPtr(nullptr) {
95 AssignAssumingAddRef(aPtr.take());
98 explicit StaticLocalRefPtr(already_AddRefed<T>&& aPtr) : mRawPtr(nullptr) {
99 AssignAssumingAddRef(aPtr.take());
102 StaticLocalRefPtr(const StaticLocalRefPtr<T>& aPtr)
103 : StaticLocalRefPtr(aPtr.mRawPtr) {}
105 StaticLocalRefPtr(StaticLocalRefPtr<T>&& aPtr) : mRawPtr(aPtr.mRawPtr) {
106 aPtr.mRawPtr = nullptr;
109 StaticLocalRefPtr<T>& operator=(T* aRhs) {
110 AssignWithAddref(aRhs);
111 return *this;
114 already_AddRefed<T> forget() {
115 T* temp = mRawPtr;
116 mRawPtr = nullptr;
117 return already_AddRefed<T>(temp);
120 T* get() const { return mRawPtr; }
122 operator T*() const { return get(); }
124 T* operator->() const {
125 MOZ_ASSERT(mRawPtr);
126 return get();
129 T& operator*() const { return *get(); }
131 private:
132 // We do not allow assignment as the intention of this class is to only
133 // assign to mRawPtr during construction.
134 StaticLocalRefPtr<T>& operator=(const StaticLocalRefPtr<T>& aRhs) = delete;
135 StaticLocalRefPtr<T>& operator=(StaticLocalRefPtr<T>&& aRhs) = delete;
137 void AssignWithAddref(T* aNewPtr) {
138 if (aNewPtr) {
139 aNewPtr->AddRef();
141 AssignAssumingAddRef(aNewPtr);
144 void AssignAssumingAddRef(T* aNewPtr) {
145 T* oldPtr = mRawPtr;
146 mRawPtr = aNewPtr;
147 if (oldPtr) {
148 oldPtr->Release();
152 T* MOZ_OWNING_REF mRawPtr;
155 namespace StaticLocalPtr_internal {
156 class Zero;
157 } // namespace StaticLocalPtr_internal
159 #define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \
160 template <__VA_ARGS__> \
161 inline bool operator==(type1 lhs, type2 rhs) { \
162 return eq_fn; \
165 template <__VA_ARGS__> \
166 inline bool operator==(type2 lhs, type1 rhs) { \
167 return rhs == lhs; \
170 template <__VA_ARGS__> \
171 inline bool operator!=(type1 lhs, type2 rhs) { \
172 return !(lhs == rhs); \
175 template <__VA_ARGS__> \
176 inline bool operator!=(type2 lhs, type1 rhs) { \
177 return !(lhs == rhs); \
180 // StaticLocalAutoPtr (in)equality operators
182 template <class T, class U>
183 inline bool operator==(const StaticLocalAutoPtr<T>& aLhs,
184 const StaticLocalAutoPtr<U>& aRhs) {
185 return aLhs.get() == aRhs.get();
188 template <class T, class U>
189 inline bool operator!=(const StaticLocalAutoPtr<T>& aLhs,
190 const StaticLocalAutoPtr<U>& aRhs) {
191 return !(aLhs == aRhs);
194 REFLEXIVE_EQUALITY_OPERATORS(const StaticLocalAutoPtr<T>&, const U*,
195 lhs.get() == rhs, class T, class U)
197 REFLEXIVE_EQUALITY_OPERATORS(const StaticLocalAutoPtr<T>&, U*, lhs.get() == rhs,
198 class T, class U)
200 // Let us compare StaticLocalAutoPtr to 0.
201 REFLEXIVE_EQUALITY_OPERATORS(const StaticLocalAutoPtr<T>&,
202 StaticLocalPtr_internal::Zero*,
203 lhs.get() == nullptr, class T)
205 // StaticLocalRefPtr (in)equality operators
207 template <class T, class U>
208 inline bool operator==(const StaticLocalRefPtr<T>& aLhs,
209 const StaticLocalRefPtr<U>& aRhs) {
210 return aLhs.get() == aRhs.get();
213 template <class T, class U>
214 inline bool operator!=(const StaticLocalRefPtr<T>& aLhs,
215 const StaticLocalRefPtr<U>& aRhs) {
216 return !(aLhs == aRhs);
219 REFLEXIVE_EQUALITY_OPERATORS(const StaticLocalRefPtr<T>&, const U*,
220 lhs.get() == rhs, class T, class U)
222 REFLEXIVE_EQUALITY_OPERATORS(const StaticLocalRefPtr<T>&, U*, lhs.get() == rhs,
223 class T, class U)
225 // Let us compare StaticLocalRefPtr to 0.
226 REFLEXIVE_EQUALITY_OPERATORS(const StaticLocalRefPtr<T>&,
227 StaticLocalPtr_internal::Zero*,
228 lhs.get() == nullptr, class T)
230 #undef REFLEXIVE_EQUALITY_OPERATORS
232 } // namespace mozilla
234 // Declared in mozilla/RefPtr.h
235 template <class T>
236 template <class U>
237 RefPtr<T>::RefPtr(const mozilla::StaticLocalRefPtr<U>& aOther)
238 : RefPtr(aOther.get()) {}
240 template <class T>
241 template <class U>
242 RefPtr<T>& RefPtr<T>::operator=(const mozilla::StaticLocalRefPtr<U>& aOther) {
243 return operator=(aOther.get());
246 template <class T>
247 inline already_AddRefed<T> do_AddRef(
248 const mozilla::StaticLocalRefPtr<T>& aObj) {
249 RefPtr<T> ref(aObj);
250 return ref.forget();
253 #endif // mozilla_StaticLocalPtr_h