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 // --------------------------------------------------------------------------- 28 namespace android { 29 30 template<typename T> class wp; 31 32 // --------------------------------------------------------------------------- 33 34 #define COMPARE(_op_) \ 35 inline bool operator _op_ (const sp<T>& o) const { \ 36 return m_ptr _op_ o.m_ptr; \ 37 } \ 38 inline bool operator _op_ (const wp<T>& o) const { \ 39 return m_ptr _op_ o.m_ptr; \ 40 } \ 41 inline bool operator _op_ (const T* o) const { \ 42 return m_ptr _op_ o; \ 43 } \ 44 template<typename U> \ 45 inline bool operator _op_ (const sp<U>& o) const { \ 46 return m_ptr _op_ o.m_ptr; \ 47 } \ 48 template<typename U> \ 49 inline bool operator _op_ (const wp<U>& o) const { \ 50 return m_ptr _op_ o.m_ptr; \ 51 } \ 52 template<typename U> \ 53 inline bool operator _op_ (const U* o) const { \ 54 return m_ptr _op_ o; \ 55 } 56 57 // --------------------------------------------------------------------------- 58 59 class RefBase 60 { 61 public: 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 112 protected: 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 134 private: 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 146 template <class T> 147 class LightRefBase 148 { 149 public: 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 //! DEBUGGING ONLY: Get current strong ref count. 160 inline int32_t getStrongCount() const { 161 return mCount; 162 } 163 164 protected: 165 inline ~LightRefBase() { } 166 167 private: 168 mutable volatile int32_t mCount; 169 }; 170 171 // --------------------------------------------------------------------------- 172 173 template <typename T> 174 class sp 175 { 176 public: 177 typedef typename RefBase::weakref_type weakref_type; 178 179 inline sp() : m_ptr(0) { } 180 181 sp(T* other); 182 sp(const sp<T>& other); 183 template<typename U> sp(U* other); 184 template<typename U> sp(const sp<U>& other); 185 186 ~sp(); 187 188 // Assignment 189 190 sp& operator = (T* other); 191 sp& operator = (const sp<T>& other); 192 193 template<typename U> sp& operator = (const sp<U>& other); 194 template<typename U> sp& operator = (U* other); 195 196 //! Special optimization for use by ProcessState (and nobody else). 197 void force_set(T* other); 198 199 // Reset 200 201 void clear(); 202 203 // Accessors 204 205 inline T& operator* () const { return *m_ptr; } 206 inline T* operator-> () const { return m_ptr; } 207 inline T* get() const { return m_ptr; } 208 209 // Operators 210 211 COMPARE(==) 212 COMPARE(!=) 213 COMPARE(>) 214 COMPARE(<) 215 COMPARE(<=) 216 COMPARE(>=) 217 218 private: 219 template<typename Y> friend class sp; 220 template<typename Y> friend class wp; 221 222 // Optimization for wp::promote(). 223 sp(T* p, weakref_type* refs); 224 225 T* m_ptr; 226 }; 227 228 template <typename T> 229 TextOutput& operator<<(TextOutput& to, const sp<T>& val); 230 231 // --------------------------------------------------------------------------- 232 233 template <typename T> 234 class wp 235 { 236 public: 237 typedef typename RefBase::weakref_type weakref_type; 238 239 inline wp() : m_ptr(0) { } 240 241 wp(T* other); 242 wp(const wp<T>& other); 243 wp(const sp<T>& other); 244 template<typename U> wp(U* other); 245 template<typename U> wp(const sp<U>& other); 246 template<typename U> wp(const wp<U>& other); 247 248 ~wp(); 249 250 // Assignment 251 252 wp& operator = (T* other); 253 wp& operator = (const wp<T>& other); 254 wp& operator = (const sp<T>& other); 255 256 template<typename U> wp& operator = (U* other); 257 template<typename U> wp& operator = (const wp<U>& other); 258 template<typename U> wp& operator = (const sp<U>& other); 259 260 void set_object_and_refs(T* other, weakref_type* refs); 261 262 // promotion to sp 263 264 sp<T> promote() const; 265 266 // Reset 267 268 void clear(); 269 270 // Accessors 271 272 inline weakref_type* get_refs() const { return m_refs; } 273 274 inline T* unsafe_get() const { return m_ptr; } 275 276 // Operators 277 278 COMPARE(==) 279 COMPARE(!=) 280 COMPARE(>) 281 COMPARE(<) 282 COMPARE(<=) 283 COMPARE(>=) 284 285 private: 286 template<typename Y> friend class sp; 287 template<typename Y> friend class wp; 288 289 T* m_ptr; 290 weakref_type* m_refs; 291 }; 292 293 template <typename T> 294 TextOutput& operator<<(TextOutput& to, const wp<T>& val); 295 296 #undef COMPARE 297 298 // --------------------------------------------------------------------------- 299 // No user serviceable parts below here. 300 301 template<typename T> 302 sp<T>::sp(T* other) 303 : m_ptr(other) 304 { 305 if (other) other->incStrong(this); 306 } 307 308 template<typename T> 309 sp<T>::sp(const sp<T>& other) 310 : m_ptr(other.m_ptr) 311 { 312 if (m_ptr) m_ptr->incStrong(this); 313 } 314 315 template<typename T> template<typename U> 316 sp<T>::sp(U* other) : m_ptr(other) 317 { 318 if (other) other->incStrong(this); 319 } 320 321 template<typename T> template<typename U> 322 sp<T>::sp(const sp<U>& other) 323 : m_ptr(other.m_ptr) 324 { 325 if (m_ptr) m_ptr->incStrong(this); 326 } 327 328 template<typename T> 329 sp<T>::~sp() 330 { 331 if (m_ptr) m_ptr->decStrong(this); 332 } 333 334 template<typename T> 335 sp<T>& sp<T>::operator = (const sp<T>& other) { 336 T* otherPtr(other.m_ptr); 337 if (otherPtr) otherPtr->incStrong(this); 338 if (m_ptr) m_ptr->decStrong(this); 339 m_ptr = otherPtr; 340 return *this; 341 } 342 343 template<typename T> 344 sp<T>& sp<T>::operator = (T* other) 345 { 346 if (other) other->incStrong(this); 347 if (m_ptr) m_ptr->decStrong(this); 348 m_ptr = other; 349 return *this; 350 } 351 352 template<typename T> template<typename U> 353 sp<T>& sp<T>::operator = (const sp<U>& other) 354 { 355 U* otherPtr(other.m_ptr); 356 if (otherPtr) otherPtr->incStrong(this); 357 if (m_ptr) m_ptr->decStrong(this); 358 m_ptr = otherPtr; 359 return *this; 360 } 361 362 template<typename T> template<typename U> 363 sp<T>& sp<T>::operator = (U* other) 364 { 365 if (other) other->incStrong(this); 366 if (m_ptr) m_ptr->decStrong(this); 367 m_ptr = other; 368 return *this; 369 } 370 371 template<typename T> 372 void sp<T>::force_set(T* other) 373 { 374 other->forceIncStrong(this); 375 m_ptr = other; 376 } 377 378 template<typename T> 379 void sp<T>::clear() 380 { 381 if (m_ptr) { 382 m_ptr->decStrong(this); 383 m_ptr = 0; 384 } 385 } 386 387 template<typename T> 388 sp<T>::sp(T* p, weakref_type* refs) 389 : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0) 390 { 391 } 392 393 template <typename T> 394 inline TextOutput& operator<<(TextOutput& to, const sp<T>& val) 395 { 396 to << "sp<>(" << val.get() << ")"; 397 return to; 398 } 399 400 // --------------------------------------------------------------------------- 401 402 template<typename T> 403 wp<T>::wp(T* other) 404 : m_ptr(other) 405 { 406 if (other) m_refs = other->createWeak(this); 407 } 408 409 template<typename T> 410 wp<T>::wp(const wp<T>& other) 411 : m_ptr(other.m_ptr), m_refs(other.m_refs) 412 { 413 if (m_ptr) m_refs->incWeak(this); 414 } 415 416 template<typename T> 417 wp<T>::wp(const sp<T>& other) 418 : m_ptr(other.m_ptr) 419 { 420 if (m_ptr) { 421 m_refs = m_ptr->createWeak(this); 422 } 423 } 424 425 template<typename T> template<typename U> 426 wp<T>::wp(U* other) 427 : m_ptr(other) 428 { 429 if (other) m_refs = other->createWeak(this); 430 } 431 432 template<typename T> template<typename U> 433 wp<T>::wp(const wp<U>& other) 434 : m_ptr(other.m_ptr) 435 { 436 if (m_ptr) { 437 m_refs = other.m_refs; 438 m_refs->incWeak(this); 439 } 440 } 441 442 template<typename T> template<typename U> 443 wp<T>::wp(const sp<U>& other) 444 : m_ptr(other.m_ptr) 445 { 446 if (m_ptr) { 447 m_refs = m_ptr->createWeak(this); 448 } 449 } 450 451 template<typename T> 452 wp<T>::~wp() 453 { 454 if (m_ptr) m_refs->decWeak(this); 455 } 456 457 template<typename T> 458 wp<T>& wp<T>::operator = (T* other) 459 { 460 weakref_type* newRefs = 461 other ? other->createWeak(this) : 0; 462 if (m_ptr) m_refs->decWeak(this); 463 m_ptr = other; 464 m_refs = newRefs; 465 return *this; 466 } 467 468 template<typename T> 469 wp<T>& wp<T>::operator = (const wp<T>& other) 470 { 471 weakref_type* otherRefs(other.m_refs); 472 T* otherPtr(other.m_ptr); 473 if (otherPtr) otherRefs->incWeak(this); 474 if (m_ptr) m_refs->decWeak(this); 475 m_ptr = otherPtr; 476 m_refs = otherRefs; 477 return *this; 478 } 479 480 template<typename T> 481 wp<T>& wp<T>::operator = (const sp<T>& other) 482 { 483 weakref_type* newRefs = 484 other != NULL ? other->createWeak(this) : 0; 485 T* otherPtr(other.m_ptr); 486 if (m_ptr) m_refs->decWeak(this); 487 m_ptr = otherPtr; 488 m_refs = newRefs; 489 return *this; 490 } 491 492 template<typename T> template<typename U> 493 wp<T>& wp<T>::operator = (U* other) 494 { 495 weakref_type* newRefs = 496 other ? other->createWeak(this) : 0; 497 if (m_ptr) m_refs->decWeak(this); 498 m_ptr = other; 499 m_refs = newRefs; 500 return *this; 501 } 502 503 template<typename T> template<typename U> 504 wp<T>& wp<T>::operator = (const wp<U>& other) 505 { 506 weakref_type* otherRefs(other.m_refs); 507 U* otherPtr(other.m_ptr); 508 if (otherPtr) otherRefs->incWeak(this); 509 if (m_ptr) m_refs->decWeak(this); 510 m_ptr = otherPtr; 511 m_refs = otherRefs; 512 return *this; 513 } 514 515 template<typename T> template<typename U> 516 wp<T>& wp<T>::operator = (const sp<U>& other) 517 { 518 weakref_type* newRefs = 519 other != NULL ? other->createWeak(this) : 0; 520 U* otherPtr(other.m_ptr); 521 if (m_ptr) m_refs->decWeak(this); 522 m_ptr = otherPtr; 523 m_refs = newRefs; 524 return *this; 525 } 526 527 template<typename T> 528 void wp<T>::set_object_and_refs(T* other, weakref_type* refs) 529 { 530 if (other) refs->incWeak(this); 531 if (m_ptr) m_refs->decWeak(this); 532 m_ptr = other; 533 m_refs = refs; 534 } 535 536 template<typename T> 537 sp<T> wp<T>::promote() const 538 { 539 return sp<T>(m_ptr, m_refs); 540 } 541 542 template<typename T> 543 void wp<T>::clear() 544 { 545 if (m_ptr) { 546 m_refs->decWeak(this); 547 m_ptr = 0; 548 } 549 } 550 551 template <typename T> 552 inline TextOutput& operator<<(TextOutput& to, const wp<T>& val) 553 { 554 to << "wp<>(" << val.unsafe_get() << ")"; 555 return to; 556 } 557 558 }; // namespace android 559 560 // --------------------------------------------------------------------------- 561 562 #endif // ANDROID_REF_BASE_H 563