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