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