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: 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; } 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> 115 sp<T>::sp(T* other) 116 : m_ptr(other) { 117 if (other) 118 other->incStrong(this); 119 } 120 121 template<typename T> 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> 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> 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> 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> 149 sp<T>::sp(sp<U>&& other) 150 : m_ptr(other.m_ptr) { 151 other.m_ptr = nullptr; 152 } 153 154 template<typename T> 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> 224 void sp<T>::force_set(T* other) { 225 other->forceIncStrong(this); 226 m_ptr = other; 227 } 228 229 template<typename T> 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> 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