Android6.0 智能指针分析

       所有需要使用Android智能指针的类都要继承自RefBase类。

class RefBase
{
public:
            void            incStrong(const void* id) const;
            void            decStrong(const void* id) const;

            void            forceIncStrong(const void* id) const;

            //! DEBUGGING ONLY: Get current strong ref count.
            int32_t         getStrongCount() const;

    class weakref_type
    {
    public:
        RefBase*            refBase() const;

        void                incWeak(const void* id);
        void                decWeak(const void* id);

        // acquires a strong reference if there is already one.
        bool                attemptIncStrong(const void* id);

        // acquires a weak reference if there is already one.
        // This is not always safe. see ProcessState.cpp and BpBinder.cpp
        // for proper use.
        bool                attemptIncWeak(const void* id);

        //! DEBUGGING ONLY: Get current weak ref count.
        int32_t             getWeakCount() const;

        //! DEBUGGING ONLY: Print references held on object.
        void                printRefs() 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.

        void                trackMe(bool enable, bool retain);
    };

            weakref_type*   createWeak(const void* id) const;

            weakref_type*   getWeakRefs() const;

            //! DEBUGGING ONLY: Print references held on object.
    inline  void            printRefs() const { getWeakRefs()->printRefs(); }

            //! DEBUGGING ONLY: Enable tracking of object.
    inline  void            trackMe(bool enable, bool retain)
    {
        getWeakRefs()->trackMe(enable, retain);
    }

    typedef RefBase basetype;

protected:
                            RefBase();
    virtual                 ~RefBase();

    //! Flags for extendObjectLifetime()
    enum {
        OBJECT_LIFETIME_STRONG  = 0x0000,
        OBJECT_LIFETIME_WEAK    = 0x0001,
        OBJECT_LIFETIME_MASK    = 0x0001
    };

            void            extendObjectLifetime(int32_t mode);

    //! Flags for onIncStrongAttempted()
    enum {
        FIRST_INC_STRONG = 0x0001
    };

    virtual void            onFirstRef();
    virtual void            onLastStrongRef(const void* id);
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    virtual void            onLastWeakRef(const void* id);

private:
    friend class ReferenceMover;
    static void moveReferences(void* d, void const* s, size_t n,
            const ReferenceConverterBase& caster);

private:
    friend class weakref_type;
    class weakref_impl;

                            RefBase(const RefBase& o);
            RefBase&        operator=(const RefBase& o);

        weakref_impl* const mRefs;
};

Refbase有一个嵌套类weakref_type,此外Refbase还有一个类型为weakref_impl*的指针成员mRefs。

class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
    volatile int32_t    mStrong;
    volatile int32_t    mWeak;
    RefBase* const      mBase;
    volatile int32_t    mFlags;

#if !DEBUG_REFS

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

    void addStrongRef(const void* /*id*/) { }
    void removeStrongRef(const void* /*id*/) { }
    void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void addWeakRef(const void* /*id*/) { }
    void removeWeakRef(const void* /*id*/) { }
    void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void printRefs() const { }
    void trackMe(bool, bool) { }

#else

    weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)
        , mWeak(0)
        , mBase(base)
        , mFlags(0)
        , mStrongRefs(NULL)
        , mWeakRefs(NULL)
        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
        , mRetain(false)
    {
    }
    
    ~weakref_impl()
    {
        bool dumpStack = false;
        if (!mRetain && mStrongRefs != NULL) {
            dumpStack = true;
            ALOGE("Strong references remain:");
            ref_entry* refs = mStrongRefs;
            while (refs) {
                char inc = refs->ref >= 0 ? '+' : '-';
                ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
                refs->stack.log(LOG_TAG);
#endif
                refs = refs->next;
            }
        }

        if (!mRetain && mWeakRefs != NULL) {
            dumpStack = true;
            ALOGE("Weak references remain!");
            ref_entry* refs = mWeakRefs;
            while (refs) {
                char inc = refs->ref >= 0 ? '+' : '-';
                ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
                refs->stack.log(LOG_TAG);
#endif
                refs = refs->next;
            }
        }
        if (dumpStack) {
            ALOGE("above errors at:");
            CallStack stack(LOG_TAG);
        }
    }
    ...

weakref_impl类中也有一个类型为RefBase的指针成员,这样weakref_impl类和Refbasw类互相记录了对方的指针。另外,成员mStrong记录了强引用计数,初始值为2的

28次方。成员mWeak记录了弱引用计数,初始值为0。mFlags记录了对指针生命周期的处理方式,初始值0表示生命周期只受强引用计数影响;OBJECT_LIFETIME_WEAK表

