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/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
* aRhs
)
57 T
* get() const { return mRawPtr
; }
59 operator T
*() const { return get(); }
67 T
& operator*() const { return *get(); }
70 // Disallow copy constructor, but only in debug mode. We only define
71 // a default constructor in debug mode (see above); if we declared
72 // this constructor always, the compiler wouldn't generate a trivial
73 // default constructor for us in non-debug mode.
75 StaticAutoPtr(StaticAutoPtr
<T
>& aOther
);
78 void Assign(T
* aNewPtr
)
80 MOZ_ASSERT(!aNewPtr
|| mRawPtr
!= aNewPtr
);
93 // In debug builds, check that mRawPtr is initialized for us as we expect
94 // by the compiler. In non-debug builds, don't declare a constructor
95 // so that the compiler can see that the constructor is trivial.
103 StaticRefPtr
<T
>& operator=(T
* aRhs
)
105 AssignWithAddref(aRhs
);
109 StaticRefPtr
<T
>& operator=(const StaticRefPtr
<T
>& aRhs
)
111 return (this = aRhs
.mRawPtr
);
114 T
* get() const { return mRawPtr
; }
116 operator T
*() const { return get(); }
118 T
* operator->() const
124 T
& operator*() const { return *get(); }
127 void AssignWithAddref(T
* aNewPtr
)
132 AssignAssumingAddRef(aNewPtr
);
135 void AssignAssumingAddRef(T
* aNewPtr
)
147 namespace StaticPtr_internal
{
149 } // namespace StaticPtr_internal
151 #define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \
152 template<__VA_ARGS__> \
154 operator==(type1 lhs, type2 rhs) \
159 template<__VA_ARGS__> \
161 operator==(type2 lhs, type1 rhs) \
166 template<__VA_ARGS__> \
168 operator!=(type1 lhs, type2 rhs) \
170 return !(lhs == rhs); \
173 template<__VA_ARGS__> \
175 operator!=(type2 lhs, type1 rhs) \
177 return !(lhs == rhs); \
180 // StaticAutoPtr (in)equality operators
182 template<class T
, class U
>
184 operator==(const StaticAutoPtr
<T
>& aLhs
, const StaticAutoPtr
<U
>& aRhs
)
186 return aLhs
.get() == aRhs
.get();
189 template<class T
, class U
>
191 operator!=(const StaticAutoPtr
<T
>& aLhs
, const StaticAutoPtr
<U
>& aRhs
)
193 return !(aLhs
== aRhs
);
196 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr
<T
>&, const U
*,
197 lhs
.get() == rhs
, class T
, class U
)
199 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr
<T
>&, U
*,
200 lhs
.get() == rhs
, class T
, class U
)
202 // Let us compare StaticAutoPtr to 0.
203 REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr
<T
>&, StaticPtr_internal::Zero
*,
204 lhs
.get() == nullptr, class T
)
206 // StaticRefPtr (in)equality operators
208 template<class T
, class U
>
210 operator==(const StaticRefPtr
<T
>& aLhs
, const StaticRefPtr
<U
>& aRhs
)
212 return aLhs
.get() == aRhs
.get();
215 template<class T
, class U
>
217 operator!=(const StaticRefPtr
<T
>& aLhs
, const StaticRefPtr
<U
>& aRhs
)
219 return !(aLhs
== aRhs
);
222 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr
<T
>&, const U
*,
223 lhs
.get() == rhs
, class T
, class U
)
225 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr
<T
>&, U
*,
226 lhs
.get() == rhs
, class T
, class U
)
228 // Let us compare StaticRefPtr to 0.
229 REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr
<T
>&, StaticPtr_internal::Zero
*,
230 lhs
.get() == nullptr, class T
)
232 #undef REFLEXIVE_EQUALITY_OPERATORS
234 } // namespace mozilla