Android智能指针sp wp详解

研究Android的时候,经常会遇到sp、wp的东西,网上一搜,原来是android封装了c++中对象回收机制。
说明:
1. 如果一个类想使用智能指针,那么必须满足下面两个条件:
    a. 该类是虚基类RefBase的子类或间接子类
    b. 该类必须定义虚构造函数。如virtual ~MyClass();
2. 本文以类BBinder来进行说明,其余类使用sp或wp的情况类似
3. 代码路径:frameworks/base/libs/utils/RefBase.cpp
       frameworks/base/include/utils/RefBase.h

一、calss BBinder类说明
      class RefBase
      class IBinder
 class BpBinder   class BBinder
 class BBinder : public IBinder
 {
 ...
 protected:
     virtual             ~BBinder();
 ...
 }
 class IBinder : public virtual RefBase
 {
 ...
 protected:
     inline virtual      ~IBinder() { }
 ...
 }
 由上,可以看出BBinder和IBinder都是以public的方式继承于虚基类RefBase的。

二、sp wp对象的建立过程
 解析:sp<BBinder>  BB_ptr(new BBinder);
 这是一条定义sp指针BB_ptr的语句,他只想的对象是一个BBinder对象。
 如图所示。
 

Android智能指针sp wp详解


 1》首先看一下new BBinder时都做了什么,特别是和该机制相关的初始化。
   c++中创建一个对象时,需要调用去构造函数,对于继承类,则是先调用其父类的构造函数,然后才会调用本身的
   构造函数。这里new一个BBinder对象时,顺序调用了:
    RefBase::RefBase() : mRefs(new weakref_impl(this)) {}
    inline   IBinder() {}
    BBinder::BBinder() : mExtras(NULL){}
   主要关注的是RefBase的构造函数,
   可以看出他是通过new weakref_impl(this)的结果来初始化私有成员mRefs
   这里的this指向BBinder对象自身,class weakref_impl继承于类RefBase的内嵌类weakref_type,然后该类
   weakref_impl又被类RefBase引用。类weakref_impl的构造函数如下:
   weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)    // 1 << 28
        , mWeak(0)
        , mBase(base)             // new BBinder指针
        , mFlags(0)
        , mStrongRefs(NULL)          // sp引用链表指针
        , mWeakRefs(NULL)           // wp引用链表指针
        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT) // 1
        , mRetain(false) {}
  
 2》new BBinder返回的是BBinder对象的指针,如:sp<BBinder>  BB_ptr(0x????????);
   sp实际上是一个类模板,这条语句最终是要建立一个sp的实例化对象,叫模板类BB_ptr
   这里生成BB_ptr对象所调用的构造函数是:
   template<typename T>
   sp<T>::sp(T* other)
       : m_ptr(other)
   {
       if (other) other->incStrong(this);
   }
   BB_ptr对象的私有指针指向刚刚前面生成的BBinder对象。
   接着调用函数incStrong(),该函数是RefBase类的成员函数,在子类中没有被重载,所以这里
   other->incStrong(this)的调用实际上是调用基类成员函数incStrong(this),这个this值是指向sp对象
   BB_ptr的指针。现在转去查看该成员函数的实现。
   
   void RefBase::incStrong(const void* id) const
   {
       weakref_impl* const refs = mRefs;
       /* 取得BBinder对象基类中的私有只读指针mRefs */
       refs->addWeakRef(id);
       /* 调用weakref_impl类定义时实现的成员函数addWeakRef, 见下注释1*/
       refs->incWeak(id);
       /* 调用weakref_impl类的基类weakref_type成员函数incWeak, 见下注释2*/
      
       refs->addStrongRef(id);
       // 调用weakref_impl类定义时实现的成员函数addStrongRef, 见下注释1
       const int32_t c = android_atomic_inc(&refs->mStrong);
     /* 该函数实际将refs->mStrong值加1,也就是增加强引用计数值。但是返回值为refs->mStrong-1 */
       LOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
   #if PRINT_REFS
       LOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
   #endif
       if (c != INITIAL_STRONG_VALUE)  {
           return;
       }
     /* c = INITIAL_STRONG_VALUE, 第一个强引用产生的时候才会出现这个情况 */
       android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
     /* 返回值为INITIAL_STRONG_VALUE,refs->mStrong值变成1 */
       const_cast<RefBase*>(this)->onFirstRef();
   }
   
/************************注释1********************************/
void addWeakRef(const void* id)
{
    addRef(&mWeakRefs, id, mWeak);
}
void addStrongRef(const void* id)
{
    addRef(&mStrongRefs, id, mStrong);
}
addRef()是类weakref_impl的私有成员函数,addWeakRef()函数引用的是public成员变量,而addRef()函数可以操作私有数据。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwxxfd.html