示同时受强引用计数和弱引用计数影响;OBJECT_LIFETIME_FOREVER表示生命周期不受强引用计数和弱引用计数影响,退化为C++普通指针。其他成员变量都用于跟踪调

试,此处不再详述。

首先说下强指针是怎么处理计数的。强指针的标志是sp,sp是模板类,接收一个继承了RefBase的类作为模板。sp有一个指针成员变量m_ptr,指向其模板参数对象。

template 
class sp
{
public:
    inline sp() : m_ptr(0) { }

    sp(T* other);
    sp(const sp& other);
    template sp(U* other);
    template sp(const sp& other);

    ~sp();

    // Assignment

    sp& operator = (T* other);
    sp& operator = (const sp& other);

    template sp& operator = (const sp& other);
    template sp& operator = (U* other);

    //! Special optimization for use by ProcessState (and nobody else).
    void force_set(T* other);

    // Reset

    void clear();

    // Accessors

    inline  T&      operator* () const  { return *m_ptr; }
    inline  T*      operator-> () const { return m_ptr;  }
    inline  T*      get() const         { return m_ptr; }

    // Operators

    COMPARE(==)
    COMPARE(!=)
    COMPARE(>)
    COMPARE(<)
    COMPARE(<=)
    COMPARE(>=)

private:
    template friend class sp;
    template friend class wp;
    void set_pointer(T* ptr);
    T* m_ptr;
};

来看看sp的构造函数:
template
sp::sp(T* other)
: m_ptr(other)
  {
    if (other) other->incStrong(this);
  }
直接调用incStrong方法使被封装的指针强引用计数加1。进入RefBase的incStrong方法实现:

void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->incWeak(id);//弱引用计数减1
    
    refs->addStrongRef(id);//debug用
    const int32_t c = android_atomic_inc(&refs->mStrong);//原子操作,强引用计数加1
    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;
    }

    android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
    refs->mBase->onFirstRef();
}

android_atomic_inc对强引用计数加1,然后返回加1前的值。若加1前强引用计数不是初始值INITIAL_STRONG_VALUE,说明之前曾被强指针引用过,直接return;否则就

说明没被强指针引用过,加1后再减去INITIAL_STRONG_VALUE,得到1。onFirstRef是个空实现,可以自己添加首次被强引用后的相关操作。

incStrong过程中还调用了incweak使弱引用计数减1:

void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast(this);
    impl->addWeakRef(id);//debug用
    const int32_t c __unused = android_atomic_inc(&impl->mWeak);
    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
首先将weakref_type指针强转成派生类weakref_impl指针(ps:父类对象不可以向下转换成子类,但是父类指针可以向下转换成子类指针)。然后对弱引用计数加1。

可以看到,强引用计数和弱引用计数是同步的,强引用计数加1的同时,弱引用计数也会加1,所以弱引用计数大于或等于强引用计数。

再来分析下sp的析构函数:

template
sp::~sp()
{
    if (m_ptr) m_ptr->decStrong(this);//对强引用计数减1
}

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);//debug
    const int32_t c = android_atomic_dec(&refs->mStrong);
#if PRINT_REFS
    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
    if (c == 1) {//强引用计数为0
        refs->mBase->onLastStrongRef(id);
        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            delete this;
        }
    }
    refs->decWeak(id);
}

decStrong方法中,首先对强引用计数减1,android_atomic_dec返回减1前的值。若强引用计数为0且mFlags值为OBJECT_LIFETIME_STRONG,说明仅受强引用计数影

响,把Refbase释放掉。然后调用decWeak对弱引用计数减1。可见弱引用计数会随着强引用计数变化。

RefBase的析构函数中,若对象没被强指针引用过,则把mRefs成员释放掉。否则,当对象生命周期不是仅受强指针影响,弱引用计数为0时,才把mRefs释放掉。

RefBase::~RefBase()
{
    if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
        // we never acquired a strong (and/or weak) reference on this object.
        delete mRefs;
    } else {
        // life-time of this object is extended to WEAK or FOREVER, in
        // which case weakref_impl doesn't out-live the object and we
        // can free it now.
        if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
            // It's possible that the weak count is not 0 if the object
            // re-acquired a weak reference in its destructor
            if (mRefs->mWeak == 0) {
                delete mRefs;
            }
        }
    }
    // for debugging purposes, clear this.
    const_cast(mRefs) = NULL;

void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast(this);
    impl->removeWeakRef(id);//debug
    const int32_t c = android_atomic_dec(&impl->mWeak);
    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    if (c != 1) return;

    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlive the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong == INITIAL_STRONG_VALUE) {
            // Special case: we never had a strong reference, so we need to
            // destroy the object now.
            delete impl->mBase;
        } else {
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;
        }
    } else {
        // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
        impl->mBase->onLastWeakRef(id);//debug
        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
            // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
            // is gone, we can destroy the object.
            delete impl->mBase;
        }
    }
}

