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