1 /*
2 * Copyright (C) 2005 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ANDROID_STRONG_POINTER_H
18 #define ANDROID_STRONG_POINTER_H
19
20 #include <functional>
21 #include <type_traits> // for common_type.
22
23 // ---------------------------------------------------------------------------
24 namespace android {
25
26 template<typename T> class wp;
27
28 // ---------------------------------------------------------------------------
29
30 template<typename T>
31 class sp {
32 public:
sp()33 inline sp() : m_ptr(nullptr) { }
34
35 sp(T* other); // NOLINT(implicit)
36 sp(const sp<T>& other);
37 sp(sp<T>&& other) noexcept;
38 template<typename U> sp(U* other); // NOLINT(implicit)
39 template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
40 template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
41
42 ~sp();
43
44 // Assignment
45
46 sp& operator = (T* other);
47 sp& operator = (const sp<T>& other);
48 sp& operator=(sp<T>&& other) noexcept;
49
50 template<typename U> sp& operator = (const sp<U>& other);
51 template<typename U> sp& operator = (sp<U>&& other);
52 template<typename U> sp& operator = (U* other);
53
54 //! Special optimization for use by ProcessState (and nobody else).
55 void force_set(T* other);
56
57 // Reset
58
59 void clear();
60
61 // Accessors
62
63 inline T& operator* () const { return *m_ptr; }
64 inline T* operator-> () const { return m_ptr; }
get()65 inline T* get() const { return m_ptr; }
66 inline explicit operator bool () const { return m_ptr != nullptr; }
67
68 // Punt these to the wp<> implementation.
69 template<typename U>
70 inline bool operator == (const wp<U>& o) const {
71 return o == *this;
72 }
73
74 template<typename U>
75 inline bool operator != (const wp<U>& o) const {
76 return o != *this;
77 }
78
79 private:
80 template<typename Y> friend class sp;
81 template<typename Y> friend class wp;
82 void set_pointer(T* ptr);
83 static inline void check_not_on_stack(const void* ptr);
84 T* m_ptr;
85 };
86
87 #define COMPARE_STRONG(_op_) \
88 template <typename T, typename U> \
89 static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
90 return t.get() _op_ u.get(); \
91 } \
92 template <typename T, typename U> \
93 static inline bool operator _op_(const T* t, const sp<U>& u) { \
94 return t _op_ u.get(); \
95 } \
96 template <typename T, typename U> \
97 static inline bool operator _op_(const sp<T>& t, const U* u) { \
98 return t.get() _op_ u; \
99 } \
100 template <typename T> \
101 static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
102 return t.get() _op_ nullptr; \
103 } \
104 template <typename T> \
105 static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
106 return nullptr _op_ t.get(); \
107 }
108
109 template <template <typename C> class comparator, typename T, typename U>
_sp_compare_(T * a,U * b)110 static inline bool _sp_compare_(T* a, U* b) {
111 return comparator<typename std::common_type<T*, U*>::type>()(a, b);
112 }
113
114 #define COMPARE_STRONG_FUNCTIONAL(_op_, _compare_) \
115 template <typename T, typename U> \
116 static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
117 return _sp_compare_<_compare_>(t.get(), u.get()); \
118 } \
119 template <typename T, typename U> \
120 static inline bool operator _op_(const T* t, const sp<U>& u) { \
121 return _sp_compare_<_compare_>(t, u.get()); \
122 } \
123 template <typename T, typename U> \
124 static inline bool operator _op_(const sp<T>& t, const U* u) { \
125 return _sp_compare_<_compare_>(t.get(), u); \
126 } \
127 template <typename T> \
128 static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
129 return _sp_compare_<_compare_>(t.get(), nullptr); \
130 } \
131 template <typename T> \
132 static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
133 return _sp_compare_<_compare_>(nullptr, t.get()); \
134 }
135
136 COMPARE_STRONG(==)
137 COMPARE_STRONG(!=)
138 COMPARE_STRONG_FUNCTIONAL(>, std::greater)
139 COMPARE_STRONG_FUNCTIONAL(<, std::less)
140 COMPARE_STRONG_FUNCTIONAL(<=, std::less_equal)
141 COMPARE_STRONG_FUNCTIONAL(>=, std::greater_equal)
142
143 #undef COMPARE_STRONG
144 #undef COMPARE_STRONG_FUNCTIONAL
145
146 // For code size reasons, we do not want these inlined or templated.
147 void sp_report_race();
148 void sp_report_stack_pointer();
149
150 // ---------------------------------------------------------------------------
151 // No user serviceable parts below here.
152
153 // Check whether address is definitely on the calling stack. We actually check whether it is on
154 // the same 4K page as the frame pointer.
155 //
156 // Assumptions:
157 // - Pages are never smaller than 4K (MIN_PAGE_SIZE)
158 // - Malloced memory never shares a page with a stack.
159 //
160 // It does not appear safe to broaden this check to include adjacent pages; apparently this code
161 // is used in environments where there may not be a guard page below (at higher addresses than)
162 // the bottom of the stack.
163 //
164 // TODO: Consider adding make_sp<T>() to allocate an object and wrap the resulting pointer safely
165 // without checking overhead.
166 template <typename T>
check_not_on_stack(const void * ptr)167 void sp<T>::check_not_on_stack(const void* ptr) {
168 static constexpr int MIN_PAGE_SIZE = 0x1000; // 4K. Safer than including sys/user.h.
169 static constexpr uintptr_t MIN_PAGE_MASK = ~static_cast<uintptr_t>(MIN_PAGE_SIZE - 1);
170 uintptr_t my_frame_address =
171 reinterpret_cast<uintptr_t>(__builtin_frame_address(0 /* this frame */));
172 if (((reinterpret_cast<uintptr_t>(ptr) ^ my_frame_address) & MIN_PAGE_MASK) == 0) {
173 sp_report_stack_pointer();
174 }
175 }
176
177 template<typename T>
sp(T * other)178 sp<T>::sp(T* other)
179 : m_ptr(other) {
180 if (other) {
181 check_not_on_stack(other);
182 other->incStrong(this);
183 }
184 }
185
186 template<typename T>
sp(const sp<T> & other)187 sp<T>::sp(const sp<T>& other)
188 : m_ptr(other.m_ptr) {
189 if (m_ptr)
190 m_ptr->incStrong(this);
191 }
192
193 template <typename T>
sp(sp<T> && other)194 sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
195 other.m_ptr = nullptr;
196 }
197
198 template<typename T> template<typename U>
sp(U * other)199 sp<T>::sp(U* other)
200 : m_ptr(other) {
201 if (other) {
202 check_not_on_stack(other);
203 (static_cast<T*>(other))->incStrong(this);
204 }
205 }
206
207 template<typename T> template<typename U>
sp(const sp<U> & other)208 sp<T>::sp(const sp<U>& other)
209 : m_ptr(other.m_ptr) {
210 if (m_ptr)
211 m_ptr->incStrong(this);
212 }
213
214 template<typename T> template<typename U>
sp(sp<U> && other)215 sp<T>::sp(sp<U>&& other)
216 : m_ptr(other.m_ptr) {
217 other.m_ptr = nullptr;
218 }
219
220 template<typename T>
~sp()221 sp<T>::~sp() {
222 if (m_ptr)
223 m_ptr->decStrong(this);
224 }
225
226 template<typename T>
227 sp<T>& sp<T>::operator =(const sp<T>& other) {
228 // Force m_ptr to be read twice, to heuristically check for data races.
229 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
230 T* otherPtr(other.m_ptr);
231 if (otherPtr) otherPtr->incStrong(this);
232 if (oldPtr) oldPtr->decStrong(this);
233 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
234 m_ptr = otherPtr;
235 return *this;
236 }
237
238 template <typename T>
239 sp<T>& sp<T>::operator=(sp<T>&& other) noexcept {
240 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
241 if (oldPtr) oldPtr->decStrong(this);
242 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
243 m_ptr = other.m_ptr;
244 other.m_ptr = nullptr;
245 return *this;
246 }
247
248 template<typename T>
249 sp<T>& sp<T>::operator =(T* other) {
250 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
251 if (other) {
252 check_not_on_stack(other);
253 other->incStrong(this);
254 }
255 if (oldPtr) oldPtr->decStrong(this);
256 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
257 m_ptr = other;
258 return *this;
259 }
260
261 template<typename T> template<typename U>
262 sp<T>& sp<T>::operator =(const sp<U>& other) {
263 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
264 T* otherPtr(other.m_ptr);
265 if (otherPtr) otherPtr->incStrong(this);
266 if (oldPtr) oldPtr->decStrong(this);
267 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
268 m_ptr = otherPtr;
269 return *this;
270 }
271
272 template<typename T> template<typename U>
273 sp<T>& sp<T>::operator =(sp<U>&& other) {
274 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
275 if (m_ptr) m_ptr->decStrong(this);
276 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
277 m_ptr = other.m_ptr;
278 other.m_ptr = nullptr;
279 return *this;
280 }
281
282 template<typename T> template<typename U>
283 sp<T>& sp<T>::operator =(U* other) {
284 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
285 if (other) (static_cast<T*>(other))->incStrong(this);
286 if (oldPtr) oldPtr->decStrong(this);
287 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
288 m_ptr = other;
289 return *this;
290 }
291
292 template<typename T>
force_set(T * other)293 void sp<T>::force_set(T* other) {
294 other->forceIncStrong(this);
295 m_ptr = other;
296 }
297
298 template<typename T>
clear()299 void sp<T>::clear() {
300 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
301 if (oldPtr) {
302 oldPtr->decStrong(this);
303 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
304 m_ptr = nullptr;
305 }
306 }
307
308 template<typename T>
set_pointer(T * ptr)309 void sp<T>::set_pointer(T* ptr) {
310 m_ptr = ptr;
311 }
312
313 } // namespace android
314
315 // ---------------------------------------------------------------------------
316
317 #endif // ANDROID_STRONG_POINTER_H
318