代码
...
sp<A>spA(A); // 见③
...
这是我们例子中创建sp的步骤,sp其实是一个模板类,而对应的创建sp的方法也有几种,具体可以查看源码,下面我们来一一对应。并且说明创建sp究竟做了哪些工作。
本例中使用的是括号的方式,而对应的构造方法是:
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) {
if (other)
other->incStrong(this);
}
也就是调用了函数对应的incstrong的方法。
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id);
refs->addStrongRef(id); // release版本不会做任何事情
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;
}
// 说明是第一次初始化,需要进行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::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);
}
原子操作的具体逻辑就不说了,此处的逻辑是:
1.首先将weak的数量+1,那么现在就是s0w1.
2.fetch_add返回先前保存的值。那么就可以判断出是否是第一次创建。
3.如果是第一次创建则需要调用onfirstref
4.那么此时引用计数其实就是s1w1.
总结:
这次我们看了如何创建sp,也就是strongpointer,在创建完对象后,其实mrefs的影子对象中其实S0W0的状态,而在sp进行创建之后,其实就是添加了强引用和弱引用,而此时的一个状态是S1W1。