Android指针管理RefBaseSPWP.docx
- 文档编号:10155586
- 上传时间:2023-05-24
- 格式:DOCX
- 页数:25
- 大小:21.88KB
Android指针管理RefBaseSPWP.docx
《Android指针管理RefBaseSPWP.docx》由会员分享,可在线阅读,更多相关《Android指针管理RefBaseSPWP.docx(25页珍藏版)》请在冰点文库上搜索。
Android指针管理RefBaseSPWP
Android指针管理:
RefBase,SP,WP
Android中通过引用计数来实现智能指针,并且实现有强指针与弱指针。
由对象本身来提供引用计数器,但是对象不会去维护引用计数器的值,而是由智能指针来管理。
要达到所有对象都可用引用计数器实现智能指针管理的目标,可以定义一个公共类,提供引用计数的方法,所有对象都去继承这个公共类,这样就可以实现所有对象都可以用引用计数来管理的目标,在Android中,这个公共类就是RefBase,同时还有一个简单版本LightRefBase。
RefBase作为公共基类提供了引用计数的方法,但是并不去维护引用计数的值,而是由两个智能指针来进行管理:
sp(StrongPointer)和wp(WeakPointer),代表强引用计数和弱引用计数。
一、轻量级引用计数的实现:
LightRefBase
LightRefBase的实现很简单,只是内部保存了一个变量用于保存对象被引用的次数,并提供了两个函数用于增加或减少引用计数。
复制代码
template
classLightRefBase
{
public:
inlineLightRefBase():
mCount(0){}
inlinevoidincStrong(constvoid*id)const{
android_atomic_inc(&mCount);
}
inlinevoiddecStrong(constvoid*id)const{
if(android_atomic_dec(&mCount)==1){
deletestatic_cast
}
}
//!
DEBUGGINGONLY:
Getcurrentstrongrefcount.
inlineint32_tgetStrongCount()const{
returnmCount;
}
typedefLightRefBase
protected:
inline~LightRefBase(){}
private:
mutablevolatileint32_tmCount;
};
复制代码
二、sp(StrongPointer)
LightRefBase仅仅提供了引用计数的方法,具体引用数应该怎么管理,就要通过智能指针类来管理了,每当有一个智能指针指向对象时,对象的引用计数要加1,当一个智能指针取消指向对象时,对象的引用计数要减1,在C++中,当一个对象生成和销毁时会自动调用(拷贝)构造函数和析构函数,所以,对对象引用数的管理就可以放到智能指针的(拷贝)构造函数和析构函数中。
Android提供了一个智能指针可以配合LightRefBase使用:
sp,sp的定义如下:
复制代码
template
classsp
{
public:
inlinesp():
m_ptr(0){}
sp(T*other);
sp(constsp
template
template
~sp();
//Assignment
sp&operator=(T*other);
sp&operator=(constsp
template
template
//!
SpecialoptimizationforusebyProcessState(andnobodyelse).
voidforce_set(T*other);
//Reset
voidclear();
//Accessors
inlineT&operator*()const{return*m_ptr;}
inlineT*operator->()const{returnm_ptr;}
inlineT*get()const{returnm_ptr;}
//Operators
COMPARE(==)
COMPARE(!
=)
COMPARE(>)
COMPARE(<)
COMPARE(<=)
COMPARE(>=)
private:
template
template
voidset_pointer(T*ptr);
T*m_ptr;
};
复制代码
代码比较多,其中Accessors部分代码重载了*、->操作符使我们使用sp的时候就像使用真实的对象指针一样,可以直接操作对象的属性或方法,COMPARE是宏定义,用于重载关系操作符,由于对引用计数的控制主要是由(拷贝)构造函数和析构函数控制,所以忽略其他相关代码后,sp可以精简为如下形式(赋值操作符也省略掉了,构造函数省略相似的两个):
复制代码
template
classsp
{
public:
inlinesp():
m_ptr(0){}
sp(T*other);
sp(constsp
~sp();
private:
template
template
voidset_pointer(T*ptr);
T*m_ptr;
};
复制代码
默认构造函数使智能指针不指向任何对象,sp(T*other)与sp(constsp
复制代码
template
sp
:
sp(T*other)
:
m_ptr(other)
{
if(other)other->incStrong(this);
}
template
sp
:
sp(constsp
:
m_ptr(other.m_ptr)
{
if(m_ptr)m_ptr->incStrong(this);
}
复制代码
内部变量m_ptr指向实际对象,并调用实际对象的incStrong函数,T继承自LightRefBase,所以此处调用的是LightRefBase的incStrong函数,之后实际对象的引用计数加1。
当智能指针销毁的时候调用智能指针的析构函数:
template
sp
:
~sp()
{
if(m_ptr)m_ptr->decStrong(this);
}
调用实际对象即LightRefBase的decStrong函数,其实现如下:
inlinevoiddecStrong(constvoid*id)const{
if(android_atomic_dec(&mCount)==1){
deletestatic_cast
}
}
android_atomic_dec返回mCount减1之前的值,如果返回1表示这次减过之后引用计数就是0了,就把对象delete掉。
三、RefBase
RefBase提供了更强大的引用计数的管理。
复制代码
classRefBase
{
public:
voidincStrong(constvoid*id)const;
voiddecStrong(constvoid*id)const;
voidforceIncStrong(constvoid*id)const;
//!
DEBUGGINGONLY:
Getcurrentstrongrefcount.
int32_tgetStrongCount()const;
classweakref_type
{
public:
RefBaserefBase()const;
voidincWeak(constvoid*id);
voiddecWeak(constvoid*id);
//acquiresastrongreferenceifthereisalreadyone.
boolattemptIncStrong(constvoid*id);
//acquiresaweakreferenceifthereisalreadyone.
//Thisisnotalwayssafe.seeProcessState.cppandBpBinder.cpp
//forproperuse.
boolattemptIncWeak(constvoid*id);
//!
DEBUGGINGONLY:
Getcurrentweakrefcount.
int32_tgetWeakCount()const;
//!
DEBUGGINGONLY:
Printreferencesheldonobject.
voidprintRefs()const;
//!
DEBUGGINGONLY:
Enabletrackingforthisobject.
//enable--enable/disabletracking
//retain--whentrackingisenable,iftrue,thenwesaveastacktrace
//foreachreferenceanddereference;whenretain==false,we
//matchupreferencesanddereferencesandkeeponlythe
//outstandingones.
voidtrackMe(boolenable,boolretain);
};
weakref_type*createWeak(constvoid*id)const;
weakref_type*getWeakRefs()const;
//DEBUGGINGONLY:
Printreferencesheldonobject.
inlinevoidprintRefs()const{getWeakRefs()->printRefs();}
//DEBUGGINGONLY:
Enabletrackingofobject.
inlinevoidtrackMe(boolenable,boolretain)
{
getWeakRefs()->trackMe(enable,retain);
}
typedefRefBasebasetype;
protected:
RefBase();
virtual~RefBase();
//!
FlagsforextendObjectLifetime()
enum{
OBJECT_LIFETIME_STRONG=0x0000,
OBJECT_LIFETIME_WEAK=0x0001,
OBJECT_LIFETIME_MASK=0x0003
};
voidextendObjectLifetime(int32_tmode);
//!
FlagsforonIncStrongAttempted()
enum{
FIRST_INC_STRONG=0x0001
};
virtualvoidonFirstRef();
virtualvoidonLastStrongRef(constvoid*id);
virtualboolonIncStrongAttempted(uint32_tflags,constvoid*id);
virtualvoidonLastWeakRef(constvoid*id);
private:
friendclassweakref_type;
classweakref_impl;
RefBase(constRefBase&o);
RefBase&operator=(constRefBase&o);
weakref_impl*constmRefs;
};
复制代码
不同于LightRefBase的是,RefBase内部并没有使用一个变量来维护引用计数,而是通过一个weakref_impl*类型的成员来维护引用计数,并且同时提供了强引用计数和弱引用计数。
weakref_impl继承于RefBase:
:
weakref_type,代码比较多,不过大都是调试代码,由宏定义分开,Release是不包含调试代码的,去除这些代码后其定义为:
复制代码
#defineINITIAL_STRONG_VALUE(1<<28)
classRefBase:
:
weakref_impl:
publicRefBase:
:
weakref_type
{
public:
volatileint32_tmStrong;
volatileint32_tmWeak;
RefBase*constmBase;
volatileint32_tmFlags;
weakref_impl(RefBase*base)
:
mStrong(INITIAL_STRONG_VALUE)
mWeak(0)
mBase(base)
mFlags(0)
{
}
voidaddStrongRef(constvoid*/*id*/){}
voidremoveStrongRef(constvoid*/*id*/){}
voidaddWeakRef(constvoid*/*id*/){}
voidremoveWeakRef(constvoid*/*id*/){}
voidprintRefs()const{}
voidtrackMe(bool,bool){}
};
复制代码
weakref_impl中的函数都是作为调试用,Release版的实现都是空的,成员变量分别表示强引用数、弱引用数、指向实际对象的指针与flag,flag可控制实际对象的生命周期,取值为0或RefBase中定义的枚举值。
RefBase提供了incStrong与decStrong函数用于控制强引用计数值,其弱引用计数值是由weakref_impl控制,强引用计数与弱引用数都保存在weakref_impl*类型的成员变量mRefs中。
RefBase同LightRefBase一样为对象提供了引用计数的方法,对引用计数的管理同样要由智能指针控制,由于RefBase同时实现了强引用计数与弱引用计数,所以就有两种类型的智能指针,sp(StrongPointer)与wp(WeakPointer)。
sp前面已经说过,其(拷贝)构造函数调用对象即RefBase的incStrong函数。
复制代码
voidRefBase:
:
incStrong(constvoid*id)const
{
weakref_impl*constrefs=mRefs;
refs->incWeak(id);
refs->addStrongRef(id);
constint32_tc=android_atomic_inc(&refs->mStrong);
LOG_ASSERT(c>0,"incStrong()calledon%pafterlaststrongref",refs);
if(c!
=INITIAL_STRONG_VALUE){
return;
}
android_atomic_add(-INITIAL_STRONG_VALUE,&refs->mStrong);
refs->mBase->onFirstRef();
}
复制代码
addStrong的函数体为空,incStrong函数内部首先调用成员变量mRefs的incWeak函数将弱引用数加1,然后再将强引用数加1,由于android_atomic_inc返回变量的旧值,所以如果其不等于INITIAL_STRONG_VALUE就直接返回,则则是第一次由强智能指针(sp)引用,将其减去INITIAL_STRONG_VALUE后变成1,然后调用对象的onFirstRef。
成员变量mRefs是在对象的构造函数中初始化的:
RefBase:
:
RefBase()
:
mRefs(newweakref_impl(this))
{
}
weakrel_impl的incWeak继承自父类weakrel_type的incWeak:
复制代码
voidRefBase:
:
weakref_type:
:
incWeak(constvoid*id)
{
weakref_impl*constimpl=static_cast
impl->addWeakRef(id);
constint32_tc=android_atomic_inc(&impl->mWeak);
LOG_ASSERT(c>=0,"incWeakcalledon%pafterlastweakref",this);
}
复制代码
addWeakRef实现同样为空,所以只是将弱引用计数加1。
所以当对象被sp引用后,强引用计数与弱引用计数会同时加1。
当sp销毁时其析构函数调用对象即RefBase的decStrong函数:
复制代码
voidRefBase:
:
decStrong(constvoid*id)const
{
weakref_impl*constrefs=mRefs;
refs->removeStrongRef(id);
constint32_tc=android_atomic_dec(&refs->mStrong);
if(c==1){
const_cast
if((refs->mFlags&OBJECT_LIFETIME_WEAK)!
=OBJECT_LIFETIME_WEAK){
deletethis;
}
}
refs->removeWeakRef(id);
refs->decWeak(id);
}
复制代码
decStrong中将强引用数与弱引用数同时减1,如果这是最后一个强引用的话,会调用对象的onLastStrongRef,并且判断成员变量mRefs的成员变量mFlags来决定是否在对象的强引用数为0时释放对象。
mFlags可以为0或以下两个枚举值:
enum{
OBJECT_LIFETIME_WEAK=0x0001,
OBJECT_LIFETIME_FOREVER=0x0003
};
mFlags的值可以通过extendObjectLifetime函数改变:
voidRefBase:
:
extendObjectLifetime(int32_tmode)
{
android_atomic_or(mode,&mRefs->mFlags);
}
OBJECT_LIFETIME_FOREVER包含OBJECT_LIFETIME_WEAK(位运算中其二进制11包含01),所以当
refs->mFlags&OBJECT_LIFETIME_WEAK)!
=OBJECT_LIFETIME_WEAK
为true时表示mFlags为0,实际对象的生命周期受强引用数控制,所以在强引用数为0时deletethis,否则实际对象的生命周期就由弱引用数控制。
再来看decWeak:
复制代码
voidRefBase:
:
weakref_type:
:
decWeak(constvoid*id)
{
weakref_impl*constimpl=static_cast
impl->removeWeakRef(id);
constint32_tc=android_atomic_dec(&impl->mWeak);
if(c!
=1)return;
if((impl->mFlags&OBJECT_LIFETIME_WEAK)!
=OBJECT_LIFETIME_WEAK){
if(impl->mStrong==INITIAL_STRONG_VALUE)
deleteimpl->mBase;
else{
deleteimpl;
}
}else{
impl->mBase->onLastWeakRef(id);
if((impl->mFlags&OBJECT_LIFETIME_FOREVER)!
=OBJECT_LIFETIME_FOREVER){
deleteimpl->mBase;
}
}
}
复制代码
将弱引用数减1,若减1后不为0直接返回,否则判断
(impl->mFlags&OBJECT_LIFETIME_WEAK)!
=OBJECT_LIFETIME_WEAK
若判断结果为true:
实际对象生命周期被强引用数控制,接下来判断:
mpl->mStrong==INITIAL_STRONG_VALUE
如果判断为true表示对象只被弱引用引用过,现在弱引用数为0,直接删除实际对象。
如果判断为false,表示对象曾经被强引用引用过,但现在强引用为变为0了(因为增加或减小强引用数时一定同时增加或减小弱引用数,所以弱引用数为0时,强引用数一定为0),弱引用数为0了,直接释放mRefs,而实际对象由于受强引用数控制,已经在RefBase:
:
decStrong中被delete了。
若判断结果为false:
判断mFlgs是否是OBJECT_LIFETIME_FOREVE
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 指针 管理 RefBaseSPWP