Android智能指针(五):sp、wp的析构

前言

前面我们都已经说完了,当前计数器已经是S1W2了,那么当他们使用结束之后又是怎么回收的呢?我们要知道怎么来也应该知道怎么去的。
在函数结束之后,就会走到对应的析构函数中。

wp的析构函数

template<typename T>
wp<T>::~wp()
{
    if (m_ptr) m_refs->decWeak(this);
}

额,从函数名就可以看出来,是直接将weak的数量进行了-1,那么真的有那么容易吗?

void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id); // 无内容
    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
    ALOGW_IF(BAD_WEAK(c), "decWeak called on %p too many times",
            this);
    if (c != 1) return; // c==1 说明当前结果就是0.
    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;
    }
}

一看,果然没有那么简单。
1.如果当前正好是最后1个,减下去之后就变成0,那么进入flag判断。
2.如果不是是strong的lifetime,那么就可以直接走删除操作,删除该对象。
3.lifetimestrong的,查看strong指针是否进行过赋值,如果没有赋值,那么其实就没有可以删除的。如果是复制了的,那么其实impl就是可以被删除的。

sp的析构函数

template<typename T>
sp<T>::~sp() {
    if (m_ptr)
        m_ptr->decStrong(this);
}

果然也是如此的简单,那么我们看看具体的实现吧。

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);
    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
#if PRINT_REFS
    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    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) {
            delete this;
            // 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);
}

最后的decweak我们就不说了,因为前面已经说过了。那么我们看前面。
1.原子操作,拿到当前的计数,如果是0,那么就说明需要进行操作了。
2.进行laststrongref操作。
3.如果当前的flag是lifetimestrong,那么就可以delete这个了。

LIFE_TIME

其实我们都可以看到,在decstrong和decweak的时候,都需要进行LIFE_TIME的判断来判断是否需要删除。那我们先看第一种情况。

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;
        }
    } else if (mRefs->mStrong.load(std::memory_order_relaxed) == INITIAL_STRONG_VALUE) {
        // We never acquired a strong reference on this object.
#if DEBUG_REFBASE_DESTRUCTION
        // Treating this as fatal is prone to causing boot loops. For debugging, it's
        // better to treat as non-fatal.
        ALOGD("RefBase: Explicit destruction, weak count = %d (in %p)", mRefs->mWeak.load(), this);
        CallStack::logStack(LOG_TAG);
#else
        LOG_ALWAYS_FATAL("RefBase: Explicit destruction, weak count = %d", mRefs->mWeak.load());
#endif
    }
    // For debugging purposes, clear mRefs.  Ineffective against outstanding wp's.
    const_cast<weakref_impl*&>(mRefs) = nullptr;
}

如果lifetime是weak的话,那么就可以直接删除影子对象。

LIFE_TIME_WEAK

在decstrong的时候,就不会直接删除该对象,而是到了decweak的时候才会删除。会将对象和对应的影子对象一并删除。

LIFE_TIME_STRONG

如果当前对象flag是strong,那么在strong==0的时候就会删除该对象。当强弱引用都减到0,普遍常见是会把实际对象和weakref_impl对象都释放。