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