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 // ---------------------------------------------------------------------------
21 namespace android {
22 
23 template<typename T> class wp;
24 
25 // ---------------------------------------------------------------------------
26 
27 #define COMPARE(_op_)                                           \
28 inline bool operator _op_ (const sp<T>& o) const {              \
29     return m_ptr _op_ o.m_ptr;                                  \
30 }                                                               \
31 inline bool operator _op_ (const T* o) const {                  \
32     return m_ptr _op_ o;                                        \
33 }                                                               \
34 template<typename U>                                            \
35 inline bool operator _op_ (const sp<U>& o) const {              \
36     return m_ptr _op_ o.m_ptr;                                  \
37 }                                                               \
38 template<typename U>                                            \
39 inline bool operator _op_ (const U* o) const {                  \
40     return m_ptr _op_ o;                                        \
41 }                                                               \
42 inline bool operator _op_ (const wp<T>& o) const {              \
43     return m_ptr _op_ o.m_ptr;                                  \
44 }                                                               \
45 template<typename U>                                            \
46 inline bool operator _op_ (const wp<U>& o) const {              \
47     return m_ptr _op_ o.m_ptr;                                  \
48 }
49 
50 // ---------------------------------------------------------------------------
51 
52 template<typename T>
53 class sp {
54 public:
sp()55     inline sp() : m_ptr(0) { }
56 
57     sp(T* other);  // NOLINT(implicit)
58     sp(const sp<T>& other);
59     sp(sp<T>&& other);
60     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)
63 
64     ~sp();
65 
66     // Assignment
67 
68     sp& operator = (T* other);
69     sp& operator = (const sp<T>& other);
70     sp& operator = (sp<T>&& other);
71 
72     template<typename U> sp& operator = (const sp<U>& other);
73     template<typename U> sp& operator = (sp<U>&& other);
74     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 
85     inline  T&      operator* () const  { return *m_ptr; }
86     inline  T*      operator-> () const { return m_ptr;  }
get()87     inline  T*      get() const         { return m_ptr; }
88 
89     // Operators
90 
91     COMPARE(==)
92     COMPARE(!=)
93     COMPARE(>)
94     COMPARE(<)
95     COMPARE(<=)
96     COMPARE(>=)
97 
98 private:
99     template<typename Y> friend class sp;
100     template<typename Y> friend class wp;
101     void set_pointer(T* ptr);
102     T* m_ptr;
103 };
104 
105 // For code size reasons, we do not want this inlined or templated.
106 void sp_report_race();
107 
108 #undef COMPARE
109 
110 // ---------------------------------------------------------------------------
111 // No user serviceable parts below here.
112 
113 template<typename T>
sp(T * other)114 sp<T>::sp(T* other)
115         : m_ptr(other) {
116     if (other)
117         other->incStrong(this);
118 }
119 
120 template<typename T>
sp(const sp<T> & other)121 sp<T>::sp(const sp<T>& other)
122         : m_ptr(other.m_ptr) {
123     if (m_ptr)
124         m_ptr->incStrong(this);
125 }
126 
127 template<typename T>
sp(sp<T> && other)128 sp<T>::sp(sp<T>&& other)
129         : m_ptr(other.m_ptr) {
130     other.m_ptr = nullptr;
131 }
132 
133 template<typename T> template<typename U>
sp(U * other)134 sp<T>::sp(U* other)
135         : m_ptr(other) {
136     if (other)
137         (static_cast<T*>(other))->incStrong(this);
138 }
139 
140 template<typename T> template<typename U>
sp(const sp<U> & other)141 sp<T>::sp(const sp<U>& other)
142         : m_ptr(other.m_ptr) {
143     if (m_ptr)
144         m_ptr->incStrong(this);
145 }
146 
147 template<typename T> template<typename U>
sp(sp<U> && other)148 sp<T>::sp(sp<U>&& other)
149         : m_ptr(other.m_ptr) {
150     other.m_ptr = nullptr;
151 }
152 
153 template<typename T>
~sp()154 sp<T>::~sp() {
155     if (m_ptr)
156         m_ptr->decStrong(this);
157 }
158 
159 template<typename T>
160 sp<T>& sp<T>::operator =(const sp<T>& other) {
161     // Force m_ptr to be read twice, to heuristically check for data races.
162     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
163     T* otherPtr(other.m_ptr);
164     if (otherPtr) otherPtr->incStrong(this);
165     if (oldPtr) oldPtr->decStrong(this);
166     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
167     m_ptr = otherPtr;
168     return *this;
169 }
170 
171 template<typename T>
172 sp<T>& sp<T>::operator =(sp<T>&& other) {
173     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();
176     m_ptr = other.m_ptr;
177     other.m_ptr = nullptr;
178     return *this;
179 }
180 
181 template<typename T>
182 sp<T>& sp<T>::operator =(T* other) {
183     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();
187     m_ptr = other;
188     return *this;
189 }
190 
191 template<typename T> template<typename U>
192 sp<T>& sp<T>::operator =(const sp<U>& other) {
193     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
194     T* otherPtr(other.m_ptr);
195     if (otherPtr) otherPtr->incStrong(this);
196     if (oldPtr) oldPtr->decStrong(this);
197     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
198     m_ptr = otherPtr;
199     return *this;
200 }
201 
202 template<typename T> template<typename U>
203 sp<T>& sp<T>::operator =(sp<U>&& other) {
204     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();
207     m_ptr = other.m_ptr;
208     other.m_ptr = nullptr;
209     return *this;
210 }
211 
212 template<typename T> template<typename U>
213 sp<T>& sp<T>::operator =(U* other) {
214     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();
218     m_ptr = other;
219     return *this;
220 }
221 
222 template<typename T>
force_set(T * other)223 void sp<T>::force_set(T* other) {
224     other->forceIncStrong(this);
225     m_ptr = other;
226 }
227 
228 template<typename T>
clear()229 void sp<T>::clear() {
230     if (m_ptr) {
231         m_ptr->decStrong(this);
232         m_ptr = 0;
233     }
234 }
235 
236 template<typename T>
set_pointer(T * ptr)237 void sp<T>::set_pointer(T* ptr) {
238     m_ptr = ptr;
239 }
240 
241 }; // namespace android
242 
243 // ---------------------------------------------------------------------------
244 
245 #endif // ANDROID_STRONG_POINTER_H
246