天天看点

Android中的RefBase,sp和wp

在Android中,RefBase结合了sp和wp,实现了一套通过引用计数的方法来控制对象声明周期的方法。

RefBase的定义在/frameworks/base/include/utils/RefBase.h,实现在/frameworks/base/libs/utils/RefBase.cpp。

wp的定义在/frameworks/base/include/utils/RefBase.h,

sp的定义在/frameworks/base/include/utils/StrongPointer.h中。

1.weakref_impl

看看RefBase的构造方法:

RefBase::RefBase()

    : mRefs(new weakref_impl(this))

{

}

方法体是空的,只是简单的给成员变量mRefs赋值。

mRefs在RefBase.h中的定义:weakref_impl* const mRefs;

继续看weakref_impl是什么。

weakref_impl在RefBase.h中只有一个private的声明,定义和实现都在RefBase.cpp中。

class RefBase::weakref_impl : public RefBase::weakref_type

{

    ......

}

weakref_impl又是派生自weakref_type。

构造方法:

weakref_impl(RefBase* base)

        : mStrong(INITIAL_STRONG_VALUE) //volatile int32_t mStrong;

        , mWeak(0)    //volatile int32_t mWeak;

        , mBase(base) //RefBase* const mBase;

        , mFlags(0) //volatile int32_t mFlags;

{

}

mBase又保存了创建它的RefBase,表示它实际代表的对象。

假设有一个class A,创建了一个A后,会相应的创建一个weak_ref,而且weak_ref中的mBase保存着实际的对象A。

这么做有什么用呢?可以看到weak_ref中有两个int值,其实就是两个引用计数器,一个强引用,一个弱引用。

假设1:

class A: public RefBase{}

A* pA = new A;

sp<A> spA(pA);

wp<A> wpA(spA);

1.sp

下面来看看sp的定义。

sp是一个模板类,看看sp的构造方法。

template<typename T>

sp<T>::sp(const sp<T>& other)

    : m_ptr(other.m_ptr) //这个m_ptr就是 T* m_ptr,就是一个T类型的指针

{

    if (m_ptr) m_ptr->incStrong(this);

}

所以sp<A> spA(pA),语句的意思就是,创建一个sp对象,sp对象中成员变量指向A对象。

在sp的构造方法中,又调用了A->incStrong(this),这个incStrong方法从字面上就可以看出,是增加强引用的引用计数。

void RefBase::incStrong(const void* id) const

{

    weakref_impl* const refs = mRefs; //取得weakref_impl引用

    refs->incWeak(id); //增加强引用的同时,弱引用计数也增加

    refs->addStrongRef(id); //release版本中,addStrongRef什么都不做

    //refs->mString的初始值是INITIAL_STRONG_VALUE,android_atomic_inc将refs->mString加1

    //返回的c为refs->mStrong的旧值INITIAL_STRONG_VALUE

    const int32_t c = android_atomic_inc(&refs->mStrong);

    ......

    //c的值为INITIAL_STRONG_VALUE,表示第一次创建强引用,否则直接返回

    if (c != INITIAL_STRONG_VALUE) 

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return; &nbsp;&nbsp;&nbsp; }

    //第一次强引用,会走到这里。

    //android_atomic_add是原子加操作,refs->mStrong的值是INITIAL_STRONG_VALUE+1,

    //然后加上-INITIAL_STRONG_VALUE,那么refs->mStrong的值就是1

    android_atomic_add(INITIAL_STRONG_VALUE, &refs>mStrong);

    //第一次创建强引用会回调RefBase的onFirstRef()方法,这个方法很重要,派生类可以重载次方法,做一些初始化操作。

    //在audio system中,很多类重载此方法!!!

    refs->mBase->onFirstRef();

}

sp构造后,强引用和弱引用都增加1。

sp析构方法:

template<typename T>

sp<T>::~sp()

{

    if (m_ptr) m_ptr->decStrong(this); //调用实际对象的decStrong,由RefBase实现

}

调用RefBase的decStrong方法:

void RefBase::decStrong(const void* id) const

{

    weakref_impl* const refs = mRefs;

    //强,弱引用都为1,减1后强引用计数为0

    const int32_t c = android_atomic_dec(&refs->mStrong);

    .......

    if (c == 1) {

        //回调onLastStrongRef,子类可实现此方法,进行一些收尾工作

        refs->mBase->onLastStrongRef(id);

        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG)

{ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//只删除了实际对象,未删除m_Refs &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete this; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

    }

    //弱引用计数减1,见下文wp析购的分析。其实此时实际对象A,已经被delete,弱引用也会被delete

    refs->decWeak(id);

}

上边delete this,会调用RefBase的析购方法。

RefBase::~RefBase()

{

    if (mRefs->mStrong == INITIAL_STRONG_VALUE)

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete mRefs; &nbsp;&nbsp;&nbsp; }

else {

        if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {

            //此时mWeak为1

            if (mRefs->mWeak == 0)

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete mRefs; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

        }

    }

}

2.wp

wp与sp的结构很相似,看看其中一个构造方法。

