RefBase.h revision 1b2c2a9ea0108cd182a56c47997ec68ee8de02b3
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_REF_BASE_H 18#define ANDROID_REF_BASE_H 19 20#include <cutils/atomic.h> 21 22#include <stdint.h> 23#include <sys/types.h> 24#include <stdlib.h> 25#include <string.h> 26 27#include <utils/StrongPointer.h> 28 29// --------------------------------------------------------------------------- 30namespace android { 31 32class TextOutput; 33TextOutput& printWeakPointer(TextOutput& to, const void* val); 34 35// --------------------------------------------------------------------------- 36 37#define COMPARE_WEAK(_op_) \ 38inline bool operator _op_ (const sp<T>& o) const { \ 39 return m_ptr _op_ o.m_ptr; \ 40} \ 41inline bool operator _op_ (const T* o) const { \ 42 return m_ptr _op_ o; \ 43} \ 44template<typename U> \ 45inline bool operator _op_ (const sp<U>& o) const { \ 46 return m_ptr _op_ o.m_ptr; \ 47} \ 48template<typename U> \ 49inline bool operator _op_ (const U* o) const { \ 50 return m_ptr _op_ o; \ 51} 52 53// --------------------------------------------------------------------------- 54 55class ReferenceMover; 56class ReferenceConverterBase { 57public: 58 virtual size_t getReferenceTypeSize() const = 0; 59 virtual void* getReferenceBase(void const*) const = 0; 60 inline virtual ~ReferenceConverterBase() { } 61}; 62 63// --------------------------------------------------------------------------- 64 65class RefBase 66{ 67public: 68 void incStrong(const void* id) const; 69 void decStrong(const void* id) const; 70 71 void forceIncStrong(const void* id) const; 72 73 //! DEBUGGING ONLY: Get current strong ref count. 74 int32_t getStrongCount() const; 75 76 class weakref_type 77 { 78 public: 79 RefBase* refBase() const; 80 81 void incWeak(const void* id); 82 void decWeak(const void* id); 83 84 bool attemptIncStrong(const void* id); 85 86 //! This is only safe if you have set OBJECT_LIFETIME_FOREVER. 87 bool attemptIncWeak(const void* id); 88 89 //! DEBUGGING ONLY: Get current weak ref count. 90 int32_t getWeakCount() const; 91 92 //! DEBUGGING ONLY: Print references held on object. 93 void printRefs() const; 94 95 //! DEBUGGING ONLY: Enable tracking for this object. 96 // enable -- enable/disable tracking 97 // retain -- when tracking is enable, if true, then we save a stack trace 98 // for each reference and dereference; when retain == false, we 99 // match up references and dereferences and keep only the 100 // outstanding ones. 101 102 void trackMe(bool enable, bool retain); 103 }; 104 105 weakref_type* createWeak(const void* id) const; 106 107 weakref_type* getWeakRefs() const; 108 109 //! DEBUGGING ONLY: Print references held on object. 110 inline void printRefs() const { getWeakRefs()->printRefs(); } 111 112 //! DEBUGGING ONLY: Enable tracking of object. 113 inline void trackMe(bool enable, bool retain) 114 { 115 getWeakRefs()->trackMe(enable, retain); 116 } 117 118 typedef RefBase basetype; 119 120protected: 121 RefBase(); 122 virtual ~RefBase(); 123 124 //! Flags for extendObjectLifetime() 125 enum { 126 OBJECT_LIFETIME_WEAK = 0x0001, 127 OBJECT_LIFETIME_FOREVER = 0x0003 128 }; 129 130 void extendObjectLifetime(int32_t mode); 131 132 //! Flags for onIncStrongAttempted() 133 enum { 134 FIRST_INC_STRONG = 0x0001 135 }; 136 137 virtual void onFirstRef(); 138 virtual void onLastStrongRef(const void* id); 139 virtual bool onIncStrongAttempted(uint32_t flags, const void* id); 140 virtual void onLastWeakRef(const void* id); 141 142private: 143 friend class ReferenceMover; 144 static void moveReferences(void* d, void const* s, size_t n, 145 const ReferenceConverterBase& caster); 146 147private: 148 friend class weakref_type; 149 class weakref_impl; 150 151 RefBase(const RefBase& o); 152 RefBase& operator=(const RefBase& o); 153 154 weakref_impl* const mRefs; 155}; 156 157// --------------------------------------------------------------------------- 158 159template <class T> 160class LightRefBase 161{ 162public: 163 inline LightRefBase() : mCount(0) { } 164 inline void incStrong(const void* id) const { 165 android_atomic_inc(&mCount); 166 } 167 inline void decStrong(const void* id) const { 168 if (android_atomic_dec(&mCount) == 1) { 169 delete static_cast<const T*>(this); 170 } 171 } 172 //! DEBUGGING ONLY: Get current strong ref count. 173 inline int32_t getStrongCount() const { 174 return mCount; 175 } 176 177 typedef LightRefBase<T> basetype; 178 179protected: 180 inline ~LightRefBase() { } 181 182private: 183 friend class ReferenceMover; 184 inline static void moveReferences(void* d, void const* s, size_t n, 185 const ReferenceConverterBase& caster) { } 186 187private: 188 mutable volatile int32_t mCount; 189}; 190 191// --------------------------------------------------------------------------- 192 193template <typename T> 194class wp 195{ 196public: 197 typedef typename RefBase::weakref_type weakref_type; 198 199 inline wp() : m_ptr(0) { } 200 201 wp(T* other); 202 wp(const wp<T>& other); 203 wp(const sp<T>& other); 204 template<typename U> wp(U* other); 205 template<typename U> wp(const sp<U>& other); 206 template<typename U> wp(const wp<U>& other); 207 208 ~wp(); 209 210 // Assignment 211 212 wp& operator = (T* other); 213 wp& operator = (const wp<T>& other); 214 wp& operator = (const sp<T>& other); 215 216 template<typename U> wp& operator = (U* other); 217 template<typename U> wp& operator = (const wp<U>& other); 218 template<typename U> wp& operator = (const sp<U>& other); 219 220 void set_object_and_refs(T* other, weakref_type* refs); 221 222 // promotion to sp 223 224 sp<T> promote() const; 225 226 // Reset 227 228 void clear(); 229 230 // Accessors 231 232 inline weakref_type* get_refs() const { return m_refs; } 233 234 inline T* unsafe_get() const { return m_ptr; } 235 236 // Operators 237 238 COMPARE_WEAK(==) 239 COMPARE_WEAK(!=) 240 COMPARE_WEAK(>) 241 COMPARE_WEAK(<) 242 COMPARE_WEAK(<=) 243 COMPARE_WEAK(>=) 244 245 inline bool operator == (const wp<T>& o) const { 246 return (m_ptr == o.m_ptr) && (m_refs == o.m_refs); 247 } 248 template<typename U> 249 inline bool operator == (const wp<U>& o) const { 250 return m_ptr == o.m_ptr; 251 } 252 253 inline bool operator > (const wp<T>& o) const { 254 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); 255 } 256 template<typename U> 257 inline bool operator > (const wp<U>& o) const { 258 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); 259 } 260 261 inline bool operator < (const wp<T>& o) const { 262 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); 263 } 264 template<typename U> 265 inline bool operator < (const wp<U>& o) const { 266 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); 267 } 268 inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; } 269 template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); } 270 inline bool operator <= (const wp<T>& o) const { return !operator > (o); } 271 template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); } 272 inline bool operator >= (const wp<T>& o) const { return !operator < (o); } 273 template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); } 274 275private: 276 template<typename Y> friend class sp; 277 template<typename Y> friend class wp; 278 279 T* m_ptr; 280 weakref_type* m_refs; 281}; 282 283template <typename T> 284TextOutput& operator<<(TextOutput& to, const wp<T>& val); 285 286#undef COMPARE_WEAK 287 288// --------------------------------------------------------------------------- 289// No user serviceable parts below here. 290 291template<typename T> 292wp<T>::wp(T* other) 293 : m_ptr(other) 294{ 295 if (other) m_refs = other->createWeak(this); 296} 297 298template<typename T> 299wp<T>::wp(const wp<T>& other) 300 : m_ptr(other.m_ptr), m_refs(other.m_refs) 301{ 302 if (m_ptr) m_refs->incWeak(this); 303} 304 305template<typename T> 306wp<T>::wp(const sp<T>& other) 307 : m_ptr(other.m_ptr) 308{ 309 if (m_ptr) { 310 m_refs = m_ptr->createWeak(this); 311 } 312} 313 314template<typename T> template<typename U> 315wp<T>::wp(U* other) 316 : m_ptr(other) 317{ 318 if (other) m_refs = other->createWeak(this); 319} 320 321template<typename T> template<typename U> 322wp<T>::wp(const wp<U>& other) 323 : m_ptr(other.m_ptr) 324{ 325 if (m_ptr) { 326 m_refs = other.m_refs; 327 m_refs->incWeak(this); 328 } 329} 330 331template<typename T> template<typename U> 332wp<T>::wp(const sp<U>& other) 333 : m_ptr(other.m_ptr) 334{ 335 if (m_ptr) { 336 m_refs = m_ptr->createWeak(this); 337 } 338} 339 340template<typename T> 341wp<T>::~wp() 342{ 343 if (m_ptr) m_refs->decWeak(this); 344} 345 346template<typename T> 347wp<T>& wp<T>::operator = (T* other) 348{ 349 weakref_type* newRefs = 350 other ? other->createWeak(this) : 0; 351 if (m_ptr) m_refs->decWeak(this); 352 m_ptr = other; 353 m_refs = newRefs; 354 return *this; 355} 356 357template<typename T> 358wp<T>& wp<T>::operator = (const wp<T>& other) 359{ 360 weakref_type* otherRefs(other.m_refs); 361 T* otherPtr(other.m_ptr); 362 if (otherPtr) otherRefs->incWeak(this); 363 if (m_ptr) m_refs->decWeak(this); 364 m_ptr = otherPtr; 365 m_refs = otherRefs; 366 return *this; 367} 368 369template<typename T> 370wp<T>& wp<T>::operator = (const sp<T>& other) 371{ 372 weakref_type* newRefs = 373 other != NULL ? other->createWeak(this) : 0; 374 T* otherPtr(other.m_ptr); 375 if (m_ptr) m_refs->decWeak(this); 376 m_ptr = otherPtr; 377 m_refs = newRefs; 378 return *this; 379} 380 381template<typename T> template<typename U> 382wp<T>& wp<T>::operator = (U* other) 383{ 384 weakref_type* newRefs = 385 other ? other->createWeak(this) : 0; 386 if (m_ptr) m_refs->decWeak(this); 387 m_ptr = other; 388 m_refs = newRefs; 389 return *this; 390} 391 392template<typename T> template<typename U> 393wp<T>& wp<T>::operator = (const wp<U>& other) 394{ 395 weakref_type* otherRefs(other.m_refs); 396 U* otherPtr(other.m_ptr); 397 if (otherPtr) otherRefs->incWeak(this); 398 if (m_ptr) m_refs->decWeak(this); 399 m_ptr = otherPtr; 400 m_refs = otherRefs; 401 return *this; 402} 403 404template<typename T> template<typename U> 405wp<T>& wp<T>::operator = (const sp<U>& other) 406{ 407 weakref_type* newRefs = 408 other != NULL ? other->createWeak(this) : 0; 409 U* otherPtr(other.m_ptr); 410 if (m_ptr) m_refs->decWeak(this); 411 m_ptr = otherPtr; 412 m_refs = newRefs; 413 return *this; 414} 415 416template<typename T> 417void wp<T>::set_object_and_refs(T* other, weakref_type* refs) 418{ 419 if (other) refs->incWeak(this); 420 if (m_ptr) m_refs->decWeak(this); 421 m_ptr = other; 422 m_refs = refs; 423} 424 425template<typename T> 426sp<T> wp<T>::promote() const 427{ 428 sp<T> result; 429 if (m_ptr && m_refs->attemptIncStrong(&result)) { 430 result.set_pointer(m_ptr); 431 } 432 return result; 433} 434 435template<typename T> 436void wp<T>::clear() 437{ 438 if (m_ptr) { 439 m_refs->decWeak(this); 440 m_ptr = 0; 441 } 442} 443 444template <typename T> 445inline TextOutput& operator<<(TextOutput& to, const wp<T>& val) 446{ 447 return printWeakPointer(to, val.unsafe_get()); 448} 449 450// --------------------------------------------------------------------------- 451 452// this class just serves as a namespace so TYPE::moveReferences can stay 453// private. 454 455class ReferenceMover { 456 // StrongReferenceCast and WeakReferenceCast do the impedance matching 457 // between the generic (void*) implementation in Refbase and the strongly typed 458 // template specializations below. 459 460 template <typename TYPE> 461 struct StrongReferenceCast : public ReferenceConverterBase { 462 virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); } 463 virtual void* getReferenceBase(void const* p) const { 464 sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p)); 465 return static_cast<typename TYPE::basetype *>(sptr->get()); 466 } 467 }; 468 469 template <typename TYPE> 470 struct WeakReferenceCast : public ReferenceConverterBase { 471 virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); } 472 virtual void* getReferenceBase(void const* p) const { 473 wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p)); 474 return static_cast<typename TYPE::basetype *>(sptr->unsafe_get()); 475 } 476 }; 477 478public: 479 template<typename TYPE> static inline 480 void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { 481 memmove(d, s, n*sizeof(sp<TYPE>)); 482 StrongReferenceCast<TYPE> caster; 483 TYPE::moveReferences(d, s, n, caster); 484 } 485 template<typename TYPE> static inline 486 void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { 487 memmove(d, s, n*sizeof(wp<TYPE>)); 488 WeakReferenceCast<TYPE> caster; 489 TYPE::moveReferences(d, s, n, caster); 490 } 491}; 492 493// specialization for moving sp<> and wp<> types. 494// these are used by the [Sorted|Keyed]Vector<> implementations 495// sp<> and wp<> need to be handled specially, because they do not 496// have trivial copy operation in the general case (see RefBase.cpp 497// when DEBUG ops are enabled), but can be implemented very 498// efficiently in most cases. 499 500template<typename TYPE> inline 501void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { 502 ReferenceMover::move_references(d, s, n); 503} 504 505template<typename TYPE> inline 506void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { 507 ReferenceMover::move_references(d, s, n); 508} 509 510template<typename TYPE> inline 511void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { 512 ReferenceMover::move_references(d, s, n); 513} 514 515template<typename TYPE> inline 516void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { 517 ReferenceMover::move_references(d, s, n); 518} 519 520 521}; // namespace android 522 523// --------------------------------------------------------------------------- 524 525#endif // ANDROID_REF_BASE_H 526