AndroidL 智能指针sp wp RefBase LightRefBase

Android系统中,不再使用的Java对象会通过gc机制自动回收,相应的对C++对象也提供了回收机制--智能指针。
Android中智能指针分为:轻量级LightRefBase和重量级RefBase。
LightRefBase只能使用sp指针,主要用于简单的管理一些全局对象的自动释放,通常用于简单逻辑处理。

RefBase可通过sp指针决定对象生命周期,还可以通过wp指针来维持对象的引用关系,通过“由弱升强”来访问对象成员。
RefBase可以通过设置mFlags来限制智能指针对实际对象生命周期的影响。

智能指针可以管理的对象必须是LightRefBase或RefBase的子类对象。
当使用智能指针管理对象时,不要试图通过delete手动删除实际对象。

1.对象的创建

Class TestObj
{
public:
TestObj();
~TestObj();
private:
int mParm;
};

// mTestObj指针是在栈空间上分配
// TestObj的对象是在堆空间分配的
// 将TestObj的对象地址赋值给mTestObj
// 动态创建的堆对象都要手动通过delete来释放对象空间
// 忘记了释放,容易造成"内存泄漏"
// 访问一个已经已经释放了的堆对象,会造成系统崩溃

TestObj *mTestObj = new TestObj(); // 堆对象

int main(int argc, char** argv)
{
// testObj对象是在栈空间上分配的,
// 当main方法退出后,testObj对象自动释放
// 栈对象的特点为:创建简单,使用后自动释放

TestObj testObj(); // 栈对象
return 0;

}


2.智能指针
为了解决以上问题,我们希望有一个"智能指针",它能自动记录一个对象被引用的次数。
智能指针使用的是引用计数机制,对象本身包含了一个引用计数器记录引用次数。
当创建新对象时,初始化指针并将引用计数器置1。
当对一个对象进行赋值时,赋值操作符“=”减少左操作数所指对象的引用计数,并增加右操作数所指对象的引用计数
当调用析构函数时,析构函数减少引用计数
当引用次数为0时自动释放掉该对象
并且智能指针类中重载了operator->和operator*来返回原始对象指针,这样智能指针使用起来就像原始对象指针一起。
Android中实现了两种智能指针:轻量级指针和强弱指针。


3.轻量级指针
继承于LightRefBase,并用sp创建的则为轻量级指针
引用计数器 system/core/include/utils/RefBase.h

........
template <class T> // 模板
class LightRefBase
{
public:
    inline LightRefBase() : mCount(0) { }       // 初始化引用计数器为0
    inline void incStrong(__attribute__((unused)) const void* id) const {
        __sync_fetch_and_add(&mCount, 1); // 引用计数器加1
    }
    inline void decStrong(__attribute__((unused)) const void* id) const {
        if (__sync_fetch_and_sub(&mCount, 1) == 1) { // 引用计数器减1
            delete static_cast<const T*>(this);  // 如果引用计数器为0,则释放对象空间
        }
    }
    inline int32_t getStrongCount() const {    // 获取对象当前引用次数
        return mCount;
    }
    ........
private:
    mutable volatile int32_t mCount;             // 引用计数器
};

........


轻量级指针 system/core/include/utils/StrongPointer.h
........
template <typename T>
class sp
{
public:
    inline sp() : m_ptr(0) { }

    sp(T* other);
    sp(const sp<T>& other);
    template<typename U> sp(U* other);
    template<typename U> sp(const sp<U>& other);

    ~sp();

    // 重载=
    sp& operator = (T* other);
    sp& operator = (const sp<T>& other);
    template<typename U> sp& operator = (const sp<U>& other);
    template<typename U> sp& operator = (U* other);
    ........
    // 重载*,->
    inline  T&      operator* () const  { return *m_ptr; } // 相当于*m_ptr
    inline  T*      operator-> () const { return m_ptr;  } // 相当于m_ptr->
    inline  T*      get() const         { return m_ptr; }
    ........
private:
    ........
    T* m_ptr; // 要进行管理的目标对象
};
........
template<typename T>
sp<T>::sp(T* other) // 构造函数参数为T类型指针
  : m_ptr(other)
{
  if (other) other->incStrong(this); // 当创建sp对象时,增加强引用计数
}

template<typename T>
sp<T>::sp(const sp<T>& other) // 构造函数参数为T类型引用对象
  : m_ptr(other.m_ptr)
{
  if (m_ptr) m_ptr->incStrong(this);
}
........
template<typename T>
sp<T>::~sp()
{
    if (m_ptr) m_ptr->decStrong(this); // 当析构sp对象时,减少强引用计数
}

template<typename T>
sp<T>& sp<T>::operator = (const sp<T>& other) { // 对“=”运算符进行重载
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);  // 增加other对象强引用计数
    if (m_ptr) m_ptr->decStrong(this);  // 减少sp对象持有的旧对象强引用计数
    m_ptr = otherPtr; // 将other对象保存到sp对象中
    return *this;
}
........


4.强指针
继承于RefBase,并用sp创建的则为强指针
system/core/include/utils/RefBase.h

........
class RefBase
{
public:
    void            incStrong(const void* id) const;
    void            decStrong(const void* id) const;
    void            forceIncStrong(const void* id) const; // 弱指针升级为强指针
    ........
    class weakref_type
    {
    public:
        RefBase*            refBase() const;
        void                incWeak(const void* id);
        void                decWeak(const void* id);
        ........
    };
    ........
    typedef RefBase basetype;
protected:
    RefBase();
    virtual ~RefBase();
    
