Android中通过引用计数来实现智能指针,并且实现有强指针与弱指针。由对象本身来提供引用计数器,但是对象不会去维护引用计数器的值,而是由智能指针来管理。

要达到所有对象都可用引用计数器实现智能指针管理的目标,可以定义一个公共类,提供引用计数的方法,所有对象都去继承这个公共类,这样就可以实现所有对象都可以用引用计数来管理的目标,在Android中,这个公共类就是RefBase,同时还有一个简单版本LightRefBase。

RefBase作为公共基类提供了引用计数的方法,但是并不去维护引用计数的值,而是由两个智能指针来进行管理:sp(Strong Pointer)和wp(Weak Pointer),代表强引用计数和弱引用计数。 本篇博客我们就一起来学习RefBase,sp(Strong Pointer)和wp(Weak Pointer)。

轻量级引用计数的实现:LightRefBase

LightRefBase的实现很简单,只是内部保存了一个变量用于保存对象被引用的次数,并提供了两个函数用于增加或减少引用计数。

template <class T>class LightRefBase{public:    inline LightRefBase() : mCount(0) { }    inline void incStrong(const void* id) const {        android_atomic_inc(&mCount);    }    inline void decStrong(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 basetype;protected:    inline ~LightRefBase() { }private:    mutable volatile int32_t mCount;};

sp(Strong Pointer)

LightRefBase仅仅提供了引用计数的方法,具体引用数应该怎么管理,就要通过智能指针类来管理了,每当有一个智能指针指向对象时,对象的引用计数要加1,当一个智能指针取消指向对象时,对象的引用计数要减1,在C++中,当一个对象生成和销毁时会自动调用(拷贝)构造函数和析构函数,所以,对对象引用数的管理就可以放到智能指针的(拷贝)构造函数和析构函数中。Android提供了一个智能指针可以配合LightRefBase使用:sp,sp的定义如下:

template <typename T>class sp{public:    inline sp() : m_ptr(0) { }    sp(T* other);    sp(const sp& other);    template<typename U> sp(U* other);    template<typename U> sp(const sp& other);    ~sp();    // Assignment    sp& operator = (T* other);    sp& operator = (const sp& other);    template<typename U> sp& operator = (const sp& other);    template<typename U> sp& operator = (U* other);    //! Special optimization for use by ProcessState (and nobody else).    void force_set(T* other);    // Reset    void clear();    // Accessors    inline  T&      operator* () const  { return *m_ptr; }    inline  T*      operator-> () const { return m_ptr;  }    inline  T*      get() const         { return m_ptr; }    // Operators    COMPARE(==)    COMPARE(!=)    COMPARE(>)    COMPARE(<)    COMPARE(<=)    COMPARE(>=)private:      template<typename Y> friend class sp;    template<typename Y> friend class wp;    void set_pointer(T* ptr);    T* m_ptr;};

其中Accessors部分代码重载了*、->操作符使我们使用sp的时候就像使用真实的对象指针一样,可以直接操作对象的属性或方法,COMPARE是宏定义,用于重载关系操作符,由于对引用计数的控制主要是由(拷贝)构造函数和析构函数控制,所以忽略其他相关代码后,sp可以精简为如下形式(赋值操作符也省略掉了,构造函数省略相似的两个):

template <typename T>class sp{public:    inline sp() : m_ptr(0) { }    sp(T* other);    sp(const sp& other);    ~sp();private:      template<typename Y> friend class sp;    template<typename Y> friend class wp;    void set_pointer(T* ptr);    T* m_ptr;};

默认构造函数使智能指针不指向任何对象,sp(T* other)与sp(const sp& other)的实现如下:

template<typename T>sp::sp(T* other): m_ptr(other){    if (other) other->incStrong(this);}template<typename T>sp::sp(const sp& other): m_ptr(other.m_ptr){    if (m_ptr) m_ptr->incStrong(this);}

内部变量m_ptr指向实际对象,并调用实际对象的incStrong函数,T继承自LightRefBase,所以此处调用的是LightRefBase的incStrong函数,之后实际对象的引用计数加1。

当智能指针销毁的时候调用智能指针的析构函数:

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

调用实际对象即LightRefBase的decStrong函数,其实现如下:

inline void decStrong(const void* id) const {    if (android_atomic_dec(&mCount) == 1) {        delete static_cast<const T*>(this);    }}

android_atomic_dec返回mCount减1之前的旧值,如果返回1表示这次减过之后引用计数就是0了,就把对象delete掉。

RefBase

RefBase提供了更强大的引用计数的管理。

class RefBase{public:    void    incStrong(const void* id) const;    void    decStrong(const void* id) const;    void    forceIncStrong(const void* id) const;    //! DEBUGGING ONLY: Get current strong ref count.    int32_t getStrongCount() const;    class weakref_type    {    public:        RefBase refBase() const;        void    incWeak(const void* id);        void    decWeak(const void* id);        // acquires a strong reference if there is already one.        bool    attemptIncStrong(const void* id);        // acquires a weak reference if there is already one.        // This is not always safe. see ProcessState.cpp and BpBinder.cpp        // for proper use.        bool    attemptIncWeak(const void* id);        //! DEBUGGING ONLY: Get current weak ref count.        int32_t getWeakCount() const;        //! DEBUGGING ONLY: Print references held on object.        void    printRefs() const;        //! DEBUGGING ONLY: Enable tracking for this object.        // enable -- enable/disable tracking        // retain -- when tracking is enable, if true, then we save a stack trace        //           for each reference and dereference; when retain == false, we        //           match up references and dereferences and keep only the        //           outstanding ones.        void    trackMe(bool enable, bool retain);    };    weakref_type*   createWeak(const void* id) const;    weakref_type*   getWeakRefs() const;    // DEBUGGING ONLY: Print references held on object.    inline  void            printRefs() const { getWeakRefs()->printRefs(); }    // DEBUGGING ONLY: Enable tracking of object.    inline  void            trackMe(bool enable, bool retain)    {        getWeakRefs()->trackMe(enable, retain);    }    typedef RefBase basetype;protected:    RefBase();    virtual     ~RefBase();    //! Flags for extendObjectLifetime()    enum {        OBJECT_LIFETIME_STRONG  = 0x0000,        OBJECT_LIFETIME_WEAK    = 0x0001,        OBJECT_LIFETIME_MASK    = 0x0003    };    void    extendObjectLifetime(int32_t mode);    //! Flags for onIncStrongAttempted()    enum {        FIRST_INC_STRONG = 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);private:    friend class weakref_type;    class weakref_impl;    RefBase(const RefBase& o);    RefBase&        operator=(const RefBase& o);    weakref_impl* const mRefs;};

不同于LightRefBase中通过mCount保存对象被引用的次数,RefBase内部并没有使用一个变量来维护引用计数,而是通过一个weakref_impl *类型的成员mRefs来维护引用计数,并且同时提供了强引用计数和弱引用计数。weakref_impl继承于RefBase::weakref_type,代码比较多,不过大都是调试代码,由宏定义分开,Release是不包含调试代码的,去除这些代码后其定义为:

#define INITIAL_STRONG_VALUE (1<<28)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)     {     }     void addStrongRef(const void* /*id*/) { }     void removeStrongRef(const void* /*id*/) { }     void addWeakRef(const void* /*id*/) { }     void removeWeakRef(const void* /*id*/) { }     void printRefs() const { }     void trackMe(bool, bool) { } };

weakref_impl中的函数都是作为调试用,Release版的实现都是空的,成员变量分别表示强引用数、弱引用数、指向实际对象的指针与flag,flag可控制实际对象的生命周期,取值为0或RefBase中定义的枚举值。

RefBase提供了incStrong与decStrong函数用于控制强引用计数值,其弱引用计数值是由weakref_impl控制,强引用计数与弱引用数都保存在weakref_impl *类型的成员变量mRefs中。

RefBase同LightRefBase一样为对象提供了引用计数的方法,对引用计数的管理同样要由智能指针控制,由于RefBase同时实现了强引用计数与弱引用计数,所以就有两种类型的智能指针,sp(Strong Pointer)与wp(Weak Pointer)。

sp采用了模版,它的(拷贝)构造函数调用实际对象的incStrong函数,由于所有实际对象都是继承自RefBase,所以查看RefBase的incStrong。

void RefBase::incStrong(const void* id) const{    weakref_impl* const refs = mRefs;    refs->incWeak(id);    refs->addStrongRef(id);     //下面函数为原子加1操作,并返回旧值。所以c=0x1000000,而mStrong变为0x1000001    const int32_t c = android_atomic_inc(&refs->mStrong);    LOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);    if (c != INITIAL_STRONG_VALUE)  {    //如果c不是初始值,则表明这个对象已经被强引用过一次了        return;    }    //下面函数为原子加1操作,并返回旧值。所以c=0x1000000,而mStrong变为0x1000001    android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);     /*   如果是第一次引用,则调用onFirstRef,这个函数很重要,派生类可以重载这个函数,完成一些   初始化工作。 */    refs->mBase->onFirstRef();}

addStrong的函数体为空,incStrong函数内部首先调用成员变量mRefs的incWeak函数将弱引用数加1,然后再将强引用数加1,由于android_atomic_inc返回变量的旧值,所以如果其不等于INITIAL_STRONG_VALUE就直接返回,则则是第一次由强智能指针(sp)引用,将其减去INITIAL_STRONG_VALUE后变成1,然后调用对象的onFirstRef。

成员变量mRefs是在对象的构造函数中初始化的:

RefBase::RefBase()    : mRefs(new weakref_impl(this)){}

weakrel_impl的incWeak继承自父类weakrel_type的incWeak:

void RefBase::weakref_type::incWeak(const void* id){    weakref_impl* const impl = static_cast    impl->addWeakRef(id);    const int32_t c = android_atomic_inc(&impl->mWeak);    LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);}

addWeakRef实现同样为空,所以只是将弱引用计数加1。所以当对象被sp引用后,强引用计数与弱引用计数会同时加1。

当sp销毁时其析构函数调用对象即RefBase的decStrong函数:

void RefBase::decStrong(const void* id) const{     weakref_impl* const refs = mRefs;     refs->removeStrongRef(id);     const int32_t c = android_atomic_dec(&refs->mStrong);    //注意,此时强弱引用计数都是1,下面函数调用的结果是c=1,强引用计数为0    if (c == 1) {     //调用onLastStrongRef,表明强引用计数减为0,对象有可能被delete        const_cast(this)->onLastStrongRef(id);         //mFlags为0,所以会通过delete this把自己干掉         //注意,此时弱引用计数仍为1         if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {             delete this;         }    }     refs->removeWeakRef(id);     refs->decWeak(id); }

decStrong中将强引用数与弱引用数同时减1,如果这是最后一个强引用的话,会调用对象的onLastStrongRef,并且判断成员变量mRefs的成员变量mFlags来决定是否在对象的强引用数为0时释放对象。

mFlags可以为0或以下枚举值:

enum {       OBJECT_LIFETIME_WEAK    =  0x0001,       OBJECT_LIFETIME_FOREVER = 0x0003};

注意:FOREVER的值是3,二进制表示是B11,而WEAK的二进制是B01,也就是说FOREVER包括了WEAK的情况。

mFlags的值可以通过extendObjectLifetime函数改变:

void RefBase::extendObjectLifetime(int32_t mode){    android_atomic_or(mode, &mRefs->mFlags);}

OBJECT_LIFETIME_FOREVER包含OBJECT_LIFETIME_WEAK(位运算中其二进制11包含01),所以当

refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK

为true时表示mFlags为0,实际对象的生命周期受强引用数控制,所以在强引用数为0时delete this,否则实际对象的生命周期就由弱引用数控制。

再来看decWeak:

void RefBase::weakref_type::decWeak(const void* id) {     weakref_impl* const impl = static_cast(this);     impl->removeWeakRef(id);     const int32_t c = android_atomic_dec(&impl->mWeak);     if (c != 1) return;     if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {         if (impl->mStrong == INITIAL_STRONG_VALUE)             delete impl->mBase;         else {             delete impl;         }     } else {         impl->mBase->onLastWeakRef(id);         if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {             delete impl->mBase;         }     } }

将弱引用数减1,若减1后不为0直接返回,否则判断
(impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK

实际对象生命周期被强引用数控制,接下来判断:
mpl->mStrong == INITIAL_STRONG_VALUE

如果判断为true表示对象只被弱引用引用过,现在弱引用数为0,直接删除实际对象。

如果判断为false,表示对象曾经被强引用引用过,但现在强引用为变为0了(因为增加或减小强引用数时一定同时增加或减小弱引用数,所以弱引用数为0时,强引用数一定为0),弱引用数为0了,直接释放mRefs,而实际对象由于受强引用数控制,已经在RefBase::decStrong中被delete了。

若判断结果为false:
判断mFlgs是否是OBJECT_LIFETIME_FOREVER,如果是,什么都不作由用户自己控制对象的生命周期,否则,实际对象的生命周期受弱引用数控制,现在弱引用数为0,delete实际对象。

wp(Weak Pointer)

定义如下:

template <typename T>class wp{public:    typedef typename RefBase::weakref_type weakref_type;    inline wp() : m_ptr(0) { }    wp(T* other);    wp(const wp& other);    wp(const sp& other);    template<typename U> wp(U* other);    template<typename U> wp(const sp& other);    template<typename U> wp(const wp& other);    ~wp();    // Assignment    wp& operator = (T* other);    wp& operator = (const wp& other);    wp& operator = (const sp& other);    template<typename U> wp& operator = (U* other);    template<typename U> wp& operator = (const wp& other);    template<typename U> wp& operator = (const sp& other);    void set_object_and_refs(T* other, weakref_type* refs);    // promotion to sp    sp promote() const;    // Reset    void clear();    // Accessors    inline  weakref_type* get_refs() const { return m_refs; }    inline  T* unsafe_get() const { return m_ptr; }    // Operators    COMPARE(==)    COMPARE(!=)    COMPARE(>)    COMPARE(<)    COMPARE(<=)    COMPARE(>=)private:    template<typename Y> friend class sp;    template<typename Y> friend class wp;    T*              m_ptr;    weakref_type*   m_refs;};

同sp一样,m_ptr指向实际对象,但wp还有一个成员变量m_refs。

template<typename T>wp::wp(T* other)    : m_ptr(other){    if (other) m_refs = other->createWeak(this);}template<typename T>wp::wp(const wp& other)    : m_ptr(other.m_ptr), m_refs(other.m_refs){    if (m_ptr) m_refs->incWeak(this);}RefBase::weakref_type* RefBase::createWeak(const void* id) const{    mRefs->incWeak(id);    return mRefs;}

可以看到,wp的m_refs就是RefBase即实际对象的mRefs。
wp析构的时候减少弱引用计数:

template<typename T>wp::~wp(){    if (m_ptr) m_refs->decWeak(this);}

由于弱指针没有重载*与->操作符,所以不能直接操作指向的对象,虽然有unsafe_get函数,但像名字所示的,不建议使用,直接使用实际对象指针的话就没必要用智能指针了。

因为弱指针不能直接操作对象,所以要想操作对象的话就要将其转换为强指针,即wp::promote方法:

templateT>sp<T> wp<T>::promote() const{    return sp<T>(m_ptr, m_refs);}templateT>sp<T>::sp(T* p, weakref_type* refs)    : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0){}

是否能从弱指针生成一个强指针关键是看refs->attemptIncStrong,看其定义:

bool RefBase::weakref_type::attemptIncStrong(const void* id){    incWeak(id);    weakref_impl* const impl = static_cast<weakref_impl*>(this);    int32_t curCount = impl->mStrong;    LOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",               this);    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {        if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {            break;        }        curCount = impl->mStrong;    }    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {        bool allow;        if (curCount == INITIAL_STRONG_VALUE) {            // Attempting to acquire first strong reference...  this is allowed            // if the object does NOT have a longer lifetime (meaning the            // implementation doesn't need to see this), or if the implementation            // allows it to happen.            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK                  || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);        } else {            // Attempting to revive the object...  this is allowed            // if the object DOES have a longer lifetime (so we can safely            // call the object with only a weak ref) and the implementation            // allows it to happen.            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK                  && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);        }        if (!allow) {            decWeak(id);            return false;        }        curCount = android_atomic_inc(&impl->mStrong);        // If the strong reference count has already been incremented by        // someone else, the implementor of onIncStrongAttempted() is holding        // an unneeded reference.  So call onLastStrongRef() here to remove it.        // (No, this is not pretty.)  Note that we MUST NOT do this if we        // are in fact acquiring the first reference.        if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {            impl->mBase->onLastStrongRef(id);        }    }    impl->addWeakRef(id);    impl->addStrongRef(id);#if PRINT_REFS    LOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);#endif    if (curCount == INITIAL_STRONG_VALUE) {        android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);        impl->mBase->onFirstRef();    }    return true;}

首先通过incWeak将弱引用数加1(被强指针sp引用会导致强引用数和弱引用数同时加1),然后:

int32_t curCount = impl->mStrong;while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {    if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {        break;    }    curCount = impl->mStrong;}

如果之前已经有强引用,直接将强引用数加1,android_atomic_cmpxchg表示如果impl->mStrong的值为curCount,则把impl->mString的值改为curCount+1,此处用while循环是防止其他线程已经增加了强引用数。
接下来:
if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE)
表示对象目前没有强引用,这就要判断对象是否存在了。
如果curCount == INITIAL_STRONG_VALUE,表示对象没有被sp引用过。接下来判断:

allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK    || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);

表示:如果对象的生命周期只受强引用控制,对象一定存在,要有强引用才可以管理对象的释放,所以一定会允许生成强引用;如果对象的生命周期受弱引用控制,调用对象的onIncStrongAttempted试图增加强引用,由于此时在弱引用中,弱引用一定不为0,对象也一定存在,调用onIncStrongAttempted的意图是因为类的实现者可能不希望用强引用引用对象。在RefBase中onIncStrongAttempted默认返回true:

bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id){    return (flags&FIRST_INC_STRONG) ? true : false;}

如果curCount <= 0(只会等于0),表示对象强引用数经历了INITIAL_STRONG_VALUE –>大于0 –> 0,接下来就要判断:

allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK    && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);

如果对象的生命周期受强引用数控制,那么由于曾被sp引用过,现在强引用数又为0,对象就已经被delete了,所以就不能生成强引用,否则如果对象的生命周期受弱引用数控制,就通过onIncStrongAttempted看类的实现者是否希望当对象的强引用数变为0时可以再次被强引用引用。

if (!allow) {    decWeak(id);    return false;}

如果allow为false表示不能从弱引用生成强引用,就要调用decWeak将弱引用减1(因为在promote入口先将弱引用加了1),然后返回false表示生成强引用失败。

if (curCount == INITIAL_STRONG_VALUE) {    android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);    impl->mBase->onFirstRef();}

最后,如果curCount == INITIAL_STRONG_VALUE表示第一次被sp引用,调用对象的onFirstRef函数。

总结

RefBase内部有一个指针指向实际对象,有一个weakref_impl类型的指针保存对象的强/弱引用计数、对象生命周期控制。

sp只有一个成员变量,用来保存实际对象,但这个实际对象内部已包含了weakref_impl *对象用于保存实际对象的引用计数。sp 管理一个对象指针时,对象的强、弱引用数同时加1,sp销毁时,对象的强、弱引用数同时减1。

wp中有两个成员变量,一个保存实际对象,另一个是weakref_impl *对象。wp管理一个对象指针时,对象的弱引用计数加1,wp销毁时,对象的弱引用计数减1。

weakref_impl中包含一个flag用于决定对象的生命周期是由强引用数控制还是由弱引用数控制:

1.当flag为0时,实际对象的生命周期由强引用数控制,weakref_impl *对象由弱引用数控制。

2.当flag为OBJECT_LIFETIME_WEAK时,实际对象的生命周期受弱引用数控制。

3.当flag为OBJECT_LIFETIME_FOREVER时,实际对象的生命周期由用户控制。

可以用extendObjectLifetime改变flag的值。

更多相关文章

  1. android 源码设计模式之--代理模式(Proxy)
  2. android,内存优化详解 .
  3. Android中的引用传递和值传递分析(Java)
  4. Android(安卓)内功心法(1.7)——android常用设计模式之组合(合成
  5. Android(安卓)用户界面---拖放(Drag and Drop)(一)
  6. Android(安卓)将Activity打成jar包供第三方调用
  7. android 将res内图片文件通过Bitmap对象存到手机本地中
  8. Android开发自己的桌面应用,Luancher原来也是如此简单(上)
  9. Android(安卓)手势操作GestureDetector

随机推荐

  1. Android(安卓)Junit单元测试
  2. Android arm linux kernel启动流程(一)
  3. 探究android:largeHeap
  4. Debug Android and Linux suspend and re
  5. Android重要类学习之——Activity
  6. Android 根文件系统启动过程(init进程 详
  7. Android实现图片选择器功能
  8. 18、不同平台版本
  9. 浅析Android事件分发
  10. Android 音视频深入 七 学习之路的总结和