前言
前面我们都已经说完了,当前计数器已经是S1W2了,那么当他们使用结束之后又是怎么回收的呢?我们要知道怎么来也应该知道怎么去的。
在函数结束之后,就会走到对应的析构函数中。
wp的析构函数
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
额,从函数名就可以看出来,是直接将weak的数量进行了-1,那么真的有那么容易吗?
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);
ALOGW_IF(BAD_WEAK(c), "decWeak called on %p too many times",
this);
if (c != 1) return; // c==1 说明当前结果就是0.
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;
}
}
一看,果然没有那么简单。
1.如果当前正好是最后1个,减下去之后就变成0,那么进入flag判断。
2.如果不是是strong的lifetime,那么就可以直接走删除操作,删除该对象。
3.lifetimestrong的,查看strong指针是否进行过赋值,如果没有赋值,那么其实就没有可以删除的。如果是复制了的,那么其实impl就是可以被删除的。
sp的析构函数
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}
果然也是如此的简单,那么我们看看具体的实现吧。
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) {
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);
}
最后的decweak我们就不说了,因为前面已经说过了。那么我们看前面。
1.原子操作,拿到当前的计数,如果是0,那么就说明需要进行操作了。
2.进行laststrongref操作。
3.如果当前的flag是lifetimestrong,那么就可以delete这个了。
LIFE_TIME
其实我们都可以看到,在decstrong和decweak的时候,都需要进行LIFE_TIME的判断来判断是否需要删除。那我们先看第一种情况。
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.
#if DEBUG_REFBASE_DESTRUCTION
// Treating this as fatal is prone to causing boot loops. For debugging, it's
// better to treat as non-fatal.
ALOGD("RefBase: Explicit destruction, weak count = %d (in %p)", mRefs->mWeak.load(), this);
CallStack::logStack(LOG_TAG);
#else
LOG_ALWAYS_FATAL("RefBase: Explicit destruction, weak count = %d", mRefs->mWeak.load());
#endif
}
// For debugging purposes, clear mRefs. Ineffective against outstanding wp's.
const_cast<weakref_impl*&>(mRefs) = nullptr;
}
如果lifetime是weak的话,那么就可以直接删除影子对象。
LIFE_TIME_WEAK
在decstrong的时候,就不会直接删除该对象,而是到了decweak的时候才会删除。会将对象和对应的影子对象一并删除。
LIFE_TIME_STRONG
如果当前对象flag是strong,那么在strong==0的时候就会删除该对象。当强弱引用都减到0,普遍常见是会把实际对象和weakref_impl对象都释放。