美文网首页
android中的wp和sp分析

android中的wp和sp分析

作者: Little熊猫 | 来源:发表于2018-09-11 10:15 被阅读0次

    一 关系图

    spwp.png

    二 各种场景应用

    1)初始化

    RefBase::RefBase()
    : mRefs(new weakref_impl(this))
    {
    }

    weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)
        , mWeak(0)
        , mBase(base)
        , mFlags(0)
    {
    }
    

    其中 mStrong的初始值是INITIAL_STRONG_VALUE=0X10000000,#define INITIAL_STRONG_VALUE (1<<28)
    而mWeak的初始值为0,一个weakref_impl 对象被创建

    1. 只有sp引用
      {
      sp<A> spA(new A);

    }

    template<typename T>
    sp<T>::sp(T* other)
            : m_ptr(other) {
        if (other)
            other->incStrong(this);
    }
    
    void RefBase::incStrong(const void* id) const
    {
        weakref_impl* const refs = mRefs;
        refs->incWeak(id);
        
        refs->addStrongRef(id);
        const int32_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 PRINT_REFS
        ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
    #endif
        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();
    }
    
    void RefBase::weakref_type::incWeak(const void* id)
    {
        weakref_impl* const impl = static_cast<weakref_impl*>(this);
        impl->addWeakRef(id);
        const int32_t c __unused = impl->mWeak.fetch_add(1,
                std::memory_order_relaxed);
        ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
    }
    

    在构造函数执行完毕后,mStrong和mWeak的值为1
    当spA在区域执行完毕后,调用析构函数

    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);
    }
    

    mStrong为1,最后一次引用,释放掉spA,其中调用refBase的析构函数

    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.
            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;
    }
    

    当调用decWeak时,由于flags为OBJECT_LIFETIME_STRONG,此时mStrong为0,调用delete impl释放掉第1步中的Impl

    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);
        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;
        }
    }
    
    
    1. 只有wp弱引用
    {
    wp<A> wpA(new A);
    }
    

    调用构造函数

    template<typename T>
    wp<T>::wp(const sp<T>& other)
        : m_ptr(other.m_ptr)
    {
        if (m_ptr) {
            m_refs = m_ptr->createWeak(this);
        }
    }
    RefBase::weakref_type* RefBase::createWeak(const void* id) const
    {
        mRefs->incWeak(id);
        return mRefs;
    }
    
    void RefBase::weakref_type::incWeak(const void* id)
    {
        weakref_impl* const impl = static_cast<weakref_impl*>(this);
        impl->addWeakRef(id);
        const int32_t c __unused = impl->mWeak.fetch_add(1,
                std::memory_order_relaxed);
        ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
    }
    

    通过代码分析,只是给mWeak计数器+1,而mStrong 则是初始值INITIAL_STRONG_VALUE,当wpA超过作用域被回收的时候,调用析构函数

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

    根据上面的代码,调用delete impl->mBase;释放掉wpA,同时RefBase的析构函数被调用,delete mRefs,释放weakref_impl

    1. 同时有wp 和sp指针
    {
    sp<A> spA(new A)
    wp<A> wpA(spA);
    }
    

    在构造期间 mStong = 1, mWeak = 2,在释放时先调用wpA的析构函数,mWeak=1,mStrong=1,然后调用spA的析构函数,同2)流程
    5)WP指针调用类方法
    由于WP没有重载"->",不能直接调用类方法,在调用decStrong中,Object可能被释放,
    我们需要将wp指针升级为sp指针

    template<typename T>
    sp<T> wp<T>::promote() const
    {
        sp<T> result;
        if (m_ptr && m_refs->attemptIncStrong(&result)) {
            result.set_pointer(m_ptr);
        }
        return result;
    }
    
    bool RefBase::weakref_type::attemptIncStrong(const void* id)
    {
        incWeak(id);
        
        weakref_impl* const impl = static_cast<weakref_impl*>(this);
        int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);
    
        ALOG_ASSERT(curCount >= 0,
                "attemptIncStrong called on %p after underflow", this);
    
        while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
            // 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) {
                    // the last strong-reference got released, the object cannot
                    // be revived.
                    decWeak(id);
                    return false;
                }
    
                // 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);
                    return false;
                }
            } else {
                // 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);
                    return false;
                }
                // 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);
        }
    
        return true;
    }
    

    first:当curCount > 0 & & curCount! = INITIAL_STRONG_VALUE,说明已经有sp指针指向,mStrong 加1
    second:如果没有sp指针的话,分如下几种情况
    Flag = OBJECT_LIFETIME_STRONG,curCount=0,说明object已经释放掉,此时强制转化,返回false
    third: 如果Flag = OBJECT_LIFETIME_STRONG, and curCount = INITIAL_STRONG_VALUE,没有sp引用,此时可以将mStrong加1
    four:如果Flag = OBJECT_LIFETIME_WEAK, and curCount <= 0 || curCount = = INITIAL_STRONG_VALUE,此种情况下mStrong加1

    相关文章

      网友评论

          本文标题:android中的wp和sp分析

          本文链接:https://www.haomeiwen.com/subject/yuvygftx.html