根据《深入理解Android 卷I》改编而来、加入自已的理解而来。对于sp&wp的理解一直知道不够深入、真好有时间、彻底深究一下、典型的程序员风格。透过代码看本质。这里对于最核心的sp&wp的构造及析构讲解。
参考代码下载地址:
http://download.csdn.net/detail/andyhuabing/9254171 通过eclipse打开c工程、即可单步调试。
第一个板斧例子:
//类A从RefBase派生,RefBase是万物的始祖
class A: public RefBase {
//A没有任何自己的功能
};
static void example1() {
printf("test example1 \n");
A* pA = new A();
{
//注意我们的sp,wp对象是在{}中创建的,下面的代码先创建sp,然后创建wp
sp<A> spA(pA);
wp<A> wpA(spA);
//大括号结束前,先析构wp,再析构sp
}
printf("test example1 finish!\n");
}
1、构造对象
A* pA = new A(); 构造一个Refbase对象
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
}
此处再构造一个weakref_impl对象、称为 影子对象、后续也主要是利用影响对象进行计数据加减
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
{
}
这里初始化 mStrong=INITIAL_STRONG_VALUE (1<<28)、mWeak=0、且将实际对象即A存储在mBase中
小结一下:
构造RefBase对象、同时构造了weakref_impl影子对象、并将影子对象的强引用mStrong及mWeak赋初始值。
2、sp上场:
sp<A> spA(pA);
模块构造
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
if (other) other->incStrong(this);
}
m_ptr 保存了 pA 的指针、并调用pA的incStrong函数
void RefBase::incStrong(const void* id) const {
weakref_impl* const refs = mRefs;
refs->incWeak(id);
refs->addStrongRef(id);
const int32_t c = android_atomic_inc(&refs->mStrong);
ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
printf("incStrong c=0x%x \n", c);
if (c != INITIAL_STRONG_VALUE) {
return;
}
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
printf("decStrong mStrong=0x%x \n", refs->mStrong);
refs->mBase->onFirstRef();
}
void RefBase::weakref_type::incWeak(const void* id) {
weakref_impl* const impl = static_cast<weakref_impl*> (this);
impl->addWeakRef(id);
const int32_t c = android_atomic_inc(&impl->mWeak);
ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
printf("incWeak c=0x%x, mWeak=0x%x \n", c, impl->mWeak);
}
在 RefBase::incStrong 中 先执行weakref_type::incWeak、再执行refs->mStrong的计数、通过打印如下:
incWeak c=0x0, mWeak=0x1
incStrong c=0x10000000
incStrong mStrong=0x1
call onFirstRef
弱引用计数加1、强引用计数加1 、第一次调用refs->mBase->onFirstRef(); 用于完成初始化工作。
3、wp 构造
wp<A> wpA(spA);
template<typename T>
wp<T>::wp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) {
m_refs = m_ptr->createWeak(this);
}
}
此时 m_ptr 指定实际对象 spA 、并调用 createWeak()函数
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
incWeak c=0x1, mWeak=0x2
即影子对象的弱引用计数为2、强引用计数为1
4、wp 对象析构
调用析构函数:
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
调用 decWeak
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);
ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
printf("decWeak c=0x%x, mWeak=0x%x \n", c, impl->mWeak);
if (c != 1)
return;
printf("decWeak mFlags =0x%x \n", impl->mFlags);
if ((impl->mFlags & OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
// This is the regular lifetime case. The object is destroyed
// when the last strong reference goes away. Since weakref_impl
// outlive the object, it is not destroyed in the dtor, and
// we'll have to do it here.
printf("decWeak mStrong=0x%x \n", impl->mStrong);
if (impl->mStrong == INITIAL_STRONG_VALUE) {
// Special case: we never had a strong reference, so we need to
// destroy the object now.
printf("decWeak object now11 \n");
delete impl->mBase;
} else {
printf("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
delete impl;
}
} else {
// less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
impl->mBase->onLastWeakRef(id);
if ((impl->mFlags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
// this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
// is gone, we can destroy the object.
printf("decWeak object now22 \n");
delete impl->mBase;
}
}
}
通过打印:
decWeak mWeak=0x2
decWeak c=0x2, mWeak=0x1
c值为2则直接返回、此时强弱引用计数都为1
5、sp 对象析构
template<typename T>
sp<T>::~sp()
{
if (m_ptr) m_ptr->decStrong(this);
}
调用 decStrong后结果:
decStrong mStrong=0x1
decStrong c=0x1
decStrong mFlags=0
decStrong delete self object
此时将调用 delete this 即调用:
RefBase::~RefBase() {
printf("call RefBase::~RefBase mRefs->mFlags=0x%x \n", mRefs->mFlags);
printf("call RefBase::~RefBase mStrong=0x%x \n", mRefs->mStrong);
printf("call RefBase::~RefBase mWeak=0x%x \n", mRefs->mWeak);
if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
// we never acquired a strong (and/or weak) reference on this object.
delete mRefs;
} else {
// life-time of this object is extended to WEAK or FOREVER, in
// which case weakref_impl doesn't out-live the object and we
// can free it now.
if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
// It's possible that the weak count is not 0 if the object
// re-acquired a weak reference in its destructor
if (mRefs->mWeak == 0) {
delete mRefs;
}
}
}
// for debugging purposes, clear this.
const_cast<weakref_impl*&> (mRefs) = NULL;
}
打印如下:
call RefBase::~RefBase mRefs->mFlags=0x0
call RefBase::~RefBase mStrong=0x0
call RefBase::~RefBase mWeak=0x1
由于 mWeak 为1 导致影响对象依然存在。继续执行 RefBase::weakref_type::decWeak 函数:
decWeak mWeak=0x1
decWeak c=0x1, mWeak=0x0
decWeak mFlags =0x0
decWeak mStrong=0x0
Freeing refs 0xada330 of old RefBase 0xada320
实际对象值:
example1 pA=0xcba320
example1 spA=0xcba320
example1 wpA=0xcba330
小结:
1、Refbase 有一个隐含的影子对象、该影子对象内部有强弱引用计数
2、sp化后、强弱引用计数各增加1、sp析构后、强弱引用计数各减1
3、wp化后、弱引用计数增加1、wp析构后、弱引用引数减1
当 flags参数为0时、有如下结论:
1、强引用计数为0时则将实际对象 delete 释放
2、弱引用计数为0时则将影子对象 delete 释放
对于flags参数:
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
可以以此为点继续分析再不再续了,比较简单。