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 // #define LOG_NDEBUG 0 19 20 #include <fcntl.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <sys/stat.h> 24 #include <sys/types.h> 25 #include <typeinfo> 26 #include <unistd.h> 27 28 #include <utils/RefBase.h> 29 30 #include <utils/CallStack.h> 31 #include <utils/Log.h> 32 #include <utils/threads.h> 33 34 #ifndef __unused 35 #define __unused __attribute__((__unused__)) 36 #endif 37 38 // compile with refcounting debugging enabled 39 #define DEBUG_REFS 0 40 41 // whether ref-tracking is enabled by default, if not, trackMe(true, false) 42 // needs to be called explicitly 43 #define DEBUG_REFS_ENABLED_BY_DEFAULT 0 44 45 // whether callstack are collected (significantly slows things down) 46 #define DEBUG_REFS_CALLSTACK_ENABLED 1 47 48 // folder where stack traces are saved when DEBUG_REFS is enabled 49 // this folder needs to exist and be writable 50 #define DEBUG_REFS_CALLSTACK_PATH "/data/debug" 51 52 // log all reference counting operations 53 #define PRINT_REFS 0 54 55 // --------------------------------------------------------------------------- 56 57 namespace android { 58 59 // Usage, invariants, etc: 60 61 // It is normally OK just to keep weak pointers to an object. The object will 62 // be deallocated by decWeak when the last weak reference disappears. 63 // Once a a strong reference has been created, the object will disappear once 64 // the last strong reference does (decStrong). 65 // AttemptIncStrong will succeed if the object has a strong reference, or if it 66 // has a weak reference and has never had a strong reference. 67 // AttemptIncWeak really does succeed only if there is already a WEAK 68 // reference, and thus may fail when attemptIncStrong would succeed. 69 // OBJECT_LIFETIME_WEAK changes this behavior to retain the object 70 // unconditionally until the last reference of either kind disappears. The 71 // client ensures that the extendObjectLifetime call happens before the dec 72 // call that would otherwise have deallocated the object, or before an 73 // attemptIncStrong call that might rely on it. We do not worry about 74 // concurrent changes to the object lifetime. 75 // mStrong is the strong reference count. mWeak is the weak reference count. 76 // Between calls, and ignoring memory ordering effects, mWeak includes strong 77 // references, and is thus >= mStrong. 78 // 79 // A weakref_impl is allocated as the value of mRefs in a RefBase object on 80 // construction. 81 // In the OBJECT_LIFETIME_STRONG case, it is deallocated in the RefBase 82 // destructor iff the strong reference count was never incremented. The 83 // destructor can be invoked either from decStrong, or from decWeak if there 84 // was never a strong reference. If the reference count had been incremented, 85 // it is deallocated directly in decWeak, and hence still lives as long as 86 // the last weak reference. 87 // In the OBJECT_LIFETIME_WEAK case, it is always deallocated from the RefBase 88 // destructor, which is always invoked by decWeak. DecStrong explicitly avoids 89 // the deletion in this case. 90 // 91 // Memory ordering: 92 // The client must ensure that every inc() call, together with all other 93 // accesses to the object, happens before the corresponding dec() call. 94 // 95 // We try to keep memory ordering constraints on atomics as weak as possible, 96 // since memory fences or ordered memory accesses are likely to be a major 97 // performance cost for this code. All accesses to mStrong, mWeak, and mFlags 98 // explicitly relax memory ordering in some way. 99 // 100 // The only operations that are not memory_order_relaxed are reference count 101 // decrements. All reference count decrements are release operations. In 102 // addition, the final decrement leading the deallocation is followed by an 103 // acquire fence, which we can view informally as also turning it into an 104 // acquire operation. (See 29.8p4 [atomics.fences] for details. We could 105 // alternatively use acq_rel operations for all decrements. This is probably 106 // slower on most current (2016) hardware, especially on ARMv7, but that may 107 // not be true indefinitely.) 108 // 109 // This convention ensures that the second-to-last decrement synchronizes with 110 // (in the language of 1.10 in the C++ standard) the final decrement of a 111 // reference count. Since reference counts are only updated using atomic 112 // read-modify-write operations, this also extends to any earlier decrements. 113 // (See "release sequence" in 1.10.) 114 // 115 // Since all operations on an object happen before the corresponding reference 116 // count decrement, and all reference count decrements happen before the final 117 // one, we are guaranteed that all other object accesses happen before the 118 // object is destroyed. 119 120 121 #define INITIAL_STRONG_VALUE (1<<28) 122 123 // --------------------------------------------------------------------------- 124 125 class RefBase::weakref_impl : public RefBase::weakref_type 126 { 127 public: 128 std::atomic<int32_t> mStrong; 129 std::atomic<int32_t> mWeak; 130 RefBase* const mBase; 131 std::atomic<int32_t> mFlags; 132 133 #if !DEBUG_REFS 134 135 weakref_impl(RefBase* base) 136 : mStrong(INITIAL_STRONG_VALUE) 137 , mWeak(0) 138 , mBase(base) 139 , mFlags(0) 140 { 141 } 142 143 void addStrongRef(const void* /*id*/) { } 144 void removeStrongRef(const void* /*id*/) { } 145 void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { } 146 void addWeakRef(const void* /*id*/) { } 147 void removeWeakRef(const void* /*id*/) { } 148 void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { } 149 void printRefs() const { } 150 void trackMe(bool, bool) { } 151 152 #else 153 154 weakref_impl(RefBase* base) 155 : mStrong(INITIAL_STRONG_VALUE) 156 , mWeak(0) 157 , mBase(base) 158 , mFlags(0) 159 , mStrongRefs(NULL) 160 , mWeakRefs(NULL) 161 , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT) 162 , mRetain(false) 163 { 164 } 165 166 ~weakref_impl() 167 { 168 bool dumpStack = false; 169 if (!mRetain && mStrongRefs != NULL) { 170 dumpStack = true; 171 ALOGE("Strong references remain:"); 172 ref_entry* refs = mStrongRefs; 173 while (refs) { 174 char inc = refs->ref >= 0 ? '+' : '-'; 175 ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); 176 #if DEBUG_REFS_CALLSTACK_ENABLED 177 refs->stack.log(LOG_TAG); 178 #endif 179 refs = refs->next; 180 } 181 } 182 183 if (!mRetain && mWeakRefs != NULL) { 184 dumpStack = true; 185 ALOGE("Weak references remain!"); 186 ref_entry* refs = mWeakRefs; 187 while (refs) { 188 char inc = refs->ref >= 0 ? '+' : '-'; 189 ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); 190 #if DEBUG_REFS_CALLSTACK_ENABLED 191 refs->stack.log(LOG_TAG); 192 #endif 193 refs = refs->next; 194 } 195 } 196 if (dumpStack) { 197 ALOGE("above errors at:"); 198 CallStack stack(LOG_TAG); 199 } 200 } 201 202 void addStrongRef(const void* id) { 203 //ALOGD_IF(mTrackEnabled, 204 // "addStrongRef: RefBase=%p, id=%p", mBase, id); 205 addRef(&mStrongRefs, id, mStrong.load(std::memory_order_relaxed)); 206 } 207 208 void removeStrongRef(const void* id) { 209 //ALOGD_IF(mTrackEnabled, 210 // "removeStrongRef: RefBase=%p, id=%p", mBase, id); 211 if (!mRetain) { 212 removeRef(&mStrongRefs, id); 213 } else { 214 addRef(&mStrongRefs, id, -mStrong.load(std::memory_order_relaxed)); 215 } 216 } 217 218 void renameStrongRefId(const void* old_id, const void* new_id) { 219 //ALOGD_IF(mTrackEnabled, 220 // "renameStrongRefId: RefBase=%p, oid=%p, nid=%p", 221 // mBase, old_id, new_id); 222 renameRefsId(mStrongRefs, old_id, new_id); 223 } 224 225 void addWeakRef(const void* id) { 226 addRef(&mWeakRefs, id, mWeak.load(std::memory_order_relaxed)); 227 } 228 229 void removeWeakRef(const void* id) { 230 if (!mRetain) { 231 removeRef(&mWeakRefs, id); 232 } else { 233 addRef(&mWeakRefs, id, -mWeak.load(std::memory_order_relaxed)); 234 } 235 } 236 237 void renameWeakRefId(const void* old_id, const void* new_id) { 238 renameRefsId(mWeakRefs, old_id, new_id); 239 } 240 241 void trackMe(bool track, bool retain) 242 { 243 mTrackEnabled = track; 244 mRetain = retain; 245 } 246 247 void printRefs() const 248 { 249 String8 text; 250 251 { 252 Mutex::Autolock _l(mMutex); 253 char buf[128]; 254 sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this); 255 text.append(buf); 256 printRefsLocked(&text, mStrongRefs); 257 sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this); 258 text.append(buf); 259 printRefsLocked(&text, mWeakRefs); 260 } 261 262 { 263 char name[100]; 264 snprintf(name, 100, DEBUG_REFS_CALLSTACK_PATH "/%p.stack", this); 265 int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644); 266 if (rc >= 0) { 267 write(rc, text.string(), text.length()); 268 close(rc); 269 ALOGD("STACK TRACE for %p saved in %s", this, name); 270 } 271 else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this, 272 name, strerror(errno)); 273 } 274 } 275 276 private: 277 struct ref_entry 278 { 279 ref_entry* next; 280 const void* id; 281 #if DEBUG_REFS_CALLSTACK_ENABLED 282 CallStack stack; 283 #endif 284 int32_t ref; 285 }; 286 287 void addRef(ref_entry** refs, const void* id, int32_t mRef) 288 { 289 if (mTrackEnabled) { 290 AutoMutex _l(mMutex); 291 292 ref_entry* ref = new ref_entry; 293 // Reference count at the time of the snapshot, but before the 294 // update. Positive value means we increment, negative--we 295 // decrement the reference count. 296 ref->ref = mRef; 297 ref->id = id; 298 #if DEBUG_REFS_CALLSTACK_ENABLED 299 ref->stack.update(2); 300 #endif 301 ref->next = *refs; 302 *refs = ref; 303 } 304 } 305 306 void removeRef(ref_entry** refs, const void* id) 307 { 308 if (mTrackEnabled) { 309 AutoMutex _l(mMutex); 310 311 ref_entry* const head = *refs; 312 ref_entry* ref = head; 313 while (ref != NULL) { 314 if (ref->id == id) { 315 *refs = ref->next; 316 delete ref; 317 return; 318 } 319 refs = &ref->next; 320 ref = *refs; 321 } 322 323 ALOGE("RefBase: removing id %p on RefBase %p" 324 "(weakref_type %p) that doesn't exist!", 325 id, mBase, this); 326 327 ref = head; 328 while (ref) { 329 char inc = ref->ref >= 0 ? '+' : '-'; 330 ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref); 331 ref = ref->next; 332 } 333 334 CallStack stack(LOG_TAG); 335 } 336 } 337 338 void renameRefsId(ref_entry* r, const void* old_id, const void* new_id) 339 { 340 if (mTrackEnabled) { 341 AutoMutex _l(mMutex); 342 ref_entry* ref = r; 343 while (ref != NULL) { 344 if (ref->id == old_id) { 345 ref->id = new_id; 346 } 347 ref = ref->next; 348 } 349 } 350 } 351 352 void printRefsLocked(String8* out, const ref_entry* refs) const 353 { 354 char buf[128]; 355 while (refs) { 356 char inc = refs->ref >= 0 ? '+' : '-'; 357 sprintf(buf, "\t%c ID %p (ref %d):\n", 358 inc, refs->id, refs->ref); 359 out->append(buf); 360 #if DEBUG_REFS_CALLSTACK_ENABLED 361 out->append(refs->stack.toString("\t\t")); 362 #else 363 out->append("\t\t(call stacks disabled)"); 364 #endif 365 refs = refs->next; 366 } 367 } 368 369 mutable Mutex mMutex; 370 ref_entry* mStrongRefs; 371 ref_entry* mWeakRefs; 372 373 bool mTrackEnabled; 374 // Collect stack traces on addref and removeref, instead of deleting the stack references 375 // on removeref that match the address ones. 376 bool mRetain; 377 378 #endif 379 }; 380 381 // --------------------------------------------------------------------------- 382 383 void RefBase::incStrong(const void* id) const 384 { 385 weakref_impl* const refs = mRefs; 386 refs->incWeak(id); 387 388 refs->addStrongRef(id); 389 const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed); 390 ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs); 391 #if PRINT_REFS 392 ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c); 393 #endif 394 if (c != INITIAL_STRONG_VALUE) { 395 return; 396 } 397 398 int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, 399 std::memory_order_relaxed); 400 // A decStrong() must still happen after us. 401 ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old); 402 refs->mBase->onFirstRef(); 403 } 404 405 void RefBase::decStrong(const void* id) const 406 { 407 weakref_impl* const refs = mRefs; 408 refs->removeStrongRef(id); 409 const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release); 410 #if PRINT_REFS 411 ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c); 412 #endif 413 ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs); 414 if (c == 1) { 415 std::atomic_thread_fence(std::memory_order_acquire); 416 refs->mBase->onLastStrongRef(id); 417 int32_t flags = refs->mFlags.load(std::memory_order_relaxed); 418 if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { 419 delete this; 420 // Since mStrong had been incremented, the destructor did not 421 // delete refs. 422 } 423 } 424 // Note that even with only strong reference operations, the thread 425 // deallocating this may not be the same as the thread deallocating refs. 426 // That's OK: all accesses to this happen before its deletion here, 427 // and all accesses to refs happen before its deletion in the final decWeak. 428 // The destructor can safely access mRefs because either it's deleting 429 // mRefs itself, or it's running entirely before the final mWeak decrement. 430 refs->decWeak(id); 431 } 432 433 void RefBase::forceIncStrong(const void* id) const 434 { 435 // Allows initial mStrong of 0 in addition to INITIAL_STRONG_VALUE. 436 // TODO: Better document assumptions. 437 weakref_impl* const refs = mRefs; 438 refs->incWeak(id); 439 440 refs->addStrongRef(id); 441 const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed); 442 ALOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow", 443 refs); 444 #if PRINT_REFS 445 ALOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c); 446 #endif 447 448 switch (c) { 449 case INITIAL_STRONG_VALUE: 450 refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, 451 std::memory_order_relaxed); 452 // fall through... 453 case 0: 454 refs->mBase->onFirstRef(); 455 } 456 } 457 458 int32_t RefBase::getStrongCount() const 459 { 460 // Debugging only; No memory ordering guarantees. 461 return mRefs->mStrong.load(std::memory_order_relaxed); 462 } 463 464 RefBase* RefBase::weakref_type::refBase() const 465 { 466 return static_cast<const weakref_impl*>(this)->mBase; 467 } 468 469 void RefBase::weakref_type::incWeak(const void* id) 470 { 471 weakref_impl* const impl = static_cast<weakref_impl*>(this); 472 impl->addWeakRef(id); 473 const int32_t c __unused = impl->mWeak.fetch_add(1, 474 std::memory_order_relaxed); 475 ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this); 476 } 477 478 479 void RefBase::weakref_type::decWeak(const void* id) 480 { 481 weakref_impl* const impl = static_cast<weakref_impl*>(this); 482 impl->removeWeakRef(id); 483 const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); 484 ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this); 485 if (c != 1) return; 486 atomic_thread_fence(std::memory_order_acquire); 487 488 int32_t flags = impl->mFlags.load(std::memory_order_relaxed); 489 if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { 490 // This is the regular lifetime case. The object is destroyed 491 // when the last strong reference goes away. Since weakref_impl 492 // outlive the object, it is not destroyed in the dtor, and 493 // we'll have to do it here. 494 if (impl->mStrong.load(std::memory_order_relaxed) 495 == INITIAL_STRONG_VALUE) { 496 // Special case: we never had a strong reference, so we need to 497 // destroy the object now. 498 delete impl->mBase; 499 } else { 500 // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase); 501 delete impl; 502 } 503 } else { 504 // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference 505 // is gone, we can destroy the object. 506 impl->mBase->onLastWeakRef(id); 507 delete impl->mBase; 508 } 509 } 510 511 bool RefBase::weakref_type::attemptIncStrong(const void* id) 512 { 513 incWeak(id); 514 515 weakref_impl* const impl = static_cast<weakref_impl*>(this); 516 int32_t curCount = impl->mStrong.load(std::memory_order_relaxed); 517 518 ALOG_ASSERT(curCount >= 0, 519 "attemptIncStrong called on %p after underflow", this); 520 521 while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) { 522 // we're in the easy/common case of promoting a weak-reference 523 // from an existing strong reference. 524 if (impl->mStrong.compare_exchange_weak(curCount, curCount+1, 525 std::memory_order_relaxed)) { 526 break; 527 } 528 // the strong count has changed on us, we need to re-assert our 529 // situation. curCount was updated by compare_exchange_weak. 530 } 531 532 if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) { 533 // we're now in the harder case of either: 534 // - there never was a strong reference on us 535 // - or, all strong references have been released 536 int32_t flags = impl->mFlags.load(std::memory_order_relaxed); 537 if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { 538 // this object has a "normal" life-time, i.e.: it gets destroyed 539 // when the last strong reference goes away 540 if (curCount <= 0) { 541 // the last strong-reference got released, the object cannot 542 // be revived. 543 decWeak(id); 544 return false; 545 } 546 547 // here, curCount == INITIAL_STRONG_VALUE, which means 548 // there never was a strong-reference, so we can try to 549 // promote this object; we need to do that atomically. 550 while (curCount > 0) { 551 if (impl->mStrong.compare_exchange_weak(curCount, curCount+1, 552 std::memory_order_relaxed)) { 553 break; 554 } 555 // the strong count has changed on us, we need to re-assert our 556 // situation (e.g.: another thread has inc/decStrong'ed us) 557 // curCount has been updated. 558 } 559 560 if (curCount <= 0) { 561 // promote() failed, some other thread destroyed us in the 562 // meantime (i.e.: strong count reached zero). 563 decWeak(id); 564 return false; 565 } 566 } else { 567 // this object has an "extended" life-time, i.e.: it can be 568 // revived from a weak-reference only. 569 // Ask the object's implementation if it agrees to be revived 570 if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) { 571 // it didn't so give-up. 572 decWeak(id); 573 return false; 574 } 575 // grab a strong-reference, which is always safe due to the 576 // extended life-time. 577 curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed); 578 } 579 580 // If the strong reference count has already been incremented by 581 // someone else, the implementor of onIncStrongAttempted() is holding 582 // an unneeded reference. So call onLastStrongRef() here to remove it. 583 // (No, this is not pretty.) Note that we MUST NOT do this if we 584 // are in fact acquiring the first reference. 585 if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) { 586 impl->mBase->onLastStrongRef(id); 587 } 588 } 589 590 impl->addStrongRef(id); 591 592 #if PRINT_REFS 593 ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount); 594 #endif 595 596 // curCount is the value of mStrong before we increment ed it. 597 // Now we need to fix-up the count if it was INITIAL_STRONG_VALUE. 598 // This must be done safely, i.e.: handle the case where several threads 599 // were here in attemptIncStrong(). 600 // curCount > INITIAL_STRONG_VALUE is OK, and can happen if we're doing 601 // this in the middle of another incStrong. The subtraction is handled 602 // by the thread that started with INITIAL_STRONG_VALUE. 603 if (curCount == INITIAL_STRONG_VALUE) { 604 impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE, 605 std::memory_order_relaxed); 606 } 607 608 return true; 609 } 610 611 bool RefBase::weakref_type::attemptIncWeak(const void* id) 612 { 613 weakref_impl* const impl = static_cast<weakref_impl*>(this); 614 615 int32_t curCount = impl->mWeak.load(std::memory_order_relaxed); 616 ALOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow", 617 this); 618 while (curCount > 0) { 619 if (impl->mWeak.compare_exchange_weak(curCount, curCount+1, 620 std::memory_order_relaxed)) { 621 break; 622 } 623 // curCount has been updated. 624 } 625 626 if (curCount > 0) { 627 impl->addWeakRef(id); 628 } 629 630 return curCount > 0; 631 } 632 633 int32_t RefBase::weakref_type::getWeakCount() const 634 { 635 // Debug only! 636 return static_cast<const weakref_impl*>(this)->mWeak 637 .load(std::memory_order_relaxed); 638 } 639 640 void RefBase::weakref_type::printRefs() const 641 { 642 static_cast<const weakref_impl*>(this)->printRefs(); 643 } 644 645 void RefBase::weakref_type::trackMe(bool enable, bool retain) 646 { 647 static_cast<weakref_impl*>(this)->trackMe(enable, retain); 648 } 649 650 RefBase::weakref_type* RefBase::createWeak(const void* id) const 651 { 652 mRefs->incWeak(id); 653 return mRefs; 654 } 655 656 RefBase::weakref_type* RefBase::getWeakRefs() const 657 { 658 return mRefs; 659 } 660 661 RefBase::RefBase() 662 : mRefs(new weakref_impl(this)) 663 { 664 } 665 666 RefBase::~RefBase() 667 { 668 if (mRefs->mStrong.load(std::memory_order_relaxed) 669 == INITIAL_STRONG_VALUE) { 670 // we never acquired a strong (and/or weak) reference on this object. 671 delete mRefs; 672 } else { 673 // life-time of this object is extended to WEAK, in 674 // which case weakref_impl doesn't out-live the object and we 675 // can free it now. 676 int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed); 677 if ((flags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) { 678 // It's possible that the weak count is not 0 if the object 679 // re-acquired a weak reference in its destructor 680 if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) { 681 delete mRefs; 682 } 683 } 684 } 685 // for debugging purposes, clear this. 686 const_cast<weakref_impl*&>(mRefs) = NULL; 687 } 688 689 void RefBase::extendObjectLifetime(int32_t mode) 690 { 691 // Must be happens-before ordered with respect to construction or any 692 // operation that could destroy the object. 693 mRefs->mFlags.fetch_or(mode, std::memory_order_relaxed); 694 } 695 696 void RefBase::onFirstRef() 697 { 698 } 699 700 void RefBase::onLastStrongRef(const void* /*id*/) 701 { 702 } 703 704 bool RefBase::onIncStrongAttempted(uint32_t flags, const void* /*id*/) 705 { 706 return (flags&FIRST_INC_STRONG) ? true : false; 707 } 708 709 void RefBase::onLastWeakRef(const void* /*id*/) 710 { 711 } 712 713 // --------------------------------------------------------------------------- 714 715 #if DEBUG_REFS 716 void RefBase::renameRefs(size_t n, const ReferenceRenamer& renamer) { 717 for (size_t i=0 ; i<n ; i++) { 718 renamer(i); 719 } 720 } 721 #else 722 void RefBase::renameRefs(size_t /*n*/, const ReferenceRenamer& /*renamer*/) { } 723 #endif 724 725 void RefBase::renameRefId(weakref_type* ref, 726 const void* old_id, const void* new_id) { 727 weakref_impl* const impl = static_cast<weakref_impl*>(ref); 728 impl->renameStrongRefId(old_id, new_id); 729 impl->renameWeakRefId(old_id, new_id); 730 } 731 732 void RefBase::renameRefId(RefBase* ref, 733 const void* old_id, const void* new_id) { 734 ref->mRefs->renameStrongRefId(old_id, new_id); 735 ref->mRefs->renameWeakRefId(old_id, new_id); 736 } 737 738 }; // namespace android 739