Android 智能指针

RefBase sp wp

Posted by LXG on December 8, 2021

Android智能指针RefBase、sp、wp解析-简书

Android C++代码中的强指针和弱指针

C++ 内存回收

c_memory

Android智能指针原理

智能指针分为3类为轻量级指针(Light Pointer)、强指针(Strong Pointer)和弱指针(Weak Pointer)

  1. Android 设计了基类RefBase, 用以管理引用计数,所有类必须从RefBase派生
  2. 设计模板类 sp wp, 用以引用实际对象,sp强引用和wp弱引用。sp wp 声明为栈对象,作用域结束时自动调用析构函数
  3. 在sp wp的构造函数中,增加引用数; 在析构函数中,减少引用计数
  4. 设计了weakref_impl类,是RefBase的内部类,用来做真正应用计数管理,创建实际对象时,同时创建一个mRefs对象。不管强引用和弱引用,都由mRref管理

refbase

原子操作函数

system/core/libcutils/Atomic.c system/core/include/cutils/atomic-arm.h


extern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr)
{
    return android_atomic_add(1, addr);
}

extern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr)
{
    return android_atomic_add(-1, addr);
}

RefBase

./system/core/include/utils/RefBase.h ./system/core/libutils/RefBase.cpp

RefBase.h


// ---------------------------------------------------------------------------

class RefBase
{
public:
            void            incStrong(const void* id) const;
            void            decStrong(const void* id) const;
            void            forceIncStrong(const void* id) const;
            int32_t         getStrongCount() const;

    class weakref_type
    {

    }

protected:
                            RefBase();
    virtual                 ~RefBase();

private:
    friend class weakref_type;
    class weakref_impl;

private:
    weakref_impl* const mRefs;
};

// ---------------------------------轻量级指针------------------------------------------

template <class T>
class LightRefBase
{
public:
    inline LightRefBase() : mCount(0) { }
    inline void incStrong(__attribute__((unused)) const void* id) const {
        android_atomic_inc(&mCount);
    }
    inline void decStrong(__attribute__((unused)) const void* id) const {
        if (android_atomic_dec(&mCount) == 1) {
            delete static_cast<const T*>(this);
        }
    }
    //! DEBUGGING ONLY: Get current strong ref count.
    inline int32_t getStrongCount() const {
        return mCount;
    }

    typedef LightRefBase<T> basetype;

protected:
    inline ~LightRefBase() { }

private:
    mutable volatile int32_t mCount;
};

// ---------------------------------------------------------------------------

RefBase.cpp


RefBase::RefBase()
    : mRefs(new weakref_impl(this)) // 真正管理引用计数
{
}

class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
    volatile int32_t    mStrong;
    volatile int32_t    mWeak;
    RefBase* const      mBase;
    volatile int32_t    mFlags;

    weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)  // 强引用计数
        , mWeak(0)      // 弱引用计数
        , mBase(base) // 指向实际对象
        , mFlags(0)   // 指定强引用控制还是弱引用控制
    {
    }

}

// 构造函数
RefBase::RefBase()
    : mRefs(new weakref_impl(this))
{
}

// 析构函数
RefBase::~RefBase()
{
    if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
        // we never acquired a strong (and/or weak) reference on this object.
        delete mRefs;
    } else {
        // life-time of this object is extended to WEAK or FOREVER, in
        // which case weakref_impl doesn't out-live the object and we
        // can free it now.
        if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
            // It's possible that the weak count is not 0 if the object
            // re-acquired a weak reference in its destructor
            if (mRefs->mWeak == 0) {
                delete mRefs;
            }
        }
    }
    // for debugging purposes, clear this.
    const_cast<weakref_impl*&>(mRefs) = NULL;
}

void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->incWeak(id);
    
    refs->addStrongRef(id);
    const int32_t c = android_atomic_inc(&refs->mStrong);
    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;
    }

    android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
    refs->mBase->onFirstRef();
}

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);
    const int32_t c = android_atomic_dec(&refs->mStrong);
#if PRINT_REFS
    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
    if (c == 1) {
        refs->mBase->onLastStrongRef(id);
        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            delete this;
        }
    }
    refs->decWeak(id);
}

强指针

system/core/include/utils/StrongPointer.h

StrongPointer.h


template<typename T>
sp<T>::sp(T* other)
        : m_ptr(other) {
    if (other)
        other->incStrong(this);  // 实际上调用的是RefBase 的 incStrong方法
}

template<typename T>
sp<T>::~sp() {
    if (m_ptr)
        m_ptr->decStrong(this);
}

强指针用法

Demo1

libbinder.so

./frameworks/native/libs/binder/IInterface.cpp


class IInterface : public virtual RefBase
{
public:
            IInterface();
            sp<IBinder>         asBinder();
            sp<const IBinder>   asBinder() const;
            
protected:
    virtual                     ~IInterface();
    virtual IBinder*            onAsBinder() = 0;
};

./frameworks/av/include/camera/ICamera.h


class ICamera: public IInterface
{

}

Demo2

framework/base/media/jni/android_media_MediaRecorder.cpp


static void
android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
                                         jstring packageName)
{
    ALOGV("setup");

    sp<MediaRecorder> mr = new MediaRecorder();

}

framework/av/media/libmedia/mediarecorder.cpp


class MediaRecorder : public BnMediaRecorderClient,
                      public virtual IMediaDeathNotifier
{

}

framework/av/include/media/IMediaDeathNotifier.h


class IMediaDeathNotifier: virtual public RefBase
{

}

弱指针

./system/core/include/utils/RefBase.h ./system/core/libutils/RefBase.cpp

RefBase.h


template <typename T>
class wp
{
public:
    typedef typename RefBase::weakref_type weakref_type;
    
    inline wp() : m_ptr(0) { }

    wp(T* other);

    ~wp();


private:
    template<typename Y> friend class sp;
    template<typename Y> friend class wp;

    T*              m_ptr;
    weakref_type*   m_refs;
};

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);
}