package cn.wjdiankong.smartpointer;
public class RefBase {
private weakref_impl mRefs;
public static final int OBJECT_LIFETIME_STRONG = 0x0000;//使用强引用计数管理生命周期
public static final int OBJECT_LIFETIME_WEAK = 0x0001;//使用弱引用计数管理
public static final int OBJECT_LIFETIME_FOREVER = 0x0003;//使用弱引用计数管理,这里我们可以看到FOREVER包含了WEAK情况
public static final int OBJECT_LIFETIME_MASK = 0x0001;
//为什么这里不用0作为初始化的值,因为后面需要判断一个状态就是强引用计数有没有被使用过,如果用0的话,那么就不能区分0值代表是没使用过,还是使用过了清零了,所以这里不用0来做初始化值
public static int INITIAL_STRONG_VALUE = (1<<28);
public RefBase(){
mRefs = new weakref_impl(INITIAL_STRONG_VALUE,0,this,OBJECT_LIFETIME_STRONG);
}
public void onLastWeakRef(){
System.out.println("on last weakref...");
}
public void onLastStrongRef(){
System.out.println("on last strongref...");
}
public void onFirstRef(){
System.out.println("on firstref...");
}
public void setFlag(int flag){
mRefs.setFlag(flag);
}
/**
* 增加弱引用
*/
public void incWeak(){
mRefs.mWeak.getAndIncrement();
System.out.println("weak count:"+mRefs.mWeak.get());
}
/**
* void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->removeWeakRef(id);
const int32_t c = android_atomic_dec(&impl->mWeak);//弱引用减1,返回旧值
ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
if (c != 1) return;//旧的弱引用值不为1,说明弱引用计数不为0,则返回
//此时弱引用计数为0,需要删除weakref_impl对像
if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {//采用强引用计数管理生命周期
if (impl->mStrong == INITIAL_STRONG_VALUE) {
//强引用计数值为初始化值,而弱引用计数值已经变成0了,因此需要删除对像
delete impl->mBase;//删除真实对像,会引发对像的析构函数,析构函数中会删除weakref_impl对像.
} else {
// ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
delete impl;//强引用计数不是初始值,那么直接删除weakref_impl对像,而不要删除真实对像,因为它采用强引用计数生命周期管理
}
} else {
//使用弱引用计数管理生命周期
impl->mBase->onLastWeakRef(id);
if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
delete impl->mBase;//删除真实对像,会引发对像的析构函数,析构函数中会删除weakref_impl对像
}
}
}
*/
/**
* 减少弱应用,要做的事有两件:是否要释放真实对象,是否要释放影子对象
* 1、如果生命周期是弱引用来控制,那么在这里就需要做判断,弱应用的计数是否为0,是否要释放真实对象和影子对象
* 2、如果生命周期是强引用来控制的,那么这里也要判断一下,如果强引用计数为0的话,需要释放真实对象,弱引用计数是否为0,是否要释放影子对象
* 弱引用计数是关系影子对象的,如果弱引用计数为0,那么影子对象一定要释放,但是真实对象不一定要释放
* 强引用计数是关系真实对象的,如果强引用计数为0,那么真实对象一定要释放的,但是影子对象不一定释放
*
* A. 如果对象的标志位被设置为0,那么只要发现对象的强引用计数值为0,那就会自动delete掉这个对象;
B. 如果对象的标志位被设置为OBJECT_LIFETIME_WEAK,那么只有当对象的强引用计数和弱引用计数都为0的时候,才会自动delete掉这个对象;
C. 如果对象的标志位被设置为OBJECT_LIFETIME_FOREVER,那么对象就永远不会自动被delete掉,谁new出来的对象谁来delete掉。
*/
public void decWeak(){
int val = mRefs.mWeak.getAndDecrement();
System.out.println("weak count:"+mRefs.mWeak.get());
if(val != 1){
return;
}
//如果是强生命周期
if((mRefs.mFlags&RefBase.OBJECT_LIFETIME_MASK) == RefBase.OBJECT_LIFETIME_STRONG){
if(mRefs.mStrong.get() == RefBase.INITIAL_STRONG_VALUE){
//释放真实对象
dealloc();
}else{
//释放影子对象
mRefs.dealloc();
}
}else{
mRefs.mBase.onLastWeakRef();
//two case:OBJECT_LIFETIME_{WEAK|FOREVER}
//这里需要注意的是:4.4之后的源码没有了OBJECT_LIFETIME_FOREVER这个变量了,代码变成了:OBJECT_LIFETIME_WEAK了
if((mRefs.mFlags&RefBase.OBJECT_LIFETIME_FOREVER) != RefBase.OBJECT_LIFETIME_FOREVER){
//释放真实对象
dealloc();
}
}
}
/**
* void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id);//弱引用计数加1
refs->addStrongRef(id);
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);//强引用计数-INITIAL_STRONG_VALUE,强引用计数现在等于1
refs->mBase->onFirstRef();//refBase的继承者可以覆盖此函数,在第一次引用时来做一些初始化操作
}
*/
/**
* 增加强引用计数
* 这里同事也要增加弱应用计数
*/
public void incStrong(){
incWeak();
int val = mRefs.mStrong.getAndIncrement();
System.out.println("strong count:"+mRefs.mStrong.get());
if(val != RefBase.INITIAL_STRONG_VALUE){
return;
}
//这一行要注意了,看到是加上强引用计数的默认值的负数,这样就能开始正常计数了
mRefs.mStrong.addAndGet(-RefBase.INITIAL_STRONG_VALUE) ;
mRefs.mBase.onFirstRef();
}
/**
* void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id);
const int32_t c = android_atomic_dec(&refs->mStrong);//强引用计数减1,并返回旧值
#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);//引用值为0了,调用onLastStrongRef
if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
delete this;//如果是强引用计数生命周期管理方式,删除此对像
}
}
refs->decWeak(id);//弱引用减1
}
*/
/**
* 减少强引用计数
* 需要做的事就是看看是否要释放真实对象,因为强引用和真实对象关联的
*/
public void decStrong(){
int val = mRefs.mStrong.getAndDecrement();
System.out.println("strong count:"+mRefs.mStrong.get());
//如果i=1,说明强引用计数为0了
if(val == 1){
//onLastWeakRef();
if((mRefs.mFlags&RefBase.OBJECT_LIFETIME_MASK) == RefBase.OBJECT_LIFETIME_STRONG){
dealloc();
}
}
decWeak();
}
/**
* RefBase::~RefBase()
{
if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
delete mRefs;//强引用计数是初始化值,那么删除weakref_impl对像
} else {
if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {//对像采用弱引用生命周期
if (mRefs->mWeak == 0) {
delete mRefs;//检查弱引用计数值,如果为0就删除weakref_impl对像
}
}
}
const_cast<weakref_impl*&>(mRefs) = NULL;
}
*/
/**
* 真实对象被销毁的时候,需要做一个工作就是释放影子对象
* 释放影子对象有两个场景:
* 1、如果强引用计数根本没有被使用过,那么直接释放
* 2、如果强引用计数使用过,但是采用的是非强生命周期管理方式,也是释放
*/
private void dealloc(){
System.out.println("refbase dealloc...");
if(mRefs.mStrong.get() == INITIAL_STRONG_VALUE){
//如果没有使用过强引用指针,那么直接释放影子对象
mRefs.dealloc();
}else{
if((mRefs.mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG){
if(mRefs.mWeak.get() == 0){
//如果采用的不是强引用管理什么周期的,并且弱引用计数为0,那么也要释放影子对象的
mRefs.dealloc();
}
}
}