blob: 15711296dcfce80f0dc55568fd0bf9911aa1b1d6 [file] [log] [blame]
Mathias Agopianb26ea8b2011-02-16 20:23:43 -08001/*
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
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080020// ---------------------------------------------------------------------------
21namespace android {
22
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080023template<typename T> class wp;
24
25// ---------------------------------------------------------------------------
26
27#define COMPARE(_op_) \
28inline bool operator _op_ (const sp<T>& o) const { \
29 return m_ptr _op_ o.m_ptr; \
30} \
31inline bool operator _op_ (const T* o) const { \
32 return m_ptr _op_ o; \
33} \
34template<typename U> \
35inline bool operator _op_ (const sp<U>& o) const { \
36 return m_ptr _op_ o.m_ptr; \
37} \
38template<typename U> \
39inline bool operator _op_ (const U* o) const { \
40 return m_ptr _op_ o; \
41} \
42inline bool operator _op_ (const wp<T>& o) const { \
43 return m_ptr _op_ o.m_ptr; \
44} \
45template<typename U> \
46inline bool operator _op_ (const wp<U>& o) const { \
47 return m_ptr _op_ o.m_ptr; \
48}
49
50// ---------------------------------------------------------------------------
51
Mathias Agopian8db925f2013-05-09 13:04:32 -070052template<typename T>
53class sp {
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080054public:
Yi Kongc1a15622018-07-11 17:37:34 -070055 inline sp() : m_ptr(nullptr) { }
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080056
Chih-Hung Hsieh2a929962016-08-02 12:14:47 -070057 sp(T* other); // NOLINT(implicit)
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080058 sp(const sp<T>& other);
Chih-Hung Hsieh747eb142018-09-25 11:16:22 -070059 sp(sp<T>&& other) noexcept;
Chih-Hung Hsieh2a929962016-08-02 12:14:47 -070060 template<typename U> sp(U* other); // NOLINT(implicit)
61 template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
62 template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080063
64 ~sp();
65
66 // Assignment
67
68 sp& operator = (T* other);
69 sp& operator = (const sp<T>& other);
Chih-Hung Hsieh747eb142018-09-25 11:16:22 -070070 sp& operator=(sp<T>&& other) noexcept;
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080071
72 template<typename U> sp& operator = (const sp<U>& other);
John Reckd69089a2015-10-28 15:36:33 -070073 template<typename U> sp& operator = (sp<U>&& other);
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080074 template<typename U> sp& operator = (U* other);
75
76 //! Special optimization for use by ProcessState (and nobody else).
77 void force_set(T* other);
78
79 // Reset
80
81 void clear();
82
83 // Accessors
84
Jeff Sharkey147b8812017-09-13 11:04:06 -060085 inline T& operator* () const { return *m_ptr; }
86 inline T* operator-> () const { return m_ptr; }
87 inline T* get() const { return m_ptr; }
88 inline explicit operator bool () const { return m_ptr != nullptr; }
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080089
90 // Operators
91
92 COMPARE(==)
93 COMPARE(!=)
94 COMPARE(>)
95 COMPARE(<)
96 COMPARE(<=)
97 COMPARE(>=)
98
99private:
100 template<typename Y> friend class sp;
101 template<typename Y> friend class wp;
Mathias Agopian3e0f8752011-02-24 18:12:34 -0800102 void set_pointer(T* ptr);
103 T* m_ptr;
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800104};
105
Hans Boehm7f0b2602017-03-15 11:01:03 -0700106// For code size reasons, we do not want this inlined or templated.
107void sp_report_race();
108
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800109#undef COMPARE
110
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800111// ---------------------------------------------------------------------------
112// No user serviceable parts below here.
113
114template<typename T>
115sp<T>::sp(T* other)
Mathias Agopian8db925f2013-05-09 13:04:32 -0700116 : m_ptr(other) {
117 if (other)
118 other->incStrong(this);
119}
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800120
121template<typename T>
122sp<T>::sp(const sp<T>& other)
Mathias Agopian8db925f2013-05-09 13:04:32 -0700123 : m_ptr(other.m_ptr) {
124 if (m_ptr)
125 m_ptr->incStrong(this);
126}
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800127
Chih-Hung Hsieh747eb142018-09-25 11:16:22 -0700128template <typename T>
129sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
John Reckd69089a2015-10-28 15:36:33 -0700130 other.m_ptr = nullptr;
131}
132
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800133template<typename T> template<typename U>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700134sp<T>::sp(U* other)
135 : m_ptr(other) {
136 if (other)
Colin Cross17b5b822016-09-15 18:15:37 -0700137 (static_cast<T*>(other))->incStrong(this);
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800138}
139
140template<typename T> template<typename U>
141sp<T>::sp(const sp<U>& other)
Mathias Agopian8db925f2013-05-09 13:04:32 -0700142 : m_ptr(other.m_ptr) {
143 if (m_ptr)
144 m_ptr->incStrong(this);
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800145}
146
John Reckd69089a2015-10-28 15:36:33 -0700147template<typename T> template<typename U>
148sp<T>::sp(sp<U>&& other)
149 : m_ptr(other.m_ptr) {
150 other.m_ptr = nullptr;
151}
152
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800153template<typename T>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700154sp<T>::~sp() {
155 if (m_ptr)
156 m_ptr->decStrong(this);
157}
158
159template<typename T>
160sp<T>& sp<T>::operator =(const sp<T>& other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700161 // Force m_ptr to be read twice, to heuristically check for data races.
162 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800163 T* otherPtr(other.m_ptr);
Hans Boehm7f0b2602017-03-15 11:01:03 -0700164 if (otherPtr) otherPtr->incStrong(this);
165 if (oldPtr) oldPtr->decStrong(this);
166 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800167 m_ptr = otherPtr;
168 return *this;
169}
170
Chih-Hung Hsieh747eb142018-09-25 11:16:22 -0700171template <typename T>
172sp<T>& sp<T>::operator=(sp<T>&& other) noexcept {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700173 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
174 if (oldPtr) oldPtr->decStrong(this);
175 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
John Reckd69089a2015-10-28 15:36:33 -0700176 m_ptr = other.m_ptr;
177 other.m_ptr = nullptr;
178 return *this;
179}
180
181template<typename T>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700182sp<T>& sp<T>::operator =(T* other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700183 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
184 if (other) other->incStrong(this);
185 if (oldPtr) oldPtr->decStrong(this);
186 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800187 m_ptr = other;
188 return *this;
189}
190
191template<typename T> template<typename U>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700192sp<T>& sp<T>::operator =(const sp<U>& other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700193 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
Mathias Agopian7332f802011-02-25 16:11:44 -0800194 T* otherPtr(other.m_ptr);
Hans Boehm7f0b2602017-03-15 11:01:03 -0700195 if (otherPtr) otherPtr->incStrong(this);
196 if (oldPtr) oldPtr->decStrong(this);
197 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800198 m_ptr = otherPtr;
199 return *this;
200}
201
202template<typename T> template<typename U>
John Reckd69089a2015-10-28 15:36:33 -0700203sp<T>& sp<T>::operator =(sp<U>&& other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700204 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
205 if (m_ptr) m_ptr->decStrong(this);
206 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
John Reckd69089a2015-10-28 15:36:33 -0700207 m_ptr = other.m_ptr;
208 other.m_ptr = nullptr;
209 return *this;
210}
211
212template<typename T> template<typename U>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700213sp<T>& sp<T>::operator =(U* other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700214 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
215 if (other) (static_cast<T*>(other))->incStrong(this);
216 if (oldPtr) oldPtr->decStrong(this);
217 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800218 m_ptr = other;
219 return *this;
220}
221
Mathias Agopian8db925f2013-05-09 13:04:32 -0700222template<typename T>
223void sp<T>::force_set(T* other) {
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800224 other->forceIncStrong(this);
225 m_ptr = other;
226}
227
228template<typename T>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700229void sp<T>::clear() {
Hans Boehmf4f76202018-08-17 11:40:39 -0700230 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
231 if (oldPtr) {
232 oldPtr->decStrong(this);
233 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
Yi Kongc1a15622018-07-11 17:37:34 -0700234 m_ptr = nullptr;
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800235 }
236}
237
238template<typename T>
Mathias Agopian3e0f8752011-02-24 18:12:34 -0800239void sp<T>::set_pointer(T* ptr) {
240 m_ptr = ptr;
241}
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800242
Pirama Arumuga Nainareab48ce2018-04-10 14:31:29 -0700243} // namespace android
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800244
245// ---------------------------------------------------------------------------
246
247#endif // ANDROID_STRONG_POINTER_H