RefBase是Android中所有对象的始祖,类似于MFC中的CObject,Java中的Object对象。在Android中,RefBase结合sp(strong pointer)和wp(weak pointer),实现来一套通过引用计数的方法来控制对象生命周期的机制。sp和wp存在的目的就是实现对new出来的内存自动回收。
1. RefBase和影子对象
RefBase::RefBase() : mRefs (new weakref_impl(this)) { // mRefs是RefBase的成员变量,类型为weakref_impl,称为影子对象。
}
weakref_impl是RefBase的内部类,继承于weakref_type。 RefBase::weakref_impl : RefBase::weakref_type 。
weakref_impl::weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE), // 强引用计数,初始值为0x1000000.
mWeak(0), // 若引用次数,初始值为0。
mBase(base), // 该影子对象指向的实际对象。
mFlags(0),
mStrongRefs(NULL) {
}
使用:
class A :public RefBase {
};
A* pA = new A();
此时, new了一个A对象后,实际上还new了一个weakref_impl对象,称这个weakref_impl对象为影子对象,A为实际对象。
2. sp
构造:
接着上面,定义一个sp:
sp<A> spA(pA);
(1) sp是一个模板类,定义如下:
template<typename T>
sp<T>::sp(T* other) : m_ptr(other) { // other即之前创建的pA.
if (other) {
other->incStrong(this);
}
}
(2) incStrong()函数的实现:
void RefBase::incStrong(const void* id) const {
weakref_impl* const refs = mRefs;
// 操作影子对象, 增加强/弱 引用计数。
refs->incWeak(id);
const int32_t c = android_atomic_inc(&refs->mStrong); //为原子执行+1操作,并返回旧值。影子对象强引用计数加1.
if (c != INITIAL_STRONG_VALUE) {
return; // 若c不是初始,则表明这个对象已经被强引用过一次了。
}
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); // 原子加操作。即执行了 refs->mStrong + (-0x1000000), 结果mStrong = 1.
// 如果是第一次引用, 则调用onFirstRef, 派生类可以重载这个函数完成一些初始化工作。
const_cast<RefBase*>(this)->onFirstRef();
}
(3) incWeak()函数的实现:
void RefBase::weakref_type::incWeak(const void* id) {
weakref_impl* const impl = static_cast<weakref_impl*>(this);
const int32_t c = android_atomic_inc(&impl->mWeak); // 影子对象弱引用计数加1.
}
sp的构造,使RefBase中影子对象的强引用计数变为1, 弱引用计数也变为1.
析构:
(1) 析构函数:
template<typename T>
sp<T>::~sp() {
if (m_ptr) {
m_ptr->decStrong(this); // 调用实际对象的decStrong, 有RefBase实现。
}
}
(2) decStrong函数的实现:
void RefBase::decStrong(const void* id) const {
weakref_impl* const refs = mRefs; // 临时保存影子对象。
const int32_t c = android_atomic_dec(&refs->mStrong);
if (c == 1) {
const_cast<RefBase*>(this)->onLastStrongRef(id); // 调用onLastStrongRef, 表明强引用计数减为0, 对象可能被delete。
if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
delete this; // 干掉实际对象,影子对象mRef并没有被干掉,被保存到refs了。
}
refs->decWeak(id); // 调用影子对象的decWeak.
}
}
注意:delete this 会导致A的析构函数被调用,从而RefBase的析构函数也被调用。
RefBase::~RefBase() {
if (mRef->mWeak == 0) { // 若弱引用计数不为0, 影子对象不会被析构。
delete mRefs;
}
}
3. wp
构造:
使用已有sp, 定义一个wp:
wp<A> wpA(spA);
(1) wp有多个构造函数,看一下参数为sp的这个:
template<typename T>
wp<T>::wp(const sp<T>& other) : m_ptr(other.m_ptr) { // wp的m_ptr指向实际对象
if (m_ptr) {
m_refs = m_ptr->createWeak(this); // 调用pA的creakWeak, 并保存返回值到成员变量m_refs中。
}
}
(2) creakWeak的实现:
RefBase::weakref_type* RefBase::createWeak(const void* id) const {
mRefs->incWeak(id); // 调用影子对象的incWeak,弱影用计数加1.
retrun mRefs; //返回影子对象本身。
}
wp构造后,影子对象的弱应用计数增加1.
注意: wp中有两个成员变量:m_ptr保存实际对象,m_refs保存影子对象。
sp只有一个成员变量:m_ptr保存实际对象,但该实际对象已包含对应的影子对象。
析构:
(1) 析构函数:
template<T>
wp<T>::~wp() {
if (m_ptr) {
m_refs->decWeak(this); // 调用影子对象的decWeak.
}
}
(2) decWeak()函数实现:
void RefBase::weakref_type::decWeak(const void* id) {
weakref_impl* const impl = static_cast<weakref_impl*>(this);
const inst32_t c android_atomic_dec(&impl->mWeak); // 原子减1,返回旧值。
if (c != 1) { // 旧值 >=2 , 直接返回。
return;
}
// 若c = 1, 则弱引用计数为0, 说明没有弱引用指向实际对象了,考虑是否释放内存。
if ((impl->mFlag&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
if (impl->mStrong == INITIAL_STRONG_VALUE) {
delete impl->mBase; // 强引用计数也为0, 释放实际对象。
} else {
delete impl; // 否则,impl就是this, 释放影子对象。
}
} else {
impl->mBase->onLastWeakRef(id);
if ((impl->mFlogs&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
delete impl->mBase;
}
}
}