Android智能指针(三):sp

代码

...
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。