android 指针是什么意思,Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析(3)...
提供引用計(jì)數(shù)器的類RefBase我們就暫時(shí)介紹到這里,后面我們再結(jié)合智能指針類一起分析,現(xiàn)在先來看看強(qiáng)指針類和弱指針類的定義。強(qiáng)指針類的定義我們在前面介紹輕量級指針的時(shí)候已經(jīng)見到了,就是sp類了,這里就不再把它的代碼列出來了。我們來看看它的構(gòu)造函數(shù)的實(shí)現(xiàn):
template
sp::sp(T*?other)
:?m_ptr(other)
{
if?(other)?other->incStrong(this);
}
這里傳進(jìn)來的參數(shù)other一定是繼承于RefBase類的,因此,在函數(shù)的內(nèi)部,它調(diào)用的是RefBase類的incStrong函數(shù),它定義在frameworks/base/libs/utils/RefBase.cpp文件中:
void?RefBase::incStrong(const?void*?id)?const
{
weakref_impl*?const?refs?=?mRefs;
refs->addWeakRef(id);
refs->incWeak(id);
refs->addStrongRef(id);
const?int32_t?c?=?android_atomic_inc(&refs->mStrong);
LOG_ASSERT(c?>?0,?"incStrong()?called?on?%p?after?last?strong?ref",?refs);
#if?PRINT_REFS
LOGD("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);
const_cast(this)->onFirstRef();
}
成員變量mRefs是在RefBase類的構(gòu)造函數(shù)中創(chuàng)建的:
RefBase::RefBase()
:?mRefs(new?weakref_impl(this))
{
//????LOGV("Creating?refs?%p?with?RefBase?%p\n",?mRefs,?this);
}
在這個(gè)incStrong函數(shù)中,主要做了三件事情:
一是增加弱引用計(jì)數(shù):
refs->addWeakRef(id);
refs->incWeak(id);
二是增加強(qiáng)引用計(jì)數(shù):
refs->addStrongRef(id);
const?int32_t?c?=?android_atomic_inc(&refs->mStrong);
三是如果發(fā)現(xiàn)是首次調(diào)用這個(gè)對象的incStrong函數(shù),就會調(diào)用一個(gè)這個(gè)對象的onFirstRef函數(shù),讓對象有機(jī)會在對象被首次引用時(shí)做一些處理邏輯:
if?(c?!=?INITIAL_STRONG_VALUE)??{
return;
}
android_atomic_add(-INITIAL_STRONG_VALUE,?&refs->mStrong);
const_cast(this)->onFirstRef();
這里的c返回的是refs->mStrong加1前的值,如果發(fā)現(xiàn)等于INITIAL_STRONG_VALUE,就說明這個(gè)對象的強(qiáng)引用計(jì)數(shù)是第一次被增加,因此,refs->mStrong就是初始化為INITIAL_STRONG_VALUE的,它的值為:#define?INITIAL_STRONG_VALUE?(1<<28)這個(gè)值加1后等于1<<28 + 1,不等于1,因此,后面要再減去-INITIAL_STRONG_VALUE,于是,refs->mStrong就等于1了,就表示當(dāng)前對象的強(qiáng)引用計(jì)數(shù)值為1了,這與這個(gè)對象是第一次被增加強(qiáng)引用計(jì)數(shù)值的邏輯是一致的。
回過頭來看弱引用計(jì)數(shù)是如何增加的,首先是調(diào)用weakref_impl類的addWeakRef函數(shù),我們知道,在Release版本中,這個(gè)函數(shù)也不做,而在Debug版本中,這個(gè)函數(shù)增加了一個(gè)ref_entry對象到了weakref_impl對象的mWeakRefs列表中,表示此weakref_impl對象的弱引用計(jì)數(shù)被增加了一次。接著又調(diào)用了weakref_impl類的incWeak函數(shù),真正增加弱引用計(jì)數(shù)值就是在這個(gè)函數(shù)實(shí)現(xiàn)的了,weakref_impl類的incWeak函數(shù)繼承于其父類weakref_type的incWeak函數(shù):
void?RefBase::weakref_type::incWeak(const?void*?id)
{
weakref_impl*?const?impl?=?static_cast(this);
impl->addWeakRef(id);
const?int32_t?c?=?android_atomic_inc(&impl->mWeak);
LOG_ASSERT(c?>=?0,?"incWeak?called?on?%p?after?last?weak?ref",?this);
}
增加弱引用計(jì)數(shù)是下面語句執(zhí)行的:constint32_t?c?=?android_atomic_inc(&impl->mWeak);但是前面為什么又調(diào)用了一次addWeakRef函數(shù)呢?前面不是已經(jīng)調(diào)用過了嗎?在Release版本中,因?yàn)閣eakref_impl類的addWeakRef函數(shù)是空實(shí)現(xiàn),這里再調(diào)用一次沒有什么害處,但是如果在Debug版本,豈不是冗余了嗎?搞不清,有人問過負(fù)責(zé)開發(fā)Android系統(tǒng)Binder通信機(jī)制模塊的作者Dianne Hackborn這個(gè)問題,他是這樣回答的:
Ah I see. ?Well the debug code may be broken, though I wouldn't leap to that
conclusion without actually testing it; I know it has been used in the
past. ?Anyway, these things get compiled out in non-debug builds, so there
is no reason to change them unless you are actually trying to use this debug
code and it isn't working and need to do this to fix it.
既然他也不知道怎么回事,我們也不必深究了,知道有這么回事就行。
這里總結(jié)一下強(qiáng)指針類sp在其構(gòu)造函數(shù)里面所做的事情就是分別為目標(biāo)對象的強(qiáng)引用計(jì)數(shù)和弱引和計(jì)數(shù)增加了1。
再來看看強(qiáng)指針類的析構(gòu)函數(shù)的實(shí)現(xiàn):
template
sp::~sp()
{
if?(m_ptr)?m_ptr->decStrong(this);
}
同樣,這里的m_ptr指向的目標(biāo)對象一定是繼承了RefBase類的,因此,這里調(diào)用的是RefBase類的decStrong函數(shù),這也是定義在frameworks/base/libs/utils/RefBase.cpp文件中:
void?RefBase::decStrong(const?void*?id)?const
{
weakref_impl*?const?refs?=?mRefs;
refs->removeStrongRef(id);
const?int32_t?c?=?android_atomic_dec(&refs->mStrong);
#if?PRINT_REFS
LOGD("decStrong?of?%p?from?%p:?cnt=%d\n",?this,?id,?c);
#endif
LOG_ASSERT(c?>=?1,?"decStrong()?called?on?%p?too?many?times",?refs);
if?(c?==?1)?{
const_cast(this)->onLastStrongRef(id);
if?((refs->mFlags&OBJECT_LIFETIME_WEAK)?!=?OBJECT_LIFETIME_WEAK)?{
deletethis;
}
}
refs->removeWeakRef(id);
refs->decWeak(id);
}
這里的refs->removeStrongRef函數(shù)調(diào)用語句是對應(yīng)前面在RefBase::incStrong函數(shù)里的refs->addStrongRef函數(shù)調(diào)用語句的,在Release版本中,這也是一個(gè)空實(shí)現(xiàn)函數(shù),真正實(shí)現(xiàn)強(qiáng)引用計(jì)數(shù)減1的操作是下面語句:
const?int32_t?c?=?android_atomic_dec(&refs->mStrong);
如果發(fā)現(xiàn)減1前,此對象的強(qiáng)引用計(jì)數(shù)為1,就說明從此以后,就再沒有地方引用這個(gè)目標(biāo)對象了,這時(shí)候,就要看看是否要delete這個(gè)目標(biāo)對象了:
if?(c?==?1)?{
const_cast(this)->onLastStrongRef(id);
if?((refs->mFlags&OBJECT_LIFETIME_WEAK)?!=?OBJECT_LIFETIME_WEAK)?{
deletethis;
}
}
在強(qiáng)引用計(jì)數(shù)為0的情況下,如果對象的標(biāo)志位OBJECT_LIFETIME_WEAK被設(shè)置了,就說明這個(gè)對象的生命周期是受弱引用計(jì)數(shù)所控制的,因此,這時(shí)候就不能delete對象,要等到弱引用計(jì)數(shù)也為0的情況下,才能delete這個(gè)對象。
接下來的ref->removeWeakRef函數(shù)調(diào)用語句是對應(yīng)前面在RefBase::incStrong函數(shù)里的refs->addWeakRef函數(shù)調(diào)用語句的,在Release版本中,這也是一個(gè)空實(shí)現(xiàn)函數(shù),真正實(shí)現(xiàn)強(qiáng)引用計(jì)數(shù)減1的操作下面的refs->decWeak函數(shù),weakref_impl類沒有實(shí)現(xiàn)自己的decWeak函數(shù),它繼承了weakref_type類的decWeak函數(shù):
void?RefBase::weakref_type::decWeak(const?void*?id)
{
weakref_impl*?const?impl?=?static_cast(this);
impl->removeWeakRef(id);
const?int32_t?c?=?android_atomic_dec(&impl->mWeak);
LOG_ASSERT(c?>=?1,?"decWeak?called?on?%p?too?many?times",?this);
if?(c?!=?1)?return;
if?((impl->mFlags&OBJECT_LIFETIME_WEAK)?!=?OBJECT_LIFETIME_WEAK)?{
if?(impl->mStrong?==?INITIAL_STRONG_VALUE)
deleteimpl->mBase;
else{
//????????????LOGV("Freeing?refs?%p?of?old?RefBase?%p\n",?this,?impl->mBase);
deleteimpl;
}
}?else{
impl->mBase->onLastWeakRef(id);
if?((impl->mFlags&OBJECT_LIFETIME_FOREVER)?!=?OBJECT_LIFETIME_FOREVER)?{
deleteimpl->mBase;
}
}
}
這里又一次調(diào)用了weakref_impl對象的removeWeakRef函數(shù),這也是和RefBase::weakref_type::incWeak函數(shù)里面的impl->addWeakRef語句所對應(yīng)的,實(shí)現(xiàn)弱引用計(jì)數(shù)減1的操作是下面語句:constint32_t?c?=?android_atomic_dec(&impl->mWeak);
減1前如果發(fā)現(xiàn)不等于1,那么就什么也不用做就返回了,如果發(fā)現(xiàn)等于1,就說明當(dāng)前對象的弱引用計(jì)數(shù)值為0了,這時(shí)候,就要看看是否要delete這個(gè)對象了:
if?((impl->mFlags&OBJECT_LIFETIME_WEAK)?!=?OBJECT_LIFETIME_WEAK)?{
if?(impl->mStrong?==?INITIAL_STRONG_VALUE)
deleteimpl->mBase;
else{
//??????LOGV("Freeing?refs?%p?of?old?RefBase?%p\n",?this,?impl->mBase);
deleteimpl;
}
}?else{
impl->mBase->onLastWeakRef(id);
if?((impl->mFlags&OBJECT_LIFETIME_FOREVER)?!=?OBJECT_LIFETIME_FOREVER)?{
deleteimpl->mBase;
}
}
如果目標(biāo)對象的生命周期是不受弱引用計(jì)數(shù)控制的,就執(zhí)行下面語句:
if?(impl->mStrong?==?INITIAL_STRONG_VALUE)
deleteimpl->mBase;
else{
//??LOGV("Freeing?refs?%p?of?old?RefBase?%p\n",?this,?impl->mBase);
deleteimpl;
}
這個(gè)代碼段是什么意思呢?這里是減少對象的弱引用計(jì)數(shù)的地方,如果調(diào)用到這里,那么就說明前面一定有增加過此對象的弱引用計(jì)數(shù),而增加對象的弱引用計(jì)數(shù)有兩種場景的,一種場景是增加對象的強(qiáng)引用計(jì)數(shù)的時(shí)候,會同時(shí)增加對象的弱引用計(jì)數(shù),另一種場景是當(dāng)我們使用一個(gè)弱指針來指向?qū)ο髸r(shí),在弱指針對象的構(gòu)造函數(shù)里面,也會增加對象的弱引用計(jì)數(shù),不過這時(shí)候,就只是增加對象的弱引用計(jì)數(shù)了,并沒有同時(shí)增加對象的強(qiáng)引用計(jì)數(shù)。因此,這里在減少對象的弱引用計(jì)數(shù)時(shí),就要分兩種情況來考慮。
如果是前一種場景,這里的impl->mStrong就必然等于0,而不會等于INITIAL_STRONG_VALUE值,因此,這里就不需要delete目標(biāo)對象了(impl->mBase),因?yàn)榍懊娴腞efBase::decStrong函數(shù)會負(fù)責(zé)delete這個(gè)對象。這里唯一需要做的就是把weakref_impl對象delete掉,但是,為什么要在這里delete這個(gè)weakref_impl對象呢?這里的weakref_impl對象是在RefBase的構(gòu)造函數(shù)里面new出來的,理論上說應(yīng)該在在RefBase的析構(gòu)函數(shù)里delete掉這個(gè)weakref_impl對象的。在RefBase的析構(gòu)函數(shù)里面,的確是會做這件事情:
RefBase::~RefBase()
{
//????LOGV("Destroying?RefBase?%p?(refs?%p)\n",?this,?mRefs);
if?(mRefs->mWeak?==?0)?{
//????????LOGV("Freeing?refs?%p?of?old?RefBase?%p\n",?mRefs,?this);
deletemRefs;
}
}
但是不要忘記,在這個(gè)場景下,目標(biāo)對象是前面的RefBase::decStrong函數(shù)delete掉的,這時(shí)候目標(biāo)對象就會被析構(gòu),但是它的弱引用計(jì)數(shù)值尚未執(zhí)行減1操作,因此,這里的mRefs->mWeak == 0條件就不成立,于是就不會delete這個(gè)weakref_impl對象,因此,就延遲到執(zhí)行這里decWeak函數(shù)時(shí)再執(zhí)行。
如果是后一種情景,這里的impl->mStrong值就等于INITIAL_STRONG_VALUE了,這時(shí)候由于沒有地方會負(fù)責(zé)delete目標(biāo)對象,因此,就需要把目標(biāo)對象(imp->mBase)delete掉了,否則就會造成內(nèi)存泄漏。在delete這個(gè)目標(biāo)對象的時(shí)候,就會執(zhí)行RefBase類的析構(gòu)函數(shù),這時(shí)候目標(biāo)對象的弱引用計(jì)數(shù)等于0,于是,就會把weakref_impl對象也一起delete掉了。
總結(jié)
以上是生活随笔為你收集整理的android 指针是什么意思,Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析(3)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (linux .svn)
- 下一篇: android 硬件对接,Android