template<typename T>

wp<T>::wp(const sp<T>& other) //传入的是一个sp

    : m_ptr(other.m_ptr) //m_ptr就是sp中的m_ptr,指向实际对象

{

    if (m_ptr)

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_refs = m_ptr->createWeak(this);//获取RefBase(也就是A)中的mRefs(weakref_impl),sp中是没有m_refs的 &nbsp;&nbsp;&nbsp; }

}

下面看看createWeak:

RefBase::weakref_type* RefBase::createWeak(const void* id) const

{

    mRefs->incWeak(id); //调用RefBase的incWeak(),弱引用+1

    return mRefs; //返回RefBase(也就是A)中的mRefs(weakref_impl)

}

wp析构方法

template<typename T>

wp<T>::~wp()

{

    if (m_ptr) m_refs->decWeak(this);

}

调用m_refs的decWeak方法,实际上是调用weakref_impl的父类weakref_type的decWeak()。

void RefBase::weakref_type::decWeak(const void* id)

{

    weakref_impl* const impl = static_cast<weakref_impl*>(this);

    impl->removeWeakRef(id);

    //弱引用计数减1

    const int32_t c = android_atomic_dec(&impl->mWeak);

    if (c != 1) return;

    //若c为1,减1后为0,要考虑是否释放内存

    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {

        if (impl->mStrong == INITIAL_STRONG_VALUE)

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete impl->mBase; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

else

{ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//接上文sp的decStrong,当decStrong后强引用为0,会继续调用decWeak,那么弱引用也会为0, &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//就会delete自己,也就是delete weakref_impl。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete impl; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

    } else {

        //回调onLastStrongRef,子类可实现此方法,进行一些收尾工作

        impl->mBase->onLastWeakRef(id);

        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK)

{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete impl->mBase;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

    }

}

3.总结sp,wp的析构方法,得出结论:

当weakref_impl的mFlag为0(后面分析mFlag)时:

mStrong == 0:delete实际对象

mWeak == 0: delete weakref_impl

假设2:

class A: public RefBase{}

A* pA = new A;

wp<A> wpA(pA);

sp<A> spA = wpA.promote(); //通过promote方法,得到一个sp

1.wp

创建一个弱引用,前文有描述。

这里要记住,创建wp,弱引用会+1,但是强引用不会增加,还是初始值INITIAL_STRONG_VALUE。

主要看promote方法:

template<typename T>

sp<T> wp<T>::promote() const

{

    sp<T> result;

    if (m_ptr && m_refs->attemptIncStrong(&result))

{ //调用weakref_impl(实际上是父类weakref_type)的attemptIncStrong,生成ap &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result.set_pointer(m_ptr); //sp中m_ptr赋值为m_ptr &nbsp;&nbsp;&nbsp; }

    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;

    //强引用+1

    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {

        if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0)

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

        curCount = impl->mStrong;

    }

    //如果curCount=0,表示强引用计数是初始化过的

    //如果curCount=INITIAL_STRONG_VALUE,表示未初始化过

    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {

        bool allow;

        //第一次生成sp

        if (curCount == INITIAL_STRONG_VALUE)

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) \!= OBJECT_LIFETIME_WEAK &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \|\| impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

else

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

        //表示不允许生成sp,弱引用-1后,返回

        if (!allow)

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decWeak(id); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

        //强引用+1

        curCount = android_atomic_inc(&impl->mStrong);

        if (curCount > 0 && curCount < INITIAL_STRONG_VALUE)

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; impl->mBase->onLastStrongRef(id); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

    }

    .......

    if (curCount == INITIAL_STRONG_VALUE)

{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //强引用计数变为1 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //回调实际对象,通知第一次强引用 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; impl->mBase->onFirstRef(); &nbsp;&nbsp;&nbsp; }

    return true;

}

总结:由弱引用生成强引用,则强引用计数为1,弱引用计数为2。

2.对象声明周期的控制

enum {

    OBJECT_LIFETIME_STRONG  = 0x0000,

    OBJECT_LIFETIME_WEAK    = 0x0001,

    OBJECT_LIFETIME_MASK    = 0x0001

};

void    extendObjectLifetime(int32_t mode);

RefBase中,声明了一个枚举和extendObjectLifetime,来控制对象的声明周期。

void RefBase::extendObjectLifetime(int32_t mode)

{

    android_atomic_or(mode, &mRefs->mFlags);

}

看实现,就是给weakref_impl的mFlags赋值。

传入的mode就是上面定义的枚举。

总结:

weakref_impl.mFlag == OBJECT_LIFETIME_STRONG:

    强引用计数来控制对象的生命周期,弱引用对象控制weakref_impl的生命周期。

    强引用为0,对象被delete,弱引用为0时,weakref_impl被delete。

    记住:使用wp时,要又sp生成,否则可能会引起segment fault。

weakref_impl.mFlag == OBJECT_LIFETIME_WEAK:

    由弱引用来控制对象和weakref_impl的生命周期。

    强引用为0无作用,弱引用为0时,对象和weakref_impl被同时delete。

继续阅读