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