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)114sp<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)121sp<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)128sp<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)134sp<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)141sp<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)148sp<T>::sp(sp<U>&& other) 149 : m_ptr(other.m_ptr) { 150 other.m_ptr = nullptr; 151 } 152 153 template<typename T> ~sp()154sp<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)223void sp<T>::force_set(T* other) { 224 other->forceIncStrong(this); 225 m_ptr = other; 226 } 227 228 template<typename T> clear()229void 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)237void 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