在Android的源代码中,经常会看到如:sp< xxx>、wp< xxx>这样的类型定义,这其实是Android中的智能指针。智能指针是C++中的一个概念,通过基于引用计数的方法,解决对象的自动释放的问题。
智能指针主要涉及如下几个源码文件:
/system/core/libutils/include/utils/StrongPointer.h
/system/core/libutils/include/utils/RefBase.h
/system/core/libutils/RefBase.cpp
StrongPointer.h提供sp<>强指针类型
RefBase.h 主要提供wp<>弱指针类型
一、RefBase.h 中定义了类weakref_type,声明了相关函数,
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;
class weakref_type
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void decWeak(const void* id);
// acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id);
// acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object.
void printRefs() const;
//! DEBUGGING ONLY: Enable tracking for this object.
// enable -- enable/disable tracking
// retain -- when tracking is enable, if true, then we save a stack trace
// for each reference and dereference; when retain == false, we
// match up references and dereferences and keep only the
// outstanding ones.
void trackMe(bool enable, bool retain);
};
weakref_impl* const mRefs;
}
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
inline wp() : m_ptr(0) { }
...
T* m_ptr; //存储 new weakref_impl 对象的地址
weakref_type* m_refs; //m_refs 是weakref_type类型指针
}
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
if (other) m_refs = other->createWeak(this);
}
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
template<typename T>
wp<T>& wp<T>::operator = (T* other)
{
weakref_type* newRefs =
other ? other->createWeak(this) : 0;
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = newRefs;
return *this;
}
二、RefBase.cpp RefBase::weakref_type 中定义了RefBase.h 中声明的函数,例如:void RefBase::weakref_type::incWeak(const void* id)
同时 RefBase.cpp中 定义了类 weakref_impl ,weakref_impl 继承 类weakref_type。如下的mBase 即class RefBase 子类实例对象(对应三中的class A对象)。
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
std::atomic<int32_t> mStrong; //默认强引用计数为1<<28
std::atomic<int32_t> mWeak; //默认弱引用的计数为0
RefBase* const mBase; //RefBase的指针
std::atomic<int32_t> mFlags;
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)//RefBase::RefBase()构造函数传递class RefBase 子类实例对象
, mFlags(0)
, mStrongRefs(NULL)
, mWeakRefs(NULL)
, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
, mRetain(false)
{
}
...
void addWeakRef(const void* id) {
addRef(&mWeakRefs, id, mWeak.load(std::memory_order_relaxed));
...
private:
struct ref_entry
{
ref_entry* next;
const void* id;
#if DEBUG_REFS_CALLSTACK_ENABLED
CallStack stack;
#endif
int32_t ref;
};
void addRef(ref_entry** refs, const void* id, int32_t mRef)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
ref_entry* ref = new ref_entry;
// Reference count at the time of the snapshot, but before the
// update. Positive value means we increment, negative--we
// decrement the reference count.
ref->ref = mRef;
ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
ref->stack.update(2);
#endif
ref->next = *refs;
*refs = ref;
}
}
...
}
ref_entry* mStrongRefs; //所有的强引用,用链表存储在这里
ref_entry* mWeakRefs; //所有的弱引用,用链表存储在这里
}
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
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 RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->removeWeakRef(id); //删除弱引用
const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); //计数减1
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) {
// This is the regular lifetime case. The object is destroyed
// when the last strong reference goes away. Since weakref_impl
// outlives the object, it is not destroyed in the dtor, and
// we'll have to do it here.
if (impl->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {
// Decrementing a weak count to zero when object never had a strong
// reference. We assume it acquired a weak reference early, e.g.
// in the constructor, and will eventually be properly destroyed,
// usually via incrementing and decrementing the strong count.
// Thus we no longer do anything here. We log this case, since it
// seems to be extremely rare, and should not normally occur. We
// used to deallocate mBase here, so this may now indicate a leak.
ALOGW("RefBase: Object at %p lost last weak reference "
"before it had a strong reference", impl->mBase);
} else {
// ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
delete impl;
}
} else {
// This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
// is gone, we can destroy the object.
impl->mBase->onLastWeakRef(id);
delete impl->mBase; //如果没有其他引用了,就释放当前指针
}
}
//将weakref_impl 赋值给mRefs,同时实例化时候将this 即class RefBase 子类实例传递给 RefBase::weakref_impl 中的mBase
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
}
RefBase::~RefBase()
{
int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
// Life-time of this object is extended to WEAK, in
// which case weakref_impl doesn't out-live the object and we
// can free it now.
if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
// It's possible that the weak count is not 0 if the object
// re-acquired a weak reference in its destructor
if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
delete mRefs;
}
} else if (mRefs->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {
// We never acquired a strong reference on this object.
LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
"RefBase: Explicit destruction with non-zero weak "
"reference count");
// TODO: Always report if we get here. Currently MediaMetadataRetriever
// C++ objects are inconsistently managed and sometimes get here.
// There may be other cases, but we believe they should all be fixed.
delete mRefs;
}
// For debugging purposes, clear mRefs. Ineffective against outstanding wp's.
const_cast<weakref_impl*&>(mRefs) = NULL;
}
三、wp<> 弱引用初始化流程
class A : public RefBase
{
public:
void test();
}
以 wp<A> a = new A为例
3.1因为类A 继承了RefBase,new A的时候会调用RefBase的构造函数,此时 会调用new weakref_impl 创建弱指针实现类对象给指针变量 mRefs
RefBase::RefBase()
: mRefs(new weakref_impl(this))
3.2从如下模板类 wp定义可知,创建wp<A> 时会调用wp<T>::wp,然后调用other->createWeak,即weakref_impl的 createWeak,最终调用
RefBase::weakref_type* RefBase::createWeak
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
if (other) m_refs = other->createWeak(this);
}
3.3RefBase::createWeak 方法调用 mRefs->incWeak(id) 方法,mRefs即weakref_impl。
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
3.4 mWeak 弱引用计数 默认是0,impl->mWeak.fetch_add 执行 弱引用计数 +1;impl->addWeakRef(id)
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);
}
3.5 weakref_impl的addWeakRef方法 中,mWeakRefs 为 ref_entry*,id为wp<A> 弱引用指针地址.
void addWeakRef(const void* id) {
addRef(&mWeakRefs, id, mWeak.load(std::memory_order_relaxed));
}
3.6 addRef 将上面的弱引用指针地址,存储到弱引用链表存储。至此创建 wp<A> 和 new A 初始化流程结束
void addRef(ref_entry** refs, const void* id, int32_t mRef)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
ref_entry* ref = new ref_entry;
// Reference count at the time of the snapshot, but before the
// update. Positive value means we increment, negative--we
// decrement the reference count.
ref->ref = mRef;
ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
ref->stack.update(2);
#endif
ref->next = *refs;
*refs = ref;
}
}
3.7 wp<A> a = new A ,= 运算符执行了什么操作?看一下如下运算符重载,这里的 other 对应 new A对象。
即先调用A对象的 createWeak (流程同上面2),然后调用 m_refs->decWeak 原来的 m_refs 需要decWeak,即调用
RefBase::weakref_type::decWeak
template<typename T>
wp<T>& wp<T>::operator = (T* other)
{
weakref_type* newRefs =
other ? other->createWeak(this) : 0;
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = newRefs;
return *this;
}
3.8 RefBase::weakref_type::decWeak,先删除当前的弱引用,然后引用计数减1,
如果引用计数不为1则认为还有其他引用在用这个指针,直接返回;否则认为没有其他引用 ,调用 delete impl->mBase 释放当前指针
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->removeWeakRef(id); //删除弱引用
const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); //获取弱引用计数给c,然后弱引用计数减1
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) {
// This is the regular lifetime case. The object is destroyed
// when the last strong reference goes away. Since weakref_impl
// outlives the object, it is not destroyed in the dtor, and
// we'll have to do it here.
if (impl->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {
// Decrementing a weak count to zero when object never had a strong
// reference. We assume it acquired a weak reference early, e.g.
// in the constructor, and will eventually be properly destroyed,
// usually via incrementing and decrementing the strong count.
// Thus we no longer do anything here. We log this case, since it
// seems to be extremely rare, and should not normally occur. We
// used to deallocate mBase here, so this may now indicate a leak.
ALOGW("RefBase: Object at %p lost last weak reference "
"before it had a strong reference", impl->mBase);
} else {
// ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
delete impl;
}
} else {
// This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
// is gone, we can destroy the object.
impl->mBase->onLastWeakRef(id);
delete impl->mBase; //如果没有其他引用了,就释放当前指针
}
}
四、弱指针也指向一个对象,但是弱指针仅仅记录该对象的地址,不能通过弱指针来访问该对象,也就是说不能通过弱引用指针来调用对象的成员函数或访问对象的成员变量。要想访问弱指针所指向的对象,
需首先将弱指针升级为强指针(通过wp类所提供的 promote()方法)。弱指针所指向的对象是有可能在其它地方被销毁的,如果对象已经被销毁,wp的promote()方法将返回空指针,这样就能避免出现地址访问错的情况。
五、sp<> 强引用初始化流程
以 sp<A> a = new A为例,
5.1 其中 new A流程同三
5.2 从如下模板类 sp定义可知,创建sp<A>时会调用sp<T>::sp,然后调用other->incStrong,即 weakref_impl 的 incStrong ,最终调用
RefBase::incStrong,m_ptr 存储 weakref_impl 的引用
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) {
if (other)
other->incStrong(this);
}
5.3 先执行 弱引用计数 +1(流程同3.4),再执行强引用计数 +1(流程参考3.4,最终是将强引用指针地址,存储到强引用链表mStrongRefs存储)。如前面 二所述 refs->mBase 对应 class RefBase 子类实例对象(对应三中的class A对象)。如果A 重写了onFirstRef方法即会调用 A中的onFirstRef方法,
即每次强引用计数+1时,回调用其对象的onFirstRef方法。
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id); //弱引用计数 +1
refs->addStrongRef(id); //强引用计数 +1
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 = 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();
}
5.4 sp<A> a = new A,= 运算符执行了什么操作?看一下如下运算符重载,这里的 other 对应 new A对象。
即先调用A对象的 incStrong (流程同上面2),然后调用 oldPtr->decStrong 原来的 m_ptr 需要 decStrong ,即调用
RefBase::decStrong
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;
}
5.5 RefBase::decStrong 方法中先 移除强引用链表中的引用id,然后强引用计数-1,判断是否最后一个引用,如果是则释放该指针
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id); //移除强引用链表中的引用id
const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release); //先获取当前强引用计数给c,然后强引用计数-1
#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) { //如果是最后一个了,那需要释放该指针了
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.
refs->decWeak(id); //减少弱引用链表
}
参考:
https://blog.csdn.net/qq_24451593/article/details/80112732
https://blog.csdn.net/shift_wwx/article/details/78864099