    //! Flags for extendObjectLifetime()
    enum {
        OBJECT_LIFETIME_STRONG  = 0x0000, // 目标对象为强引用
        OBJECT_LIFETIME_WEAK    = 0x0001, // 目标对象为弱引用
        OBJECT_LIFETIME_MASK    = 0x0001
    };
    ........
    virtual void            onFirstRef(); // 强指针第一次创建时调用此方法
    virtual void            onLastStrongRef(const void* id); // 强指针最后一次调用时调用此方法 
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id); 
    virtual void            onLastWeakRef(const void* id); // 弱指针最后一次调用时调用此方法
    ........
    weakref_impl* const mRefs;
};
........

system/core/libutils/RefBase.cpp
........
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
    volatile int32_t    mStrong; // 强引用计数变量
    volatile int32_t    mWeak;  // 弱引用计数变量
    RefBase* const      mBase;
    volatile int32_t    mFlags;  // 目标对象是否受引用计数标志变量

#if !DEBUG_REFS

    weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)
        , mWeak(0)
        , mBase(base)
        , mFlags(0) //初始化为0,即不是OBJECT_LIFETIME_WEAK,也不是OBJECT_LIFETIME_FOREVER
    {
    }
    ........
#else
    ........
}
........
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);
    ........
    android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
    refs->mBase->onFirstRef(); // 当第一次强引用时调用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 (c == 1) {
        refs->mBase->onLastStrongRef(id); // 当最后一次强引用对象时回调onLastStrongRef
        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            delete this; //当目标对象生命周期不受弱引用计数影响时,删除目标对象
        }
    }
    refs->decWeak(id); // 减少弱引用计数
}
// 弱指针升级为强指针方法
void RefBase::forceIncStrong(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, "forceIncStrong called on %p after ref count underflow",
               refs);
#if PRINT_REFS
    ALOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
#endif

    switch (c) {
    case INITIAL_STRONG_VALUE:
        android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
        // fall through...
    case 0:
        refs->mBase->onFirstRef();
    }
}
........
RefBase::RefBase()
    : mRefs(new weakref_impl(this)) // 构造函数,创建weakref_impl对象赋值给mRefs
{
}

RefBase::~RefBase()  // 析构函数,当弱引用计数减为0时,删除mRefs指向的对象
{
    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;
}
........

5.弱指针
继承于RefBase,并用wp创建的则为弱指针,它不能和sp一样直接访问目标对象成员
system/core/include/utils/RefBase.h

template <typename T>
class wp
{
public:
    typedef typename RefBase::weakref_type weakref_type;

    inline wp() : m_ptr(0) { }
    // 三种构造函数的定义
    wp(T* other); // 参数为T类型的指针
    wp(const wp<T>& other); // 参数为弱指针
    wp(const sp<T>& other);  // 参数为强指针
    template<typename U> wp(U* other);
    template<typename U> wp(const sp<U>& other);
    template<typename U> wp(const wp<U>& other);

    ~wp();

    // 重载了=运算符,但是没有实现运算符->与*,说明我们可以为wp赋值,而不能通过wp直接访问目标对象
    wp& operator = (T* other);
    wp& operator = (const wp<T>& other);
    wp& operator = (const sp<T>& other);

    template<typename U> wp& operator = (U* other);
    template<typename U> wp& operator = (const wp<U>& other);
    template<typename U> wp& operator = (const sp<U>& other);

    void set_object_and_refs(T* other, weakref_type* refs);

    // 用来将一个弱引用升级为强引用
    sp<T> promote() const;

    // 用来清除弱引用指针,减少对实际对象的弱引用计数,将m_ptr指针清空
    void clear();
    ........
    // 持有两种指针
    T*              m_ptr;
    weakref_type*   m_refs;
};
........
// 构造函数,引用计数器加1
template<typename T>
wp<T>::wp(T* other) // 接收指针
    : m_ptr(other)
{
    if (other) m_refs = other->createWeak(this);
}

template<typename T>
wp<T>::wp(const wp<T>& other) // 接收弱引用
    : m_ptr(other.m_ptr), m_refs(other.m_refs)
{
    if (m_ptr) m_refs->incWeak(this);
}

template<typename T>
wp<T>::wp(const sp<T>& other) // 接收强引用
    : m_ptr(other.m_ptr)
{
    if (m_ptr) {
        m_refs = m_ptr->createWeak(this);
    }
}

template<typename T> template<typename U>
wp<T>::wp(U* other) // 两种类型U->T的转换
    : m_ptr(other)
{
    if (other) m_refs = other->createWeak(this);
}
........
template<typename T>
wp<T>::~wp() // 析构函数,引用计数器减1
{
    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;
}
........
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 = android_atomic_inc(&impl->mWeak); // 计数器加1
    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 = android_atomic_dec(&impl->mWeak); // 减少弱引用计数
    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    if (c != 1) return;  //当弱引用计数 !=1 时,直接返回


    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
        if (impl->mStrong == INITIAL_STRONG_VALUE) { // 标记为INITIAL_STRONG_VALUE
            delete impl->mBase; // 释放RefBase对象
        } else {
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl; // 释放内置的weakref_type对象
        }
    } else { // 标记为OBJECT_LIFETIME_WEAK
        impl->mBase->onLastWeakRef(id);
        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {  
            delete impl->mBase; // 标记为非OBJECT_LIFETIME_FOREVER时,只释放RefBase对象
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值