0%

Android智能指针

基于Android P源码分析,加深对RefBase、sp、wp的理解。

前言

Android源码中存在大量C++代码,里面涉及智能指针的使用,除了标准库的std::shared_ptr和std::weak_ptr,还有sp/wp搭配RefBase通过强弱引用计数实现对c++对象回收机制的管理。

相关代码位于:

1
2
3
4
system/core/libutils/include/utils/RefBase.h
/system/core/libutils/include/util/StrongPointer.h
system/core/libutils/RefBase.cpp
system/core/libutils/StrongPointer.cpp

类图关系如下:
RefBase

sp模板类

[ StrongPointer.h ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
template<typename T>
class sp {
public:
inline sp() : m_ptr(0) { }

sp(T* other); // NOLINT(implicit)
sp(const sp<T>& other);
sp(sp<T>&& other);
template<typename U> sp(U* other); // NOLINT(implicit)
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)

~sp();

// Assignment
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
sp& operator = (sp<T>&& other);

template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (sp<U>&& other);
template<typename U> sp& operator = (U* other);

//! Special optimization for use by ProcessState (and nobody else).
void force_set(T* other);

// Reset
void clear();

//指针访问重载
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
inline explicit operator bool () const { return m_ptr != nullptr; }

//操作符重载
COMPARE(==)
COMPARE(!=)
COMPARE(>)
COMPARE(<)
COMPARE(<=)
COMPARE(>=)

private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr);
T* m_ptr; //对应类的指针
};

sp构造函数和赋值函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) {
if (other)
other->incStrong(this);
}

template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}

template<typename T>
sp<T>& sp<T>::operator =(const sp<T>& other) {
// Force m_ptr to be read twice, to heuristically check for data races.
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
T* otherPtr(other.m_ptr);
if (otherPtr) otherPtr->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = otherPtr;
return *this;
}

template<typename T>
sp<T>& sp<T>::operator =(T* other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (other) other->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other;
return *this;
}

以surfaceflinger服务为例,main_surfaceflinger.cpp中有以下代码,这里既有sp构造函数,又有sp赋值构造函数。其中ProcessState继承于RefBase,所以初始化过程会初始化其父类RefBase。

1
2
3
4
5
6
7
8
int main(int, char**) {
...
// start the thread pool
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();

...
}

RefBase构造函数

RefBase的构造函数,首先构造weakref_impl对象,这里的this指向当前对象的指针,该对象应该继承于RefBase。

1
2
3
4
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
}

weakref_impl

weakref_impl的成员变量mBase为ProcessState指针,最终会调用目标对象的incStrong()方法,这里是RefBase::incStrong()方法。

1
2
3
4
5
6
7
8
9
10
11
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE) //强引用计数 0x10000000
, mWeak(0) //弱引用计数为0
, mBase(base) //继承类对象的指针
, mFlags(0)
, mStrongRefs(NULL)
, mWeakRefs(NULL)
, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
, mRetain(false)
{
}

incStrong

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id);

refs->addStrongRef(id);
const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
#if PRINT_REFS
ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
if (c != INITIAL_STRONG_VALUE) {
return;
}

int32_t old __unused = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, std::memory_order_relaxed);
// A decStrong() must still happen after us.
ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
refs->mBase->onFirstRef();
}

首先调用weakref_impl的incWeak()增加的指针弱引用计数,同时增加mStrong指针强引用计数;当首次引用该对象时,回调目标对象的onFirstRef()方法。

incWeak

1
2
3
4
5
6
7
8
9
10
11
12
void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->addWeakRef(id);
const int32_t c __unused = impl->mWeak.fetch_add(1,
std::memory_order_relaxed);
ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}

void addWeakRef(const void* id) {
addRef(&mWeakRefs, id, mWeak.load(std::memory_order_relaxed));
}

weakref_impl是weakref_type的子类,首先增加weakref_impl中mWeak的弱引用计数,所以此时mWeak和mStrong引用计数都为1。当sp对象ProcessState退出作用域时,就会调用对应析构函数释放该对象。

RefBase析构函数

sp析构函数

1
2
3
4
5
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}

m_ptr保存对象,该对象继承于RefBase,所以析构函数会调用RefBase::decStrong()方法。

decStrong

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id);
const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);

LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
refs);
if (c == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
refs->mBase->onLastStrongRef(id);
int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
delete this;
// The destructor does not delete refs in this case.
}
}

refs->decWeak(id);
}

对mStrong强引用计数执行减1操作,如果操作之前mStrong就是1,回调目标对象的onLastStrongRef()方法。如果当前flags设置对象的生命周期由强引用计数决定,那么就会释放该目标对象,最后调用decWeak()减少弱引用计数。

decWeak

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->removeWeakRef(id);
//mWeak执行减1操作
const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
this);
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; //释放weakref_impl对象
}
} else {
impl->mBase->onLastWeakRef(id);
delete impl->mBase; //释放实际目标对象
}
}

对mWeak执行减1操作,如果操作前mWeak不等于1,表示还有其他wp引用,这里直接返回;如果mWeak等于1,表示没有其他wp引用,这里需要释放目标对象和weakref_impl对象。如果flags设定目标对象的生命周期由强引用计数决定,则释放weakref_impl对象,目标对象已经在调用decWeak()方法前被释放;如果flags设定目标对象的生命周期由弱引用计数决定,则调用目标对象的onLastWeakRef()方法,然后释放目标对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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) {
LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
"RefBase: Explicit destruction with non-zero weak "
"reference count");
delete mRefs;
}
const_cast<weakref_impl*&>(mRefs) = NULL;
}

在释放目标对象时,会调用到父类的析构函数,如果flags设定目标对象的生命周期由弱引用计数决定,并且mWeak计数为0,则删除weakref_impl对象;如果没有sp引用该目标对象,释放weakref_impl对象。

总结

RefBase是Android C++类的父类,有一个成员变量mRefs为weakref_impl类型指针,weakref_impl是weakref_type的子类,用来管理引用计数。

首次调用对象incStrong(),则会调用该对象的onFirstRef();调用decStrong()的最后一次,则调用该对象的onLastStrongRef()。

弱引用不能直接操作目标对象,因为wp模版类没有实现指针引用的重载,而sp模版类则实现了指针引用的重载,但是可以通过promote()函数将弱引用提升为强引用对象。

1
2
3
4
5
6
7
8
9
template<typename T>
sp<T> wp<T>::promote() const
{
sp<T> result;
if (m_ptr && m_refs->attemptIncStrong(&result)) {
result.set_pointer(m_ptr);
}
return result;
}