// acquires a strong reference if there is already one. boolattemptIncStrong(constvoid* id);
// acquires a weak reference if there is already one. // This is not always safe. see ProcessState.cpp and BpBinder.cpp // for proper use. boolattemptIncWeak(constvoid* id);
//! DEBUGGING ONLY: Get current weak ref count. int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object. voidprintRefs()const;
//! DEBUGGING ONLY: Enable tracking for this object. // enable -- enable/disable tracking // retain -- when tracking is enable, if true, then we save a stack trace // for each reference and dereference; when retain == false, we // match up references and dereferences and keep only the // outstanding ones.
protected: RefBase(); virtual ~RefBase(); //! Flags for extendObjectLifetime() enum { OBJECT_LIFETIME_STRONG = 0x0000, OBJECT_LIFETIME_WEAK = 0x0001, OBJECT_LIFETIME_MASK = 0x0001 }; voidextendObjectLifetime(int32_t mode); //! Flags for onIncStrongAttempted() enum { FIRST_INC_STRONG = 0x0001 }; // Invoked after creation of initial strong pointer/reference. virtualvoidonFirstRef(); // Invoked when either the last strong reference goes away, or we need to undo // the effect of an unnecessary onIncStrongAttempted. virtualvoidonLastStrongRef(constvoid* id); // Only called in OBJECT_LIFETIME_WEAK case. Returns true if OK to promote to // strong reference. May have side effects if it returns true. // The first flags argument is always FIRST_INC_STRONG. // TODO: Remove initial flag argument. virtualboolonIncStrongAttempted(uint32_t flags, constvoid* id); // Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either // kind goes away. Unused. // TODO: Remove. virtualvoidonLastWeakRef(constvoid* id);
// system/core/libutils/RefBase.cpp void RefBase::incStrong(constvoid* id) const { weakref_impl* const refs = mRefs; refs->incWeak(id); refs->addStrongRef(id); constint32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed); ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs); if (c != INITIAL_STRONG_VALUE) { return; }
int32_t old __unused = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, std::memory_order_relaxed); // A decStrong() must still happen after us. ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old); refs->mBase->onFirstRef(); }
// system/core/libutils/RefBase.cpp void RefBase::decStrong(constvoid* id) const { weakref_impl* const refs = mRefs; refs->removeStrongRef(id); // 空实现 constint32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release); LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times", refs); if (c == 1) { std::atomic_thread_fence(std::memory_order_acquire); refs->mBase->onLastStrongRef(id); int32_t flags = refs->mFlags.load(std::memory_order_relaxed); if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { deletethis; // The destructor does not delete refs in this case. } } // Note that even with only strong reference operations, the thread // deallocating this may not be the same as the thread deallocating refs. // That's OK: all accesses to this happen before its deletion here, // and all accesses to refs happen before its deletion in the final decWeak. // The destructor can safely access mRefs because either it's deleting // mRefs itself, or it's running entirely before the final mWeak decrement. // // Since we're doing atomic loads of `flags`, the static analyzer assumes // they can change between `delete this;` and `refs->decWeak(id);`. This is // not the case. The analyzer may become more okay with this patten when // https://bugs.llvm.org/show_bug.cgi?id=34365 gets resolved. NOLINTNEXTLINE refs->decWeak(id); }
ALOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow", this);
while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) { // 情况1: // we're in the easy/common case of promoting a weak-reference // from an existing strong reference. if (impl->mStrong.compare_exchange_weak(curCount, curCount+1, std::memory_order_relaxed)) { break; } // the strong count has changed on us, we need to re-assert our // situation. curCount was updated by compare_exchange_weak. } if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) { // we're now in the harder case of either: // - there never was a strong reference on us // - or, all strong references have been released int32_t flags = impl->mFlags.load(std::memory_order_relaxed); if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { // this object has a "normal" life-time, i.e.: it gets destroyed // when the last strong reference goes away if (curCount <= 0) { // 情况2: // the last strong-reference got released, the object cannot // be revived. decWeak(id); returnfalse; }
// 情况3: // here, curCount == INITIAL_STRONG_VALUE, which means // there never was a strong-reference, so we can try to // promote this object; we need to do that atomically. while (curCount > 0) { if (impl->mStrong.compare_exchange_weak(curCount, curCount+1, std::memory_order_relaxed)) { break; } // the strong count has changed on us, we need to re-assert our // situation (e.g.: another thread has inc/decStrong'ed us) // curCount has been updated. }
if (curCount <= 0) { // promote() failed, some other thread destroyed us in the // meantime (i.e.: strong count reached zero). decWeak(id); returnfalse; } } else { // 情况4: // this object has an "extended" life-time, i.e.: it can be // revived from a weak-reference only. // Ask the object's implementation if it agrees to be revived if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) { // it didn't so give-up. decWeak(id); returnfalse; } // grab a strong-reference, which is always safe due to the // extended life-time. curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed); // If the strong reference count has already been incremented by // someone else, the implementor of onIncStrongAttempted() is holding // an unneeded reference. So call onLastStrongRef() here to remove it. // (No, this is not pretty.) Note that we MUST NOT do this if we // are in fact acquiring the first reference. if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) { impl->mBase->onLastStrongRef(id); } } } impl->addStrongRef(id);
#if PRINT_REFS ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount); #endif
// curCount is the value of mStrong before we incremented it. // Now we need to fix-up the count if it was INITIAL_STRONG_VALUE. // This must be done safely, i.e.: handle the case where several threads // were here in attemptIncStrong(). // curCount > INITIAL_STRONG_VALUE is OK, and can happen if we're doing // this in the middle of another incStrong. The subtraction is handled // by the thread that started with INITIAL_STRONG_VALUE. if (curCount == INITIAL_STRONG_VALUE) { impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE, std::memory_order_relaxed); }
// system/core/libutils/RefBase.cpp void RefBase::weakref_type::decWeak(constvoid* id) { weakref_impl* const impl = static_cast<weakref_impl*>(this); impl->removeWeakRef(id); constint32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times", this); if (c != 1) return; atomic_thread_fence(std::memory_order_acquire);
int32_t flags = impl->mFlags.load(std::memory_order_relaxed); if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { // This is the regular lifetime case. The object is destroyed // when the last strong reference goes away. Since weakref_impl // outlives the object, it is not destroyed in the dtor, and // we'll have to do it here. if (impl->mStrong.load(std::memory_order_relaxed) == INITIAL_STRONG_VALUE) { // Decrementing a weak count to zero when object never had a strong // reference. We assume it acquired a weak reference early, e.g. // in the constructor, and will eventually be properly destroyed, // usually via incrementing and decrementing the strong count. // Thus we no longer do anything here. We log this case, since it // seems to be extremely rare, and should not normally occur. We // used to deallocate mBase here, so this may now indicate a leak. ALOGW("RefBase: Object at %p lost last weak reference " "before it had a strong reference", impl->mBase); } else { // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase); delete impl; } } else { // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference // is gone, we can destroy the object. impl->mBase->onLastWeakRef(id); delete impl->mBase; } }
RefBase::~RefBase() { int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed); // Life-time of this object is extended to WEAK, in // which case weakref_impl doesn't out-live the object and we // can free it now. if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) { // It's possible that the weak count is not 0 if the object // re-acquired a weak reference in its destructor if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) { delete mRefs; } } elseif (mRefs->mStrong.load(std::memory_order_relaxed) == INITIAL_STRONG_VALUE) { // We never acquired a strong reference on this object. LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0, "RefBase: Explicit destruction with non-zero weak " "reference count"); // TODO: Always report if we get here. Currently MediaMetadataRetriever // C++ objects are inconsistently managed and sometimes get here. // There may be other cases, but we believe they should all be fixed. delete mRefs; } // For debugging purposes, clear mRefs. Ineffective against outstanding wp's. const_cast<weakref_impl*&>(mRefs) = NULL; }