RefBase.cpp 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#define LOG_TAG "RefBase" 18 19#include <utils/RefBase.h> 20 21#include <utils/Atomic.h> 22#include <utils/CallStack.h> 23#include <utils/Log.h> 24#include <utils/threads.h> 25#include <utils/TextOutput.h> 26 27#include <stdlib.h> 28#include <stdio.h> 29#include <typeinfo> 30#include <sys/types.h> 31#include <sys/stat.h> 32#include <fcntl.h> 33#include <unistd.h> 34 35// compile with refcounting debugging enabled 36#define DEBUG_REFS 0 37#define DEBUG_REFS_FATAL_SANITY_CHECKS 0 38#define DEBUG_REFS_ENABLED_BY_DEFAULT 1 39#define DEBUG_REFS_CALLSTACK_ENABLED 1 40 41// log all reference counting operations 42#define PRINT_REFS 0 43 44// --------------------------------------------------------------------------- 45 46namespace android { 47 48#define INITIAL_STRONG_VALUE (1<<28) 49 50// --------------------------------------------------------------------------- 51 52RefBase::Destroyer::~Destroyer() { 53} 54 55// --------------------------------------------------------------------------- 56 57class RefBase::weakref_impl : public RefBase::weakref_type 58{ 59public: 60 volatile int32_t mStrong; 61 volatile int32_t mWeak; 62 RefBase* const mBase; 63 volatile int32_t mFlags; 64 Destroyer* mDestroyer; 65 66#if !DEBUG_REFS 67 68 weakref_impl(RefBase* base) 69 : mStrong(INITIAL_STRONG_VALUE) 70 , mWeak(0) 71 , mBase(base) 72 , mFlags(0) 73 , mDestroyer(0) 74 { 75 } 76 77 void addStrongRef(const void* /*id*/) { } 78 void removeStrongRef(const void* /*id*/) { } 79 void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { } 80 void addWeakRef(const void* /*id*/) { } 81 void removeWeakRef(const void* /*id*/) { } 82 void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { } 83 void printRefs() const { } 84 void trackMe(bool, bool) { } 85 86#else 87 88 weakref_impl(RefBase* base) 89 : mStrong(INITIAL_STRONG_VALUE) 90 , mWeak(0) 91 , mBase(base) 92 , mFlags(0) 93 , mStrongRefs(NULL) 94 , mWeakRefs(NULL) 95 , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT) 96 , mRetain(false) 97 { 98 } 99 100 ~weakref_impl() 101 { 102 bool dumpStack = false; 103 if (!mRetain && mStrongRefs != NULL) { 104 dumpStack = true; 105#if DEBUG_REFS_FATAL_SANITY_CHECKS 106 LOG_ALWAYS_FATAL("Strong references remain!"); 107#else 108 LOGE("Strong references remain:"); 109#endif 110 ref_entry* refs = mStrongRefs; 111 while (refs) { 112 char inc = refs->ref >= 0 ? '+' : '-'; 113 LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); 114#if DEBUG_REFS_CALLSTACK_ENABLED 115 refs->stack.dump(); 116#endif; 117 refs = refs->next; 118 } 119 } 120 121 if (!mRetain && mWeakRefs != NULL) { 122 dumpStack = true; 123#if DEBUG_REFS_FATAL_SANITY_CHECKS 124 LOG_ALWAYS_FATAL("Weak references remain:"); 125#else 126 LOGE("Weak references remain!"); 127#endif 128 ref_entry* refs = mWeakRefs; 129 while (refs) { 130 char inc = refs->ref >= 0 ? '+' : '-'; 131 LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); 132#if DEBUG_REFS_CALLSTACK_ENABLED 133 refs->stack.dump(); 134#endif; 135 refs = refs->next; 136 } 137 } 138 if (dumpStack) { 139 LOGE("above errors at:"); 140 CallStack stack; 141 stack.update(); 142 stack.dump(); 143 } 144 } 145 146 void addStrongRef(const void* id) { 147 //LOGD_IF(mTrackEnabled, 148 // "addStrongRef: RefBase=%p, id=%p", mBase, id); 149 addRef(&mStrongRefs, id, mStrong); 150 } 151 152 void removeStrongRef(const void* id) { 153 //LOGD_IF(mTrackEnabled, 154 // "removeStrongRef: RefBase=%p, id=%p", mBase, id); 155 if (!mRetain) { 156 removeRef(&mStrongRefs, id); 157 } else { 158 addRef(&mStrongRefs, id, -mStrong); 159 } 160 } 161 162 void renameStrongRefId(const void* old_id, const void* new_id) { 163 //LOGD_IF(mTrackEnabled, 164 // "renameStrongRefId: RefBase=%p, oid=%p, nid=%p", 165 // mBase, old_id, new_id); 166 renameRefsId(mStrongRefs, old_id, new_id); 167 } 168 169 void addWeakRef(const void* id) { 170 addRef(&mWeakRefs, id, mWeak); 171 } 172 173 void removeWeakRef(const void* id) { 174 if (!mRetain) { 175 removeRef(&mWeakRefs, id); 176 } else { 177 addRef(&mWeakRefs, id, -mWeak); 178 } 179 } 180 181 void renameWeakRefId(const void* old_id, const void* new_id) { 182 renameRefsId(mWeakRefs, old_id, new_id); 183 } 184 185 void trackMe(bool track, bool retain) 186 { 187 mTrackEnabled = track; 188 mRetain = retain; 189 } 190 191 void printRefs() const 192 { 193 String8 text; 194 195 { 196 Mutex::Autolock _l(const_cast<weakref_impl*>(this)->mMutex); 197 char buf[128]; 198 sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this); 199 text.append(buf); 200 printRefsLocked(&text, mStrongRefs); 201 sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this); 202 text.append(buf); 203 printRefsLocked(&text, mWeakRefs); 204 } 205 206 { 207 char name[100]; 208 snprintf(name, 100, "/data/%p.stack", this); 209 int rc = open(name, O_RDWR | O_CREAT | O_APPEND); 210 if (rc >= 0) { 211 write(rc, text.string(), text.length()); 212 close(rc); 213 LOGD("STACK TRACE for %p saved in %s", this, name); 214 } 215 else LOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this, 216 name, strerror(errno)); 217 } 218 } 219 220private: 221 struct ref_entry 222 { 223 ref_entry* next; 224 const void* id; 225#if DEBUG_REFS_CALLSTACK_ENABLED 226 CallStack stack; 227#endif 228 int32_t ref; 229 }; 230 231 void addRef(ref_entry** refs, const void* id, int32_t mRef) 232 { 233 if (mTrackEnabled) { 234 AutoMutex _l(mMutex); 235 236 ref_entry* ref = new ref_entry; 237 // Reference count at the time of the snapshot, but before the 238 // update. Positive value means we increment, negative--we 239 // decrement the reference count. 240 ref->ref = mRef; 241 ref->id = id; 242#if DEBUG_REFS_CALLSTACK_ENABLED 243 ref->stack.update(2); 244#endif 245 ref->next = *refs; 246 *refs = ref; 247 } 248 } 249 250 void removeRef(ref_entry** refs, const void* id) 251 { 252 if (mTrackEnabled) { 253 AutoMutex _l(mMutex); 254 255 ref_entry* const head = *refs; 256 ref_entry* ref = head; 257 while (ref != NULL) { 258 if (ref->id == id) { 259 *refs = ref->next; 260 delete ref; 261 return; 262 } 263 refs = &ref->next; 264 ref = *refs; 265 } 266 267#if DEBUG_REFS_FATAL_SANITY_CHECKS 268 LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p" 269 "(weakref_type %p) that doesn't exist!", 270 id, mBase, this); 271#endif 272 273 LOGE("RefBase: removing id %p on RefBase %p" 274 "(weakref_type %p) that doesn't exist!", 275 id, mBase, this); 276 277 ref = head; 278 while (ref) { 279 char inc = ref->ref >= 0 ? '+' : '-'; 280 LOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref); 281 ref = ref->next; 282 } 283 284 CallStack stack; 285 stack.update(); 286 stack.dump(); 287 } 288 } 289 290 void renameRefsId(ref_entry* r, const void* old_id, const void* new_id) 291 { 292 if (mTrackEnabled) { 293 AutoMutex _l(mMutex); 294 ref_entry* ref = r; 295 while (ref != NULL) { 296 if (ref->id == old_id) { 297 ref->id = new_id; 298 } 299 ref = ref->next; 300 } 301 } 302 } 303 304 void printRefsLocked(String8* out, const ref_entry* refs) const 305 { 306 char buf[128]; 307 while (refs) { 308 char inc = refs->ref >= 0 ? '+' : '-'; 309 sprintf(buf, "\t%c ID %p (ref %d):\n", 310 inc, refs->id, refs->ref); 311 out->append(buf); 312#if DEBUG_REFS_CALLSTACK_ENABLED 313 out->append(refs->stack.toString("\t\t")); 314#else 315 out->append("\t\t(call stacks disabled)"); 316#endif 317 refs = refs->next; 318 } 319 } 320 321 Mutex mMutex; 322 ref_entry* mStrongRefs; 323 ref_entry* mWeakRefs; 324 325 bool mTrackEnabled; 326 // Collect stack traces on addref and removeref, instead of deleting the stack references 327 // on removeref that match the address ones. 328 bool mRetain; 329 330#endif 331}; 332 333// --------------------------------------------------------------------------- 334 335void RefBase::incStrong(const void* id) const 336{ 337 weakref_impl* const refs = mRefs; 338 refs->incWeak(id); 339 340 refs->addStrongRef(id); 341 const int32_t c = android_atomic_inc(&refs->mStrong); 342 LOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs); 343#if PRINT_REFS 344 LOGD("incStrong of %p from %p: cnt=%d\n", this, id, c); 345#endif 346 if (c != INITIAL_STRONG_VALUE) { 347 return; 348 } 349 350 android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); 351 const_cast<RefBase*>(this)->onFirstRef(); 352} 353 354void RefBase::decStrong(const void* id) const 355{ 356 weakref_impl* const refs = mRefs; 357 refs->removeStrongRef(id); 358 const int32_t c = android_atomic_dec(&refs->mStrong); 359#if PRINT_REFS 360 LOGD("decStrong of %p from %p: cnt=%d\n", this, id, c); 361#endif 362 LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs); 363 if (c == 1) { 364 const_cast<RefBase*>(this)->onLastStrongRef(id); 365 if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) { 366 if (refs->mDestroyer) { 367 refs->mDestroyer->destroy(this); 368 } else { 369 delete this; 370 } 371 } 372 } 373 refs->decWeak(id); 374} 375 376void RefBase::forceIncStrong(const void* id) const 377{ 378 weakref_impl* const refs = mRefs; 379 refs->incWeak(id); 380 381 refs->addStrongRef(id); 382 const int32_t c = android_atomic_inc(&refs->mStrong); 383 LOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow", 384 refs); 385#if PRINT_REFS 386 LOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c); 387#endif 388 389 switch (c) { 390 case INITIAL_STRONG_VALUE: 391 android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); 392 // fall through... 393 case 0: 394 const_cast<RefBase*>(this)->onFirstRef(); 395 } 396} 397 398int32_t RefBase::getStrongCount() const 399{ 400 return mRefs->mStrong; 401} 402 403void RefBase::setDestroyer(RefBase::Destroyer* destroyer) { 404 mRefs->mDestroyer = destroyer; 405} 406 407RefBase* RefBase::weakref_type::refBase() const 408{ 409 return static_cast<const weakref_impl*>(this)->mBase; 410} 411 412void RefBase::weakref_type::incWeak(const void* id) 413{ 414 weakref_impl* const impl = static_cast<weakref_impl*>(this); 415 impl->addWeakRef(id); 416 const int32_t c = android_atomic_inc(&impl->mWeak); 417 LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this); 418} 419 420void RefBase::weakref_type::decWeak(const void* id) 421{ 422 weakref_impl* const impl = static_cast<weakref_impl*>(this); 423 impl->removeWeakRef(id); 424 const int32_t c = android_atomic_dec(&impl->mWeak); 425 LOG_ASSERT(c >= 1, "decWeak called on %p too many times", this); 426 if (c != 1) return; 427 428 if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) { 429 if (impl->mStrong == INITIAL_STRONG_VALUE) { 430 if (impl->mBase) { 431 if (impl->mDestroyer) { 432 impl->mDestroyer->destroy(impl->mBase); 433 } else { 434 delete impl->mBase; 435 } 436 } 437 } else { 438 // LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase); 439 delete impl; 440 } 441 } else { 442 impl->mBase->onLastWeakRef(id); 443 if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) { 444 if (impl->mBase) { 445 if (impl->mDestroyer) { 446 impl->mDestroyer->destroy(impl->mBase); 447 } else { 448 delete impl->mBase; 449 } 450 } 451 } 452 } 453} 454 455bool RefBase::weakref_type::attemptIncStrong(const void* id) 456{ 457 incWeak(id); 458 459 weakref_impl* const impl = static_cast<weakref_impl*>(this); 460 461 int32_t curCount = impl->mStrong; 462 LOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow", 463 this); 464 while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) { 465 if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) { 466 break; 467 } 468 curCount = impl->mStrong; 469 } 470 471 if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) { 472 bool allow; 473 if (curCount == INITIAL_STRONG_VALUE) { 474 // Attempting to acquire first strong reference... this is allowed 475 // if the object does NOT have a longer lifetime (meaning the 476 // implementation doesn't need to see this), or if the implementation 477 // allows it to happen. 478 allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK 479 || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); 480 } else { 481 // Attempting to revive the object... this is allowed 482 // if the object DOES have a longer lifetime (so we can safely 483 // call the object with only a weak ref) and the implementation 484 // allows it to happen. 485 allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK 486 && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); 487 } 488 if (!allow) { 489 decWeak(id); 490 return false; 491 } 492 curCount = android_atomic_inc(&impl->mStrong); 493 494 // If the strong reference count has already been incremented by 495 // someone else, the implementor of onIncStrongAttempted() is holding 496 // an unneeded reference. So call onLastStrongRef() here to remove it. 497 // (No, this is not pretty.) Note that we MUST NOT do this if we 498 // are in fact acquiring the first reference. 499 if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) { 500 impl->mBase->onLastStrongRef(id); 501 } 502 } 503 504 impl->addStrongRef(id); 505 506#if PRINT_REFS 507 LOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount); 508#endif 509 510 if (curCount == INITIAL_STRONG_VALUE) { 511 android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong); 512 impl->mBase->onFirstRef(); 513 } 514 515 return true; 516} 517 518bool RefBase::weakref_type::attemptIncWeak(const void* id) 519{ 520 weakref_impl* const impl = static_cast<weakref_impl*>(this); 521 522 int32_t curCount = impl->mWeak; 523 LOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow", 524 this); 525 while (curCount > 0) { 526 if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) { 527 break; 528 } 529 curCount = impl->mWeak; 530 } 531 532 if (curCount > 0) { 533 impl->addWeakRef(id); 534 } 535 536 return curCount > 0; 537} 538 539int32_t RefBase::weakref_type::getWeakCount() const 540{ 541 return static_cast<const weakref_impl*>(this)->mWeak; 542} 543 544void RefBase::weakref_type::printRefs() const 545{ 546 static_cast<const weakref_impl*>(this)->printRefs(); 547} 548 549void RefBase::weakref_type::trackMe(bool enable, bool retain) 550{ 551 static_cast<const weakref_impl*>(this)->trackMe(enable, retain); 552} 553 554RefBase::weakref_type* RefBase::createWeak(const void* id) const 555{ 556 mRefs->incWeak(id); 557 return mRefs; 558} 559 560RefBase::weakref_type* RefBase::getWeakRefs() const 561{ 562 return mRefs; 563} 564 565RefBase::RefBase() 566 : mRefs(new weakref_impl(this)) 567{ 568} 569 570RefBase::~RefBase() 571{ 572 if ((mRefs->mFlags & OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK) { 573 if (mRefs->mWeak == 0) { 574 delete mRefs; 575 } 576 } 577} 578 579void RefBase::extendObjectLifetime(int32_t mode) 580{ 581 android_atomic_or(mode, &mRefs->mFlags); 582} 583 584void RefBase::onFirstRef() 585{ 586} 587 588void RefBase::onLastStrongRef(const void* /*id*/) 589{ 590} 591 592bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id) 593{ 594 return (flags&FIRST_INC_STRONG) ? true : false; 595} 596 597void RefBase::onLastWeakRef(const void* /*id*/) 598{ 599} 600 601// --------------------------------------------------------------------------- 602 603void RefBase::moveReferences(void* dst, void const* src, size_t n, 604 const ReferenceConverterBase& caster) 605{ 606#if DEBUG_REFS 607 const size_t itemSize = caster.getReferenceTypeSize(); 608 for (size_t i=0 ; i<n ; i++) { 609 void* d = reinterpret_cast<void *>(intptr_t(dst) + i*itemSize); 610 void const* s = reinterpret_cast<void const*>(intptr_t(src) + i*itemSize); 611 RefBase* ref(reinterpret_cast<RefBase*>(caster.getReferenceBase(d))); 612 ref->mRefs->renameStrongRefId(s, d); 613 ref->mRefs->renameWeakRefId(s, d); 614 } 615#endif 616} 617 618// --------------------------------------------------------------------------- 619 620TextOutput& printStrongPointer(TextOutput& to, const void* val) 621{ 622 to << "sp<>(" << val << ")"; 623 return to; 624} 625 626TextOutput& printWeakPointer(TextOutput& to, const void* val) 627{ 628 to << "wp<>(" << val << ")"; 629 return to; 630} 631 632 633}; // namespace android 634