设为首页 加入收藏

TOP

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

一、calss BBinder类说明
class RefBase
class IBinder
class BpBinder class BBinder
class BBinder : public IBinder
{
...
protected:
virtual ~BBinder();
...
}
class IBinder : public virtual RefBase
{
...
protected:
inline virtual ~IBinder() { }
...
}
由上,可以看出BBinder和IBinder都是以public的方式继承于虚基类RefBase的。


二、sp wp对象的建立过程
解析:sp BB_ptr(new BBinder);
这是一条定义sp指针BB_ptr的语句,他只想的对象是一个BBinder对象。
如图所示。



1》首先看一下new BBinder时都做了什么,特别是和该机制相关的初始化。
c++中创建一个对象时,需要调用去构造函数,对于继承类,则是先调用其父类的构造函数,然后才会调用本身的
构造函数。这里new一个BBinder对象时,顺序调用了:
RefBase::RefBase() : mRefs(new weakref_impl(this)) {}
inline IBinder() {}
BBinder::BBinder() : mExtras(NULL){}
主要关注的是RefBase的构造函数,
可以看出他是通过new weakref_impl(this)的结果来初始化私有成员mRefs
这里的this指向BBinder对象自身,class weakref_impl继承于类RefBase的内嵌类weakref_type,然后该类
weakref_impl又被类RefBase引用。类weakref_impl的构造函数如下:
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE) // 1 << 28
, mWeak(0)
, mBase(base) // new BBinder指针
, mFlags(0)
, mStrongRefs(NULL) // sp引用链表指针
, mWeakRefs(NULL) // wp引用链表指针
, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT) // 1
, mRetain(false) {}

2》new BBinder返回的是BBinder对象的指针,如:sp BB_ptr(0x );
sp实际上是一个类模板,这条语句最终是要建立一个sp的实例化对象,叫模板类BB_ptr
这里生成BB_ptr对象所调用的构造函数是:
template
sp::sp(T* other)
: m_ptr(other)
{
if (other) other->incStrong(this);
}
BB_ptr对象的私有指针指向刚刚前面生成的BBinder对象。
接着调用函数incStrong(),该函数是RefBase类的成员函数,在子类中没有被重载,所以这里
other->incStrong(this)的调用实际上是调用基类成员函数incStrong(this),这个this值是指向sp对象
BB_ptr的指针。现在转去查看该成员函数的实现。

void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
/* 取得BBinder对象基类中的私有只读指针mRefs */
refs->addWeakRef(id);
/* 调用weakref_impl类定义时实现的成员函数addWeakRef, 见下注释1*/
refs->incWeak(id);
/* 调用weakref_impl类的基类weakref_type成员函数incWeak, 见下注释2*/

refs->addStrongRef(id);
// 调用weakref_impl类定义时实现的成员函数addStrongRef, 见下注释1
const int32_t c = android_atomic_inc(&refs->mStrong);
/* 该函数实际将refs->mStrong值加1,也就是增加强引用计数值。但是返回值为refs->mStrong-1 */
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;
}
/* c = INITIAL_STRONG_VALUE, 第一个强引用产生的时候才会出现这个情况 */
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
/* 返回值为INITIAL_STRONG_VALUE,refs->mStrong值变成1 */
const_cast(this)->onFirstRef();
}

/************************注释1********************************/
void addWeakRef(const void* id)
{
addRef(&mWeakRefs, id, mWeak);
}
void addStrongRef(const void* id)
{
addRef(&mStrongRefs, id, mStrong);
}
addRef()是类weakref_impl的私有成员函数,addWeakRef()函数引用的是public成员变量,而addRef()函数可以操作私有数据。


struct ref_entry
{
ref_entry* next;
const void* id;
int32_t ref;
};

void addRef(ref_entry** refs, const void* id, int32_t mRef)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
ref_entry* ref = new ref_entry;
ref->ref = mRef;
ref->id = id;

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

评论

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

·微服务 Spring Boot (2025-12-26 18:20:10)
·如何调整 Redis 内存 (2025-12-26 18:20:07)
·MySQL 数据类型:从 (2025-12-26 18:20:03)
·Linux Shell脚本教程 (2025-12-26 17:51:10)
·Qt教程,Qt5编程入门 (2025-12-26 17:51:07)