RefBase.h revision 3d6881f3940dd19268006e71dd2ed9896588dfb6
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#include <utils/TextOutput.h> 22 23#include <stdint.h> 24#include <sys/types.h> 25#include <stdlib.h> 26 27// --------------------------------------------------------------------------- 28namespace android { 29 30template<typename T> class wp; 31 32// --------------------------------------------------------------------------- 33 34#define COMPARE_WEAK(_op_) \ 35inline bool operator _op_ (const sp<T>& o) const { \ 36 return m_ptr _op_ o.m_ptr; \ 37} \ 38inline bool operator _op_ (const T* o) const { \ 39 return m_ptr _op_ o; \ 40} \ 41template<typename U> \ 42inline bool operator _op_ (const sp<U>& o) const { \ 43 return m_ptr _op_ o.m_ptr; \ 44} \ 45template<typename U> \ 46inline bool operator _op_ (const U* o) const { \ 47 return m_ptr _op_ o; \ 48} 49 50#define COMPARE(_op_) \ 51COMPARE_WEAK(_op_) \ 52inline bool operator _op_ (const wp<T>& o) const { \ 53 return m_ptr _op_ o.m_ptr; \ 54} \ 55template<typename U> \ 56inline bool operator _op_ (const wp<U>& o) const { \ 57 return m_ptr _op_ o.m_ptr; \ 58} 59 60// --------------------------------------------------------------------------- 61 62class RefBase 63{ 64public: 65 void incStrong(const void* id) const; 66 void decStrong(const void* id) const; 67 68 void forceIncStrong(const void* id) const; 69 70 //! DEBUGGING ONLY: Get current strong ref count. 71 int32_t getStrongCount() const; 72 73 class weakref_type 74 { 75 public: 76 RefBase* refBase() const; 77 78 void incWeak(const void* id); 79 void decWeak(const void* id); 80 81 bool attemptIncStrong(const void* id); 82 83 //! This is only safe if you have set OBJECT_LIFETIME_FOREVER. 84 bool attemptIncWeak(const void* id); 85 86 //! DEBUGGING ONLY: Get current weak ref count. 87 int32_t getWeakCount() const; 88 89 //! DEBUGGING ONLY: Print references held on object. 90 void printRefs() const; 91 92 //! DEBUGGING ONLY: Enable tracking for this object. 93 // enable -- enable/disable tracking 94 // retain -- when tracking is enable, if true, then we save a stack trace 95 // for each reference and dereference; when retain == false, we 96 // match up references and dereferences and keep only the 97 // outstanding ones. 98 99 void trackMe(bool enable, bool retain); 100 }; 101 102 weakref_type* createWeak(const void* id) const; 103 104 weakref_type* getWeakRefs() const; 105 106 //! DEBUGGING ONLY: Print references held on object. 107 inline void printRefs() const { getWeakRefs()->printRefs(); } 108 109 //! DEBUGGING ONLY: Enable tracking of object. 110 inline void trackMe(bool enable, bool retain) 111 { 112 getWeakRefs()->trackMe(enable, retain); 113 } 114 115protected: 116 RefBase(); 117 virtual ~RefBase(); 118 119 // called when the last reference goes away. this is responsible for 120 // calling the destructor. The default implementation just does 121 // "delete this;". 122 // Make sure to never acquire a strong reference from this function. The 123 // same restrictions than for destructors apply. 124 virtual void destroy() const; 125 126 //! Flags for extendObjectLifetime() 127 enum { 128 OBJECT_LIFETIME_WEAK = 0x0001, 129 OBJECT_LIFETIME_FOREVER = 0x0003 130 }; 131 132 void extendObjectLifetime(int32_t mode); 133 134 //! Flags for onIncStrongAttempted() 135 enum { 136 FIRST_INC_STRONG = 0x0001 137 }; 138 139 virtual void onFirstRef(); 140 virtual void onLastStrongRef(const void* id); 141 virtual bool onIncStrongAttempted(uint32_t flags, const void* id); 142 virtual void onLastWeakRef(const void* id); 143 144private: 145 friend class weakref_type; 146 class weakref_impl; 147 148 RefBase(const RefBase& o); 149 RefBase& operator=(const RefBase& o); 150 151 weakref_impl* const mRefs; 152}; 153 154// --------------------------------------------------------------------------- 155 156template <class T> 157class LightRefBase 158{ 159public: 160 inline LightRefBase() : mCount(0) { } 161 inline void incStrong(const void* id) const { 162 android_atomic_inc(&mCount); 163 } 164 inline void decStrong(const void* id) const { 165 if (android_atomic_dec(&mCount) == 1) { 166 delete static_cast<const T*>(this); 167 } 168 } 169 //! DEBUGGING ONLY: Get current strong ref count. 170 inline int32_t getStrongCount() const { 171 return mCount; 172 } 173 174protected: 175 inline ~LightRefBase() { } 176 177private: 178 mutable volatile int32_t mCount; 179}; 180 181// --------------------------------------------------------------------------- 182 183template <typename T> 184class sp 185{ 186public: 187 typedef typename RefBase::weakref_type weakref_type; 188 189 inline sp() : m_ptr(0) { } 190 191 sp(T* other); 192 sp(const sp<T>& other); 193 template<typename U> sp(U* other); 194 template<typename U> sp(const sp<U>& other); 195 196 ~sp(); 197 198 // Assignment 199 200 sp& operator = (T* other); 201 sp& operator = (const sp<T>& other); 202 203 template<typename U> sp& operator = (const sp<U>& other); 204 template<typename U> sp& operator = (U* other); 205 206 //! Special optimization for use by ProcessState (and nobody else). 207 void force_set(T* other); 208 209 // Reset 210 211 void clear(); 212 213 // Accessors 214 215 inline T& operator* () const { return *m_ptr; } 216 inline T* operator-> () const { return m_ptr; } 217 inline T* get() const { return m_ptr; } 218 219 // Operators 220 221 COMPARE(==) 222 COMPARE(!=) 223 COMPARE(>) 224 COMPARE(<) 225 COMPARE(<=) 226 COMPARE(>=) 227 228private: 229 template<typename Y> friend class sp; 230 template<typename Y> friend class wp; 231 232 // Optimization for wp::promote(). 233 sp(T* p, weakref_type* refs); 234 235 T* m_ptr; 236}; 237 238template <typename T> 239TextOutput& operator<<(TextOutput& to, const sp<T>& val); 240 241// --------------------------------------------------------------------------- 242 243template <typename T> 244class wp 245{ 246public: 247 typedef typename RefBase::weakref_type weakref_type; 248 249 inline wp() : m_ptr(0) { } 250 251 wp(T* other); 252 wp(const wp<T>& other); 253 wp(const sp<T>& other); 254 template<typename U> wp(U* other); 255 template<typename U> wp(const sp<U>& other); 256 template<typename U> wp(const wp<U>& other); 257 258 ~wp(); 259 260 // Assignment 261 262 wp& operator = (T* other); 263 wp& operator = (const wp<T>& other); 264 wp& operator = (const sp<T>& other); 265 266 template<typename U> wp& operator = (U* other); 267 template<typename U> wp& operator = (const wp<U>& other); 268 template<typename U> wp& operator = (const sp<U>& other); 269 270 void set_object_and_refs(T* other, weakref_type* refs); 271 272 // promotion to sp 273 274 sp<T> promote() const; 275 276 // Reset 277 278 void clear(); 279 280 // Accessors 281 282 inline weakref_type* get_refs() const { return m_refs; } 283 284 inline T* unsafe_get() const { return m_ptr; } 285 286 // Operators 287 288 COMPARE_WEAK(==) 289 COMPARE_WEAK(!=) 290 COMPARE_WEAK(>) 291 COMPARE_WEAK(<) 292 COMPARE_WEAK(<=) 293 COMPARE_WEAK(>=) 294 295 inline bool operator == (const wp<T>& o) const { 296 return (m_ptr == o.m_ptr) && (m_refs == o.m_refs); 297 } 298 template<typename U> 299 inline bool operator == (const wp<U>& o) const { 300 return m_ptr == o.m_ptr; 301 } 302 303 inline bool operator > (const wp<T>& o) const { 304 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); 305 } 306 template<typename U> 307 inline bool operator > (const wp<U>& o) const { 308 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); 309 } 310 311 inline bool operator < (const wp<T>& o) const { 312 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); 313 } 314 template<typename U> 315 inline bool operator < (const wp<U>& o) const { 316 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); 317 } 318 inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; } 319 template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); } 320 inline bool operator <= (const wp<T>& o) const { return !operator > (o); } 321 template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); } 322 inline bool operator >= (const wp<T>& o) const { return !operator < (o); } 323 template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); } 324 325private: 326 template<typename Y> friend class sp; 327 template<typename Y> friend class wp; 328 329 T* m_ptr; 330 weakref_type* m_refs; 331}; 332 333template <typename T> 334TextOutput& operator<<(TextOutput& to, const wp<T>& val); 335 336#undef COMPARE 337#undef COMPARE_WEAK 338 339// --------------------------------------------------------------------------- 340// No user serviceable parts below here. 341 342template<typename T> 343sp<T>::sp(T* other) 344 : m_ptr(other) 345{ 346 if (other) other->incStrong(this); 347} 348 349template<typename T> 350sp<T>::sp(const sp<T>& other) 351 : m_ptr(other.m_ptr) 352{ 353 if (m_ptr) m_ptr->incStrong(this); 354} 355 356template<typename T> template<typename U> 357sp<T>::sp(U* other) : m_ptr(other) 358{ 359 if (other) other->incStrong(this); 360} 361 362template<typename T> template<typename U> 363sp<T>::sp(const sp<U>& other) 364 : m_ptr(other.m_ptr) 365{ 366 if (m_ptr) m_ptr->incStrong(this); 367} 368 369template<typename T> 370sp<T>::~sp() 371{ 372 if (m_ptr) m_ptr->decStrong(this); 373} 374 375template<typename T> 376sp<T>& sp<T>::operator = (const sp<T>& other) { 377 T* otherPtr(other.m_ptr); 378 if (otherPtr) otherPtr->incStrong(this); 379 if (m_ptr) m_ptr->decStrong(this); 380 m_ptr = otherPtr; 381 return *this; 382} 383 384template<typename T> 385sp<T>& sp<T>::operator = (T* other) 386{ 387 if (other) other->incStrong(this); 388 if (m_ptr) m_ptr->decStrong(this); 389 m_ptr = other; 390 return *this; 391} 392 393template<typename T> template<typename U> 394sp<T>& sp<T>::operator = (const sp<U>& other) 395{ 396 U* otherPtr(other.m_ptr); 397 if (otherPtr) otherPtr->incStrong(this); 398 if (m_ptr) m_ptr->decStrong(this); 399 m_ptr = otherPtr; 400 return *this; 401} 402 403template<typename T> template<typename U> 404sp<T>& sp<T>::operator = (U* other) 405{ 406 if (other) other->incStrong(this); 407 if (m_ptr) m_ptr->decStrong(this); 408 m_ptr = other; 409 return *this; 410} 411 412template<typename T> 413void sp<T>::force_set(T* other) 414{ 415 other->forceIncStrong(this); 416 m_ptr = other; 417} 418 419template<typename T> 420void sp<T>::clear() 421{ 422 if (m_ptr) { 423 m_ptr->decStrong(this); 424 m_ptr = 0; 425 } 426} 427 428template<typename T> 429sp<T>::sp(T* p, weakref_type* refs) 430 : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0) 431{ 432} 433 434template <typename T> 435inline TextOutput& operator<<(TextOutput& to, const sp<T>& val) 436{ 437 to << "sp<>(" << val.get() << ")"; 438 return to; 439} 440 441// --------------------------------------------------------------------------- 442 443template<typename T> 444wp<T>::wp(T* other) 445 : m_ptr(other) 446{ 447 if (other) m_refs = other->createWeak(this); 448} 449 450template<typename T> 451wp<T>::wp(const wp<T>& other) 452 : m_ptr(other.m_ptr), m_refs(other.m_refs) 453{ 454 if (m_ptr) m_refs->incWeak(this); 455} 456 457template<typename T> 458wp<T>::wp(const sp<T>& other) 459 : m_ptr(other.m_ptr) 460{ 461 if (m_ptr) { 462 m_refs = m_ptr->createWeak(this); 463 } 464} 465 466template<typename T> template<typename U> 467wp<T>::wp(U* other) 468 : m_ptr(other) 469{ 470 if (other) m_refs = other->createWeak(this); 471} 472 473template<typename T> template<typename U> 474wp<T>::wp(const wp<U>& other) 475 : m_ptr(other.m_ptr) 476{ 477 if (m_ptr) { 478 m_refs = other.m_refs; 479 m_refs->incWeak(this); 480 } 481} 482 483template<typename T> template<typename U> 484wp<T>::wp(const sp<U>& other) 485 : m_ptr(other.m_ptr) 486{ 487 if (m_ptr) { 488 m_refs = m_ptr->createWeak(this); 489 } 490} 491 492template<typename T> 493wp<T>::~wp() 494{ 495 if (m_ptr) m_refs->decWeak(this); 496} 497 498template<typename T> 499wp<T>& wp<T>::operator = (T* other) 500{ 501 weakref_type* newRefs = 502 other ? other->createWeak(this) : 0; 503 if (m_ptr) m_refs->decWeak(this); 504 m_ptr = other; 505 m_refs = newRefs; 506 return *this; 507} 508 509template<typename T> 510wp<T>& wp<T>::operator = (const wp<T>& other) 511{ 512 weakref_type* otherRefs(other.m_refs); 513 T* otherPtr(other.m_ptr); 514 if (otherPtr) otherRefs->incWeak(this); 515 if (m_ptr) m_refs->decWeak(this); 516 m_ptr = otherPtr; 517 m_refs = otherRefs; 518 return *this; 519} 520 521template<typename T> 522wp<T>& wp<T>::operator = (const sp<T>& other) 523{ 524 weakref_type* newRefs = 525 other != NULL ? other->createWeak(this) : 0; 526 T* otherPtr(other.m_ptr); 527 if (m_ptr) m_refs->decWeak(this); 528 m_ptr = otherPtr; 529 m_refs = newRefs; 530 return *this; 531} 532 533template<typename T> template<typename U> 534wp<T>& wp<T>::operator = (U* other) 535{ 536 weakref_type* newRefs = 537 other ? other->createWeak(this) : 0; 538 if (m_ptr) m_refs->decWeak(this); 539 m_ptr = other; 540 m_refs = newRefs; 541 return *this; 542} 543 544template<typename T> template<typename U> 545wp<T>& wp<T>::operator = (const wp<U>& other) 546{ 547 weakref_type* otherRefs(other.m_refs); 548 U* otherPtr(other.m_ptr); 549 if (otherPtr) otherRefs->incWeak(this); 550 if (m_ptr) m_refs->decWeak(this); 551 m_ptr = otherPtr; 552 m_refs = otherRefs; 553 return *this; 554} 555 556template<typename T> template<typename U> 557wp<T>& wp<T>::operator = (const sp<U>& other) 558{ 559 weakref_type* newRefs = 560 other != NULL ? other->createWeak(this) : 0; 561 U* otherPtr(other.m_ptr); 562 if (m_ptr) m_refs->decWeak(this); 563 m_ptr = otherPtr; 564 m_refs = newRefs; 565 return *this; 566} 567 568template<typename T> 569void wp<T>::set_object_and_refs(T* other, weakref_type* refs) 570{ 571 if (other) refs->incWeak(this); 572 if (m_ptr) m_refs->decWeak(this); 573 m_ptr = other; 574 m_refs = refs; 575} 576 577template<typename T> 578sp<T> wp<T>::promote() const 579{ 580 return sp<T>(m_ptr, m_refs); 581} 582 583template<typename T> 584void wp<T>::clear() 585{ 586 if (m_ptr) { 587 m_refs->decWeak(this); 588 m_ptr = 0; 589 } 590} 591 592template <typename T> 593inline TextOutput& operator<<(TextOutput& to, const wp<T>& val) 594{ 595 to << "wp<>(" << val.unsafe_get() << ")"; 596 return to; 597} 598 599}; // namespace android 600 601// --------------------------------------------------------------------------- 602 603#endif // ANDROID_REF_BASE_H 604