1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et ft=cpp : */
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/Assertions.h"
11 #include "mozilla/NullPtr.h"
16 * StaticAutoPtr and StaticRefPtr are like nsAutoPtr and nsRefPtr, except they
17 * are suitable for use as global variables.
19 * In particular, a global instance of Static{Auto,Ref}Ptr doesn't cause the
20 * compiler to emit a static initializer (in release builds, anyway).
22 * In order to accomplish this, Static{Auto,Ref}Ptr must have a trivial
23 * constructor and destructor. As a consequence, it cannot initialize its raw
24 * pointer to 0 on construction, and it cannot delete/release its raw pointer
27 * Since the compiler guarantees that all global variables are initialized to
28 * 0, these trivial constructors are safe, so long as you use
29 * Static{Auto,Ref}Ptr as a global variable. If you use Static{Auto,Ref}Ptr as
30 * a stack variable or as a class instance variable, you will get what you
33 * Static{Auto,Ref}Ptr have a limited interface as compared to ns{Auto,Ref}Ptr;
34 * this is intentional, since their range of acceptable uses is smaller.
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.
51 StaticAutoPtr
<T
>& operator=(T
* rhs
)
79 // Disallow copy constructor, but only in debug mode. We only define
80 // a default constructor in debug mode (see above); if we declared
81 // this constructor always, the compiler wouldn't generate a trivial
82 // default constructor for us in non-debug mode.
84 StaticAutoPtr(StaticAutoPtr
<T
> &other
);
87 void Assign(T
* newPtr
)
89 MOZ_ASSERT(!newPtr
|| mRawPtr
!= newPtr
);
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.
108 MOZ_ASSERT(!mRawPtr
);
112 StaticRefPtr
<T
>& operator=(T
* rhs
)
114 AssignWithAddref(rhs
);
118 StaticRefPtr
<T
>& operator=(const StaticRefPtr
<T
>& rhs
)
120 return (this = rhs
.mRawPtr
);
133 T
* operator->() const
145 void AssignWithAddref(T
* newPtr
)
150 AssignAssumingAddRef(newPtr
);
153 void AssignAssumingAddRef(T
* newPtr
)
165 namespace StaticPtr_internal
{
167 } // namespace StaticPtr_internal
169 #define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \
170 template<__VA_ARGS__> \
172 operator==(type1 lhs, type2 rhs) \
177 template<__VA_ARGS__> \
179 operator==(type2 lhs, type1 rhs) \
184 template<__VA_ARGS__> \
186 operator!=(type1 lhs, type2 rhs) \
188 return !(lhs == rhs); \
191 template<__VA_ARGS__> \
193 operator!=(type2 lhs, type1 rhs) \
195 return !(lhs == rhs); \
198 // StaticAutoPtr (in)equality operators
200 template<class T
, class U
>
202 operator==(const StaticAutoPtr
<T
>& lhs
, const StaticAutoPtr
<U
>& rhs
)
204 return lhs
.get() == rhs
.get();
207 template<class T
, class U
>
209 operator!=(const StaticAutoPtr
<T
>& lhs
, const StaticAutoPtr
<U
>& rhs
)
211 return !(lhs
== rhs
);
214 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr
<T
>&, const U
*,
215 lhs
.get() == rhs
, class T
, class U
)
217 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr
<T
>&, U
*,
218 lhs
.get() == rhs
, class T
, class U
)
220 // Let us compare StaticAutoPtr to 0.
221 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr
<T
>&, StaticPtr_internal::Zero
*,
222 lhs
.get() == nullptr, class T
)
224 // StaticRefPtr (in)equality operators
226 template<class T
, class U
>
228 operator==(const StaticRefPtr
<T
>& lhs
, const StaticRefPtr
<U
>& rhs
)
230 return lhs
.get() == rhs
.get();
233 template<class T
, class U
>
235 operator!=(const StaticRefPtr
<T
>& lhs
, const StaticRefPtr
<U
>& rhs
)
237 return !(lhs
== rhs
);
240 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr
<T
>&, const U
*,
241 lhs
.get() == rhs
, class T
, class U
)
243 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr
<T
>&, U
*,
244 lhs
.get() == rhs
, class T
, class U
)
246 // Let us compare StaticRefPtr to 0.
247 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr
<T
>&, StaticPtr_internal::Zero
*,
248 lhs
.get() == nullptr, class T
)
250 #undef REFLEXIVE_EQUALITY_OPERATORS
252 } // namespace mozilla