C++层Binder——智能指针
要讲native层的Binder机制,那得首先搞明白native层智能指针的原理。
core/include/utils/RefBase.h
core/libutils/RefBase.cpp
core/libutils/include/utils/StrongPointer.h
一、RefBase
一个对象想要使用智能指针,该对象则必须要满足一个前提条件,即该对象必须继承自RefBase。这很好理解,智能指针的原理便是有一个引用计数用于计算该对象被引用的次数,而这个引用计数显然是应该被存储到被引用对象里面的。是的,这个引用计数正式在RefBase里面。
class RefBase
{public:
void incStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
……
weakref_impl* const mRefs;
};
是的,这个weakref_impl正是引用计数的管理类。
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
std::atomic<int32_t> mStrong;
std::atomic<int32_t> mWeak;
RefBase* const mBase;
std::atomic<int32_t> mFlags;
……
}
mStrong是强引用计数,mWeak是弱引用计数,mBase则是引用对象所在指针。
回到RefBase类来,RefBase类还有两个关键函数,分别是incStrong和decStrong,用于增加强引用计数和减少强引用计数。
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) { //若c != INITIAL_STRONG_VALUE说明该对象不是第一次被引用,INITIAL_STRONG_VALUE是mStrong的初值
return; //不是第一次被引用,直接退出函数
}
//否则是第一次被引用,会调用onFirstRef接口
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();
}
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); //真正减少强引用计数的地方
#if PRINT_REFS
ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
refs);
if (c == 1) { //强引用计数只剩下一个时,执行下面逻辑,会调用被引用用对象的onLastStrongRef方法
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.
}
}
// Note that even with only strong reference operations, the thread
// deallocating this may not be the same as the thread deallocating refs.
// That's OK: all accesses to this happen before its deletion here,
// and all accesses to refs happen before its deletion in the final decWeak.
// The destructor can safely access mRefs because either it's deleting
// mRefs itself, or it's running entirely before the final mWeak decrement.
//
// Since we're doing atomic loads of `flags`, the static analyzer assumes
// they can change between `delete this;` and `refs->decWeak(id);`. This is
// not the case. The analyzer may become more okay with this patten when
// https://bugs.llvm.org/show_bug.cgi?id=34365 gets resolved. NOLINTNEXTLINE
refs->decWeak(id); //减少弱引用计数
}
以上是增加和减少弱引用计数的调用方法,有趣的是,RefBase类中,只有修改强引用计数的方法,但修改弱有引用的地方只有一处createWeak方法,该方法实际上也是调用的weakref_type中的incWeak。
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
所以本质上修改弱引用计数的方法在weakref_type类中,该类是weakref_impl的父类,而weakref_impl正式引用计数的管理类。那么使用wp对RefBase进行弱引用时,又是怎么修改RefBase的弱引用计数呢?
二、wp
当使用wp引用RefBase及其子类时,wp会从RefBase中直接获取weakref_impl并存储到自己的m_refs成员变量中。
template <typename T>
class wp
{
……
weakref_type* m_refs;
};
然后有两个方式增加弱引用,一是直接调用weakref_type的incWeak和decWeak对弱引用计数进行操作。二是调用RefBase的createWeak方法。
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
//other不是wp类型,说明是第一次引用,且不为空时,
m_refs = other ? m_refs = other->createWeak(this) : nullptr;
}
template<typename T>
wp<T>::wp(const wp<T>& other)
: m_ptr(other.m_ptr), m_refs(other.m_refs)
{
if (m_ptr) m_refs->incWeak(this);
}
template<typename T>
wp<T>::wp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
}
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this); //减少弱引用的方法只有调用RefBase的decWeak
}
三、sp
sp的成员变量只有一个m_ptr,而m_ptr本质上是被引用的RefBase子类。
class sp {
……
T* m_ptr;
};
在sp的构造和析构函数中,会分别增加、减少RefBase的强引用计数。而其调用的方法则是RefBase中的incStrong和decStrong
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) {
if (other) {
check_not_on_stack(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(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
template<typename T> template<typename U>
sp<T>::sp(U* other)
: m_ptr(other) {
if (other) {
check_not_on_stack(other);
(static_cast<T*>(other))->incStrong(this);
}
}
template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(sp<U>&& other)
: m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}
四、UML
Android C++的智能指针UML图如下所示