Android中的RefBase,sp和wp

来源:互联网 发布:网络销售项目计划书 编辑:程序博客网 时间:2024/06/10 16:56

在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。