• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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