decweak方法会对弱引用计数减1,若减1后弱引用计数不为0,则直接返回。若弱引用计数为0,且对象生命周期仅取决于强引用计数,则进入下一步。此处又分两种情

况:1.对象还没被强指针引用过,即mStrong的值仍为初始值INITIAL_STRONG_VALUE,则把Rebase部分释放掉。2.强指针被引用过,因为弱引用计数为0,所以强引用计数也

为0,这里再把Rebase的指针成员mRefs释放掉。若弱引用计数为0,对象生命周期还仅取决于弱引用计数,则把RefBase释放掉。(ps:6.0版本中感觉delete impl->mBase和

delete  impl是等价的,这个问题有待商榷)


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

mRefs是efBase构造函数中new出来的对象,这个一定要手动释放。

这样就比较明显了:RefBase和weakref_impl互相关联,强引用计数加1,弱引用计数也加1;强引用计数减1,弱引用计数也减1;对象的生命周期取决于weakref_impl的

mFlags值。

同样地,wp(弱指针)的模板参数要继承自RefBase。wp的成员变量比sp多一个weakref_impl,wp类的构造函数如下所示:

    T*              m_ptr;
    weakref_type*   m_refs;


template
wp::wp(T* other)
    : m_ptr(other)
{
    if (other) m_refs = other->createWeak(this);
}

再看看createWeak方法:

RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);
    return mRefs;
}
调用的是incWeak方法,就是对对象的弱引用计数加1,返回weakref_impl类型成员变量。

void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast(this);
    impl->addWeakRef(id);//debug
    const int32_t c __unused = android_atomic_inc(&impl->mWeak);
    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}

wp的析构函数对弱引用计数减1:

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

弱指针是不能直接操作其指向的对象的,因为里面没有重载解引用所需的*和->符号。但是弱指针可以通过promote函数来提升为强指针,使其可以操作指向的对象。

template
sp wp::promote() const
{
    sp 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(this);
    int32_t curCount = impl->mStrong;

    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 (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
            break;
        }
        // the strong count has changed on us, we need to re-assert our
        // situation.
        curCount = impl->mStrong;
    }
    
    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
        if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == 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 (android_atomic_cmpxchg(curCount, curCount + 1,
                        &impl->mStrong) == 0) {
                    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 = impl->mStrong;
            }

            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 = android_atomic_inc(&impl->mStrong);
        }

        // 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

    // 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 = impl->mStrong;
    while (curCount >= INITIAL_STRONG_VALUE) {
        ALOG_ASSERT(curCount > INITIAL_STRONG_VALUE,
                "attemptIncStrong in %p underflowed to INITIAL_STRONG_VALUE",
                this);
        if (android_atomic_cmpxchg(curCount, curCount-INITIAL_STRONG_VALUE,
                &impl->mStrong) == 0) {
            break;
        }
        // the strong-count changed on us, we need to re-assert the situation,
        // for e.g.: it's possible the fix-up happened in another thread.
        curCount = impl->mStrong;
    }

    return true;
}

attemptIncStrong首先对弱引用计数加1。curCount记录当前的强引用计数。如果对象还在被强指针引用(强引用计数大于0且不等于初始值),则使其强引用计数加1,

android_atomic_cmpxchg失败的话,则恢复原值,重新对强引用计数进行加1操作。若对象从没被强指针引用过或者强引用计数小于或等于0,这里依据生命周期进行分情况讨

论:1.若对象仅受强指针影响,当强引用计数为0,说明对象已经被彻底释放了,无法进行提升操作,对弱引用计数减1恢复原值,直接返回false;强引用计数为初始值时,对其

强引用计数加1,后面还有一段if(curCount<0)的判断,我感觉有点多余,或者是水平有限看不懂。2.当生命周期为其他方式时,onIncStrongAttempted是RefBase中的一个虚函

数,可以由子类重写,大概就是是否允许提升弱指针,如果不允许就恢复弱引用计数的值,如果允许就对强引用计数加1。函数末尾,对之前在初始值的加1操作进行还原,将

强引用计数减去INITIAL_STRONG_VALUE,得到真实引用数。

返回到promote函数,如果对象存在而且可以进行指针提升,使用setPointer函数返回一个强指针,指针提升完成。

template
void sp::set_pointer(T* ptr) {
    m_ptr = ptr;
}



你可能感兴趣的:(Framework)