参照罗升阳的《Android源代码情景分析第三版》,自己重新分析一遍Android P上的智能指针,加强对基础知识的理解。
一、总览
由于Android底层是采用C/C++语言编写,它没有像java类似的垃圾回收机制,所以就需要程序员去手动释放释放内存,但随着项目规模变大,手动释放内存这种方式耗时耗力,且极不靠谱,这时候就需要用到智能指针。
根据我个人理解,智能指针分为两种:轻量级指针和重量级指针。
注意:这里我将强指针和弱指针统称为重量级指针,只是为了便于大家理解,因为它们之间存在千丝万缕的联系,不便于独立讲解。
其大致区别如下表所示:
轻量级指针 | 重量级指针 | |
---|---|---|
模板类 | sp<T> | sp<T>和wp<T> |
模板参数T | 继承至LightRefBase | 继承至RefBase |
计数器 | LightRefBase->mCount | RefBase->mRefs(mWeak、mStrong两个引用计数) |
计数器何时释放 | 无需释放 | 弱引用计数(mRefs->mWeak)为0时 |
对象何时释放 | mCount==0 | 1、对象生命周期受强引用影响,且mRefs->mStrong==0 2、对象生命周期受强、弱引用同时影响时,且mRefs->mWeak==0 |
这里需要注意:
1、智能指针并不是指针,而是一个模板类。
2、强指针增加(减少)强引用计数(mStrong)时,也会相应增加(减少)弱引用计数(mWeak)。
3、弱指针只会增加(减少)弱引用计数(mWeak)。
由2、3点可以看出,mRefs->mWeak总是大于等于mRefs->mStrong。
3、强/弱指针有一些生命周期,当对象被强指针引用时,该对象一定存在。但当对象只被弱指针引用时,根据其生命周期,该对象有可能被释放。
二、轻量级指针
template <class T>
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
mCount.fetch_add(1, std::memory_order_relaxed);
}
inline void decStrong(__attribute__((unused)) const void* id) const {
if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
delete static_cast<const T*>(this);
}
}
inline int32_t getStrongCount() const {
return mCount.load(std::memory_order_relaxed);
}
private:
mutable std::atomic<int32_t> mCount;
};
轻量级指针采用atomic<int32_t> mCount进行指针计数。其模板类为sp<>,当调用以下语句时,mCount将自增,而当sp<>脱离作用域,系统自动回收时(sp是通过赋值操作,而不是new获得)。
LightClass *p = new LightClass(); //LightClass继承至LightBRefBase
sp<LightClass> pRef1 = p;
sp<LightClass> pRef2 = pRef1;
待续(一天写一点)
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
if (c != 1) return;
atomic_thread_fence(std::memory_order_acquire);
int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
if (impl->mStrong.load(std::memory_order_relaxed) == INITIAL_STRONG_VALUE) {
ALOGW("RefBase: Object at %p lost last weak reference "
"before it had a strong reference", impl->mBase);
} else {
delete impl;
}
} else {
impl->mBase->onLastWeakRef(id);
delete impl->mBase;
}
}
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
}
RefBase::~RefBase()
{
int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
delete mRefs;
}
} else if (mRefs->mStrong.load(std::memory_order_relaxed) == INITIAL_STRONG_VALUE) {
delete mRefs;
}
const_cast<weakref_impl*&>(mRefs) = NULL;
}
RefBase在构造函数中,将创建weakref_impl对象,并赋值给mRefs。
重量级指针
重量级指针分析比轻量级指针要难理解很多,这样按一定方法去分析,才能不迷失方向。
宗旨:时刻关心对象和计数器何时被释放
网友评论