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)
//第一次强引用,会走到这里。
//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)
}
//弱引用计数减1,见下文wp析购的分析。其实此时实际对象A,已经被delete,弱引用也会被delete
refs->decWeak(id);
}
上边delete this,会调用RefBase的析购方法。
RefBase::~RefBase()
{
if (mRefs->mStrong == INITIAL_STRONG_VALUE)
else {
if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
//此时mWeak为1
if (mRefs->mWeak == 0)
}
}
}
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)
}
下面看看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)
else
} else {
//回调onLastStrongRef,子类可实现此方法,进行一些收尾工作
impl->mBase->onLastWeakRef(id);
if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK)
}
}
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))
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)
curCount = impl->mStrong;
}
//如果curCount=0,表示强引用计数是初始化过的
//如果curCount=INITIAL_STRONG_VALUE,表示未初始化过
if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
bool allow;
//第一次生成sp
if (curCount == INITIAL_STRONG_VALUE)
else
//表示不允许生成sp,弱引用-1后,返回
if (!allow)
//强引用+1
curCount = android_atomic_inc(&impl->mStrong);
if (curCount > 0 && curCount < INITIAL_STRONG_VALUE)
}
.......
if (curCount == INITIAL_STRONG_VALUE)
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。
- Android中的RefBase,sp和wp
- Android中的sp和wp类模板以及RefBase类
- Android中的sp和wp类模板以及RefBase类
- Android中的sp和wp类模板以及RefBase类
- android 中的的 sp/wp/RefBase
- Android RefBase类(sp,wp)
- Android RefBase类(sp,wp)
- ANDROID -- sp,wp,RefBase 使用
- Android sp,wp,RefBase浅析
- Android 的sp 和 wp 类模板 以及RefBase类
- Android 的sp 和 wp 类模板 以及RefBase类
- Android - 引用计数(sp、wp、Refbase)
- Android指针管理:RefBase,SP,WP
- Android指针管理:RefBase,SP,WP
- Android指针管理:RefBase,SP,WP
- Android指针管理:RefBase,SP,WP
- Android指针管理:RefBase,SP,WP
- Android - 引用计数(sp、wp、Refbase)
- Xcode使用教程详细讲解 1
- 二进制补码运算公式
- Linux文件编程
- SQL limit offset
- stdafx.h与Afx.h了解
- Android中的RefBase,sp和wp
- 基于位运算的权限控制
- 数组传参的三种方法:泛型;压扁数组;数组结构
- memcache学习笔记
- android安卓sqlite数据库 多线程并发 locked问题
- JavaScript 框架比较
- HDU1573 一元线性同余方程组
- 用OpenCV实现Photoshop曲线功能的'在图像中取样设置黑场'
- 在指定范围和数量中进行目标查找的一个公用容器