阅读android源码,Refbase,wp,sp一点所得
来源:互联网 发布:单机斗牛牛无网络破解 编辑:程序博客网 时间:2024/06/06 05:07
一、
RefBase是引用计数的类,它封装了引用计数的技术细节。包括增加强引用计数,增加弱引用计数,减少强引用计数,减少弱引用计数等等。
但是对RefBase的具体操作,却是委托给了weakref_impl这个类。就好比RefBase是一块农田,对农田的操作由weakref_impl这个农夫来操作。weakref_impl是RefBase内部定义的一个类weakref_type的派生类。强和弱引用计数的实际数据也是放在weakref_impl中的.下面是 weakref_impl这个类的定义
class RefBase::weakref_impl 表示它是RefBase的内部类
public RefBase::weakref_type 表示它继承RefBase的内部类weakref_type
class RefBase::weakref_impl : public RefBase::weakref_type{public: std::atomic<int32_t> mStrong; //强引用计数 std::atomic<int32_t> mWeak; //弱引用计数 RefBase* const mBase;//实际对象的影子 std::atomic<int32_t> mFlags;.........};注意RefBase* const mBase这个成员. 任意一个类,当他需要使用引用计数时,都需要继承RefBase这个类。在weakref_impl中设置这么一个RefBase类型的成员是什么用意?我们先看一下RefBase的构造函数,因为实际对象在构造时父类构造必须被率先调用,c++的多态!
RefBase::RefBase():mRefs(new weakref_impl(this)){//代码略}请看初始化代码mRefs(new weakref_impl(this))也就是说父类在构造的时候,先new了一个new weakref_impl,去初始化mRefs成员,这说明,RefBase这块农田内置了一个农夫weakref_impl,且这个农田的农夫在构造时诞生了!
并且用的是this作为参数,这个this可是实际对象哦,子类构造导致基类构造执行,传递的this自然是子类,也就是实际对象!既然实际对象作为农夫的构造参数,那么我们去看看这个weakref_impl的构造参数,他是怎么处理this的。
weakref_impl(RefBase* base) : mStrong(INITIAL_STRONG_VALUE) , mWeak(0) , mBase(base) , mFlags(0) { }weakref_impl的mBase成员保存的就是传递的this啊,前面说过这个this就是实际对象哦。所以,可以说weakref_impl保存了一个实际对象的引用.
现在可以看sp。sp使用了模板技术,先看一下sp的构造函数
template<typename T> sp<T>::sp(T* other):m_ptr(other) {if(other)other->incStrong(this); }T就代表着实际对象,已知实际对象是继承了RefBase的。m_ptr是sp的成员,类型就是T*,由此可见,强引用类sp内部保存了一个实际对象的引用,由成员m_ptr保存。且sp构造时调用了other->incStrong(this);
实际上就是RefBase的方法incStrong(),不就是多态吗!other是实际对象,它继承RefBase自然就调用RefBase的incStrong()!
但是强和弱引用计数的实际数据是放在weakref_impl中的,那么RefBase的方法incStrong()一旦被调用,又是如何影响到强和弱引用计数的数值变化呢?我们看看这个incStrong()函数的具体实现
void RefBase::incStrong(const void *id) {weakref_impl *const refs = mRefs;refs->addWeakRef(id); //空函数refs->incWeak(id);refs->addStrongRef(id);......... }原来在IncStrong()中生成了一个weakref_impl的指针,而这个指针等价于RefBase的成员mRefs. 前面说过了,mRefs就是指向着weakref_impl的。从而通过这个指针调用weakref_impl内部的方法实现了实际数值的改变。由此可见确实是weakref_impl在实际操作引用计数的数值。
RefBase::RefBase():mRefs(new weakref_impl(this)){//再看一眼RefBase的构造把,再次确定一下mRefs就是指向weakref_impl}
现在脉络有点清晰了。sp在构造的时候,首先将实际对象给保存起来了。
而实际对象因为它继承自RefBase, RefBase内部又保存着weakref_impl这个农夫的对象指针(农夫负责操作RefBase这块农田,农夫内部保存着实际的引用计数数值和实际对象). 所有虽然sp只保存了一个实际对象,但是只要sp愿意,它也可以定位到农夫,不是吗?小知识点:weakref_impl在修改引用计数数值的时候,都是使用了原子级操作,android_atomic_inc() 或者 android_atomic_dec(),这2个原子级操作的函数,返回值都是旧值,这一点要注意。比如android_atomic_inc()操作前旧值是1,则函数成功新值是2,但是返回值是旧值1.
根据incStrong()代码中的实际代码,其实不光令强引用计数+1也令弱引用计数+1。其他的暂时不关注了,只记住一点,sp的构造函数令强引用计数+1,弱引用计数同时+1;
顺便再来看一下wp的构造,wp是弱引用计数,构造好几个,随便挑一个来看看
templete<typename T>wp<T>::wp(const sp<T>& other):m_ptr(other.m_ptr){if(m_ptr)m_refs = m_ptr->createWeak(this);}m_ptr是T* 类型,同上面介绍sp时细述的一样,那这个createWeak()不出意外就是RefBase的方法咯,过去看看这个createWeak的实现
RefBase::weakref_type* RefBase::createWeak(const void*id) const{mRef->incWeak(id);return mRef;}哈,基类RefBase的mRef就是weakref_impl*类型嘛,mRef->incWeak()不就是调用weakref_impl的方法吗?绕一圈还是调用weakref_impl的incWeak()去给弱引用计数+1,并且返回weakref_impl* 给wp的m_Refs成员。
现在对sp和wp能看出一点区别了:
sp 有T* m_ptr 成员,这个成员就是实际对象的引用,但是这个m_ptr继承自RefBase,等价于m_ptr也包含了weakref_impl*;
wp 有weakref_impl m_Refs成员,也有T* m_ptr,已知m_ptr是保存了实际对象的引用的,m_Refs代表着weakref_impl;
sp会令强引用计数+1,弱引用计数+1
wp会令弱引用计数+1
构造看完了,来看看wp的析构函数
wp<T>::~wp(){if(m_ptr)m_refs->decWeak(this);}去调用weakref_impl的decWeak(),参数是wp的this,
void RefBase::weakref_type::decWeak(const void* id){//原子级操作减少弱引用计数,代码略if(弱引用!=1)return; //弱引用没到0,就直接返回了 //如果走到这里,弱引用计数应该是为0,if(xxx)//如果对象不受弱引用控制{if(强引用==初始值)delete impl->mBase; //干掉实际对象elsedelete impl;//农夫给干掉了}else{if(xxx) //如果既不受强引用控制也不受弱引用控制delete impl->mBase;//干掉实际对象}}
可以看出来,在函数先进行一次原子级操作,将弱引用计数-1之后。当弱引用计数==0的情况下,函数才回继续干活,否则函数立刻返回。wp的析构时是有可能干掉实际对象或者农夫impl的。
template<typename T> sp<T>::~sp() {if(m_ptr)m_ptr->decStrong(this); }根据多态,实际上调用的是RefBase的decStrong()
void RefBase::decStrong(const void *id) {//原子级操作,减少强引用计数,代码略过if(xx) //如果强引用计数==0{if(不受弱引用控制)delete this; //干掉实际对象,因为m_pter调用的decStrong().this就是实际对象}refs->decWeak(); }
如果干掉实际对象,已知实际对象T是继承RefBase的类,则RefBase这个父类会率先析构,我们继续看看整个的析构流程
RefBase::~RefBase() {if(mRefs->mWeak==0){delete mRefs;} }
RefBase的析构函数中身,在满足条件的情况下将weakref_impl对象mRefs也一块干掉了。
这个满足条件为什么是mRefs->mWeak==0,即弱引用计数为0呢?已知sp会令强引用+1&弱引用+1,而wp会令弱引用+1,
当sp和wp一块使用时,有可能令弱引用数值 > 强引用数值,所以要判断一下,当强引用==0时,且弱引用==0才可以释放weakref_impl对象mRefs.
此外在强引用==0的时候,依然有可能存在其他的弱指针通过weakref_impl在引用实际对象,所以必须弱引用==0才可以析构weakref_impl
在decStrong()中为何又调用refs->decWeak()呢?
我们再捋一下流程:
因为如果对象生命周期仅受到强引用计数控制,在decStrong()中会先干掉实际对象,而实际对象析构时跑到RefBase的析构中,顺带着把weakref_impl也给干掉了,
皆大欢喜,农田农夫都没了,sp也没有了,实际对象也没有了,清理的很干净。虽然decWeak()在函数底部被调用,但是它不做事,进去就返回了。如果对象生命周期受到弱引用计数控制,则decStrong()中干掉实际对象的代码就不会得到执行,流程向下跑到decWeak()。 这时候decWeak()就不会立刻返回啦,它要做事,一旦发现弱引用也是0,强应用也是0,就会干掉实际对象,同上实际对象析构会顺带 析构RefBase,RefBase析构顺带析构weakref_impl,此时也是农田农夫没有了,wp自身也被析构没有了,实际对象也没有了,清理的也很干净。而 如果弱引用=0,而强引用有效,则仅仅干掉weakref_impl,实际对象的清理工作显然交给sp去操心了
很复杂很绕,分析的应该还不是很完整,但是学到不少,尤其是之前学类的时候,完全没有注意到的细节,很有帮助!
阅读全文
0 0
- 阅读android源码,Refbase,wp,sp一点所得
- Android RefBase类(sp,wp)
- Android RefBase类(sp,wp)
- ANDROID -- sp,wp,RefBase 使用
- Android sp,wp,RefBase浅析
- Android中的RefBase,sp和wp
- Android - 引用计数(sp、wp、Refbase)
- Android指针管理:RefBase,SP,WP
- android 中的的 sp/wp/RefBase
- Android指针管理:RefBase,SP,WP
- Android指针管理:RefBase,SP,WP
- Android指针管理:RefBase,SP,WP
- Android指针管理:RefBase,SP,WP
- Android - 引用计数(sp、wp、Refbase)
- Android指针管理:RefBase,SP,WP
- Android指针管理:RefBase,SP,WP
- sp wp RefBase
- RefBase, sp, wp
- java项目导入
- Java关键字final、static使用总结
- Educational Codeforces Round 22
- This absolute uri http://Java.sun.com/jsp/jstl/core) cannot be resolved in either web.xml or the jar
- What are: DNS, DHCP, IP Addresses and Subnet Mask
- 阅读android源码,Refbase,wp,sp一点所得
- .NET图像处理库ImageGear for .NET v23发布,新增AcroForm功能和亚洲OCR丨附下载
- Day7:Linux的启动流程、模块管理和Loader
- Eclipse 项目中的包路径变成文件夹目录形式了
- Web app root system property already set to different value 错误
- 金钱是婚姻的基础
- 支付宝生成应用公钥(支付出现der input, integer tag error)
- Android
- 再窥--单链表和顺序存储