sp&wp 的三板斧

根据《深入理解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
    };

可以以此为点继续分析再不再续了,比较简单。



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值