• 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 // ---------------------------------------------------------------------------
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     inline explicit operator bool () const { return m_ptr != nullptr; }
89 
90     // Operators
91 
92     COMPARE(==)
93     COMPARE(!=)
94     COMPARE(>)
95     COMPARE(<)
96     COMPARE(<=)
97     COMPARE(>=)
98 
99 private:
100     template<typename Y> friend class sp;
101     template<typename Y> friend class wp;
102     void set_pointer(T* ptr);
103     T* m_ptr;
104 };
105 
106 // For code size reasons, we do not want this inlined or templated.
107 void sp_report_race();
108 
109 #undef COMPARE
110 
111 // ---------------------------------------------------------------------------
112 // No user serviceable parts below here.
113 
114 template<typename T>
sp(T * other)115 sp<T>::sp(T* other)
116         : m_ptr(other) {
117     if (other)
118         other->incStrong(this);
119 }
120 
121 template<typename T>
sp(const sp<T> & other)122 sp<T>::sp(const sp<T>& other)
123         : m_ptr(other.m_ptr) {
124     if (m_ptr)
125         m_ptr->incStrong(this);
126 }
127 
128 template<typename T>
sp(sp<T> && other)129 sp<T>::sp(sp<T>&& other)
130         : m_ptr(other.m_ptr) {
131     other.m_ptr = nullptr;
132 }
133 
134 template<typename T> template<typename U>
sp(U * other)135 sp<T>::sp(U* other)
136         : m_ptr(other) {
137     if (other)
138         (static_cast<T*>(other))->incStrong(this);
139 }
140 
141 template<typename T> template<typename U>
sp(const sp<U> & other)142 sp<T>::sp(const sp<U>& other)
143         : m_ptr(other.m_ptr) {
144     if (m_ptr)
145         m_ptr->incStrong(this);
146 }
147 
148 template<typename T> template<typename U>
sp(sp<U> && other)149 sp<T>::sp(sp<U>&& other)
150         : m_ptr(other.m_ptr) {
151     other.m_ptr = nullptr;
152 }
153 
154 template<typename T>
~sp()155 sp<T>::~sp() {
156     if (m_ptr)
157         m_ptr->decStrong(this);
158 }
159 
160 template<typename T>
161 sp<T>& sp<T>::operator =(const sp<T>& other) {
162     // Force m_ptr to be read twice, to heuristically check for data races.
163     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
164     T* otherPtr(other.m_ptr);
165     if (otherPtr) otherPtr->incStrong(this);
166     if (oldPtr) oldPtr->decStrong(this);
167     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
168     m_ptr = otherPtr;
169     return *this;
170 }
171 
172 template<typename T>
173 sp<T>& sp<T>::operator =(sp<T>&& other) {
174     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
175     if (oldPtr) oldPtr->decStrong(this);
176     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
177     m_ptr = other.m_ptr;
178     other.m_ptr = nullptr;
179     return *this;
180 }
181 
182 template<typename T>
183 sp<T>& sp<T>::operator =(T* other) {
184     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
185     if (other) other->incStrong(this);
186     if (oldPtr) oldPtr->decStrong(this);
187     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
188     m_ptr = other;
189     return *this;
190 }
191 
192 template<typename T> template<typename U>
193 sp<T>& sp<T>::operator =(const sp<U>& other) {
194     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
195     T* otherPtr(other.m_ptr);
196     if (otherPtr) otherPtr->incStrong(this);
197     if (oldPtr) oldPtr->decStrong(this);
198     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
199     m_ptr = otherPtr;
200     return *this;
201 }
202 
203 template<typename T> template<typename U>
204 sp<T>& sp<T>::operator =(sp<U>&& other) {
205     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
206     if (m_ptr) m_ptr->decStrong(this);
207     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
208     m_ptr = other.m_ptr;
209     other.m_ptr = nullptr;
210     return *this;
211 }
212 
213 template<typename T> template<typename U>
214 sp<T>& sp<T>::operator =(U* other) {
215     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
216     if (other) (static_cast<T*>(other))->incStrong(this);
217     if (oldPtr) oldPtr->decStrong(this);
218     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
219     m_ptr = other;
220     return *this;
221 }
222 
223 template<typename T>
force_set(T * other)224 void sp<T>::force_set(T* other) {
225     other->forceIncStrong(this);
226     m_ptr = other;
227 }
228 
229 template<typename T>
clear()230 void sp<T>::clear() {
231     if (m_ptr) {
232         m_ptr->decStrong(this);
233         m_ptr = 0;
234     }
235 }
236 
237 template<typename T>
set_pointer(T * ptr)238 void sp<T>::set_pointer(T* ptr) {
239     m_ptr = ptr;
240 }
241 
242 }; // namespace android
243 
244 // ---------------------------------------------------------------------------
245 
246 #endif // ANDROID_STRONG_POINTER_H
247