设为首页 加入收藏

TOP

Android智能指针sp wp详解(二)
2014-11-24 08:22:46 来源: 作者: 【 】 浏览:10
Tags:Android 智能 指针 详解

ref->next = *refs;
*refs = ref;
/*
新出现的ref_entry结构体加入到链表头上,如果有n个sp指针指向同一个目标对象
那么这里就有n个ref_entry结构体加入到这个单链表中,该结构体记录着如下数据
1. id域记录着对应的sp强指针类对象的this值
2. ref域记录的是当前sp强指针类对象是第几个引用目标对象的指针
3. next域指向下一个指向目标对象的sp强指针对应的ref_entry结构体

类RefBase的嵌套类weakref_type的子类的私有数据mRefs的私有二级指针成员mWeakRefs指向的是
最后一个sp强指针对应的ref_entry结构体指针。


总结一下:
一个目标对象,可能被n个sp强指针指向,那么就存在n个class sp对象,同时每一个sp
对象在目标对象的虚基类对象的成员类mRefs的私有二级指针成员mWeakRefs登记了一个
ref_entry结构体,这些ref_entry结构体的地址都是由该链表管理,每一个
ref_entry结构体和哪一个sp对象对应,也由该链表管理。同时链接数就是该链表节点的
个数
*/
}
}
/************************注释1********************************/


/************************注释2********************************/
void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast(this);
// 强制类型转换,将基类指针转换成子类指针
impl->addWeakRef(id);
// 调用类weakref_impl成员函数addWeakRef(),产生一个ref_entry结构体挂载mWeakRefs链表上
const int32_t c = android_atomic_inc(&impl->mWeak);
/* impl->mWeak加1,表示已存在一个weak引用。但返回值c为操作前的结果 */
LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
/************************注释2********************************/


3》上面是定义一个sp指针,下面看看定义一个wp指针式如何实现的。
wp BB_wp_ptr(BB_ptr);
下面是wp类对应上面定义类型的构造函数
template
wp::wp(const sp& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) {
m_refs = m_ptr->createWeak(this);
}
}
this指针是指向wp对象的。createWeak()函数是RefBase类的成员函数。
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
mRefs指向的是第二步骤中产生的weakref_impl对象,调用基类weakref_type的成员函数incWeak()
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);
/* impl->mWeak有加1,但返回值为操作前的结果 */
LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}



三、sp、wp释放过程
sp BB_SP_ptr(BB_ptr);
实际上BB_SP_ptr和前面的BB_ptr一样,指向的是同一个BBinder对象。另外需要注意的时,调用sp构造函数:
template
sp::sp(const sp& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) m_ptr->incStrong(this);
}
同样是需要调用BBinder对象的incStrong()函数,使用weakref_impl对象来管理新添加进来的强引用,同时增加一个
ref_entry结构体到weakref_impl对象的mStrongRefs,增加2个ref_entry结构体到weakref_impl对象的mWeakRefs。
如上图所示。

现在来看看释放sp、wp指针的情况。
delete BB_SP_ptr;
将会调用如下形式的sp析构函数:
template
sp::~sp()
{
if (m_ptr) m_ptr->decStrong(this);
}
m_ptr指向的是前面生成的BBinder对象,调用其基类函数decStrong(this),this值是指向BB_SP_ptr对象。

void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id); // 注释3,移除mStrongRefs链表中和该sp对应的ref_entry结构体
const int32_t c = android_atomic_dec(&refs->mStrong);
/* 强引用计数减1, 但返回的是操作之前的引用计数值 */
LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
if (c == 1) {
/* c == 1说明刚刚removeStrongRef之前,整个系统中只存在一个sp对象引用目标对象,现在的情况就是
系统中没有任何强指针对象来引用目标对象了,此时目标对象就会被删除释放
*/
const_cast(this)->onLastStrongRef(id);
if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
delete this; // mFlags =0 ,条件成立,删除目标对象,这里就会删除前面new出来的

首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android编译系统 - findleaves.sh 下一篇Redboot mini2440 qemu 增加LCD功..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C/C++模板类模板与函 (2025-12-27 01:49:46)
·如何理解c语言指针和 (2025-12-27 01:19:11)
·为什么C标准库没有链 (2025-12-27 01:19:08)
·玩转C语言和数据结构 (2025-12-27 01:19:05)
·MySQL 基础入门视频 (2025-12-26 23:20:22)