zoukankan      html  css  js  c++  java
  • Android结构分析Android智能指针(两)

    笔者:刘蒿羽 

    博客:http://blog.csdn.net/liuhaoyutz

    Android版本号:4.4.2

    在上一篇文章中,我们分析了Android智能指针中的强指针sp,本文我们来分析弱指针wp。为什么须要弱指针wp呢?我们来考虑以下一种场景:有两个类CParent和CChild。CParent类中有一个智能指针指向CChild对象。CChild类中有一个智能指针指向CParent对象

    class CParent :public LightRefBase<CParent>
    {
           ……
           sp<CChild> spc;
           ……
    }
     
    class CChild :public LightRefBase<CChild>
    {
           ……
           sp<CParent> spp
           ……
    }


    分别创建CParent类对象parent和CChild对象child,让parent.spc指向child。让child.spp指向parent。这样。parent和child的引用计数器的值都是1,当要释放parent和child时,由于它们的引用计数器都是1,而且系统一次仅仅能析构一个对象,这就造成一种死锁,无法析构parent和child对象中的不论什么一个。

    这样,也相同造成内存泄漏的问题。为此。Android引入了弱指针wp,定义在frameworks/rs/cpp/util/RefBase.h文件里,我们先来看wp的定义:

    197template<typename T>
    198class wp
    199{
    200public:
    201    typedef typename RefBase::weakref_typeweakref_type;
    202
    203    inline wp() : m_ptr(0) { }
    204
    205    wp(T* other);
    206    wp(const wp<T>& other);
    207    wp(const sp<T>& other);
    208    template<typename U> wp(U* other);
    209    template<typename U> wp(constsp<U>& other);
    210    template<typename U> wp(constwp<U>& other);
    211
    212    ~wp();
    213
    214    // Assignment
    215
    216    wp& operator = (T* other);
    217    wp& operator = (const wp<T>&other);
    218    wp& operator = (const sp<T>&other);
    219
    220    template<typename U> wp& operator= (U* other);
    221    template<typename U> wp& operator= (const wp<U>& other);
    222    template<typename U> wp& operator= (const sp<U>& other);
    223
    224    void set_object_and_refs(T* other,weakref_type* refs);
    225
    226    // promotion to sp
    227
    228    sp<T> promote() const;
    229
    230    // Reset
    231
    232    void clear();
    233
    234    // Accessors
    235
    236    inline weakref_type* get_refs() const { return m_refs; }
    237
    238    inline T* unsafe_get() const { return m_ptr; }
    239
    240    // Operators
    241
    242    COMPARE_WEAK(==)
    243    COMPARE_WEAK(!=)
    244    COMPARE_WEAK(>)
    245    COMPARE_WEAK(<)
    246    COMPARE_WEAK(<=)
    247    COMPARE_WEAK(>=)
    248
    249    inline bool operator == (constwp<T>& o) const {
    250        return (m_ptr == o.m_ptr) &&(m_refs == o.m_refs);
    251    }
    252    template<typename U>
    253    inline bool operator == (constwp<U>& o) const {
    254        return m_ptr == o.m_ptr;
    255    }
    256
    257    inline bool operator > (constwp<T>& o) const {
    258        return (m_ptr == o.m_ptr) ? (m_refs> o.m_refs) : (m_ptr > o.m_ptr);
    259    }
    260    template<typename U>
    261    inline bool operator > (constwp<U>& o) const {
    262        return (m_ptr == o.m_ptr) ? (m_refs> o.m_refs) : (m_ptr > o.m_ptr);
    263    }
    264
    265    inline bool operator < (constwp<T>& o) const {
    266        return (m_ptr == o.m_ptr) ? (m_refs< o.m_refs) : (m_ptr < o.m_ptr);
    267    }
    268    template<typename U>
    269    inline bool operator < (constwp<U>& o) const {
    270        return (m_ptr == o.m_ptr) ? (m_refs< o.m_refs) : (m_ptr < o.m_ptr);
    271    }
    272                         inline bool operator!= (const wp<T>& o) const { return m_refs != o.m_refs; }
    273    template<typename U> inline booloperator != (const wp<U>& o) const { return !operator == (o); }
    274                         inline bool operator<= (const wp<T>& o) const { return !operator > (o); }
    275    template<typename U> inline booloperator <= (const wp<U>& o) const { return !operator > (o); }
    276                         inline bool operator>= (const wp<T>& o) const { return !operator < (o); }
    277    template<typename U> inline booloperator >= (const wp<U>& o) const { return !operator < (o); }
    278
    279private:
    280    template<typename Y> friend class sp;
    281    template<typename Y> friend class wp;
    282
    283    T*              m_ptr;
    284    weakref_type*   m_refs;
    285};


    能够看到,弱指针wp与强指针sp基本内容是类似的,可是又有例如以下差别:

    1、wp多了一个weakref_type类型的指针变量m_refs。

    2、wp有一个promote函数,用于将wp升级为sp。

    3、另一点重要差别。后面我们会看到,wp目标对象的父类是RefBase而不是LightRefBase。

    Android规定:

    1、当一个对象强引用计数为0时,不论弱引用计数是否为0。都能够释放该对象。

    2、我们不能通过弱指针wp直接操作引用对象,假设要操作,必须先将wp通过promote函数升级为sp才行。

    在frameworks/rs/cpp/util/RefBase.h文件里。RefBase类定义例如以下:

    65class RefBase
     66{
     67public:
     68            void            incStrong(const void* id) const;
     69            void            decStrong(const void* id) const;
     70
     71            void            forceIncStrong(const void* id)const;
     72
     73            //! DEBUGGING ONLY: Get currentstrong ref count.
     74            int32_t         getStrongCount() const;
     75
     76    class weakref_type
     77    {
     78    public:
     79        RefBase*            refBase() const;
     80
     81        void                incWeak(const void* id);
     82        void                decWeak(const void* id);
     83
     84        // acquires a strong reference if thereis already one.
     85        bool                attemptIncStrong(const void*id);
     86
     87        // acquires a weak reference if thereis already one.
     88        // This is not always safe. seeProcessState.cpp and BpBinder.cpp
     89        // for proper use.
     90        bool                attemptIncWeak(const void* id);
     91
     92        //! DEBUGGING ONLY: Get current weakref count.
     93        int32_t             getWeakCount() const;
     94
     95        //! DEBUGGING ONLY: Print referencesheld on object.
     96        void                printRefs() const;
     97
     98        //! DEBUGGING ONLY: Enable tracking forthis object.
     99        // enable -- enable/disable tracking
    100        // retain -- whentracking is enable, if true, then we save a stack trace
    101        //           for each reference and dereference;when retain == false, we
    102        //           match up references and dereferencesand keep only the
    103        //           outstanding ones.
    104
    105        void                trackMe(bool enable, boolretain);
    106    };
    107
    108            weakref_type*   createWeak(const void* id) const;
    109
    110            weakref_type*   getWeakRefs() const;
    111
    112            //! DEBUGGING ONLY:Print references held on object.
    113    inline  void           printRefs() const {getWeakRefs()->printRefs(); }
    114
    115            //! DEBUGGING ONLY:Enable tracking of object.
    116    inline  void            trackMe(bool enable, bool retain)
    117    {
    118       getWeakRefs()->trackMe(enable, retain);
    119    }
    120
    121    typedef RefBase basetype;
    122
    123protected:
    124                           RefBase();
    125    virtual                 ~RefBase();
    126
    127    //! Flags forextendObjectLifetime()
    128    enum {
    129       OBJECT_LIFETIME_STRONG  = 0x0000,
    130        OBJECT_LIFETIME_WEAK    = 0x0001,
    131       OBJECT_LIFETIME_MASK    = 0x0001
    132    };
    133
    134            void            extendObjectLifetime(int32_t mode);
    135
    136    //! Flags foronIncStrongAttempted()
    137    enum {
    138        FIRST_INC_STRONG =0x0001
    139    };
    140
    141    virtual void            onFirstRef();
    142    virtual void            onLastStrongRef(const void* id);
    143    virtual bool            onIncStrongAttempted(uint32_tflags, const void* id);
    144    virtual void            onLastWeakRef(const void* id);
    145
    146private:
    147    friend classReferenceMover;
    148    static voidmoveReferences(void* d, void const* s, size_t n,
    149            constReferenceConverterBase& caster);
    150
    151private:
    152    friend class weakref_type;
    153    class weakref_impl;
    154
    155                           RefBase(const RefBase& o);
    156            RefBase&        operator=(const RefBase& o);
    157
    158        weakref_impl* constmRefs;
    159};


    与LightRefBase给sp指向的对象提供引用计数器类似,RefBase用于给被wp指向的对象提供引用计数器功能。LightRefBase的引用计数器详细实现为一个整数LightRefBase.mCount。可是我们在RefBase类中并没有一个相应的整数作为引用计数器,那么RefBase的引用计数器是谁呢?实际上是RefBase.mRefs,它是weakref_impl类的指针。

    weakref_impl类中有两个成员变量mStrong和mWeak,即强引用计数和弱引用计数。RefBase.mRefs是在RefBase的构造函数中进行初始化的:

    579RefBase::RefBase()
    580    : mRefs(newweakref_impl(this))
    581{
    582}


    580行,new一个weakref_impl对象,赋值给RefBase.mRefs。

    RefBase::weakref_impl定义在system/core/libutils/RefBase.cpp文件里,例如以下所看到的:

    60class RefBase::weakref_impl : public RefBase::weakref_type
     61{
     62public:
     63    volatile int32_t    mStrong;
     64    volatile int32_t    mWeak;
     65    RefBase* const      mBase;
     66    volatile int32_t    mFlags;
     67
     68#if !DEBUG_REFS
     69
     70    weakref_impl(RefBase* base)
     71        : mStrong(INITIAL_STRONG_VALUE)
     72        , mWeak(0)
     73        , mBase(base)
     74        , mFlags(0)
     75    {
     76    }
     77
     78    void addStrongRef(const void* /*id*/) { }
     79    void removeStrongRef(const void* /*id*/) {}
     80    void renameStrongRefId(const void*/*old_id*/, const void* /*new_id*/) { }
     81    void addWeakRef(const void* /*id*/) { }
     82    void removeWeakRef(const void* /*id*/) { }
     83    void renameWeakRefId(const void*/*old_id*/, const void* /*new_id*/) { }
     84    void printRefs() const { }
     85    void trackMe(bool, bool) { }
     86
     87#else
        ……
        ……
    313#endif
    314};


    weakref_impl类的定义内容尽管非常长。可是从87行到最后都是用于debug调试,能够忽略。

    78-85行定义的函数都没有详细实现。所以也能够忽略。

    70-76行,构造函数中对mStrong、mWeak、mBase、mFlags进行初始化。mStrong被初始化为INITIAL_STRONG_VALUE,该宏定义在system/core/libutils/RefBase.cpp文件里:

    56#define INITIAL_STRONG_VALUE (1<<28)

    看起来weakref_impl类仅仅是提供了mStrong、mWeak、mBase、mFlags四个成员变量,并进行初始化,没有实现什么功能,可是要注意weakref_impl继承自RefBase::weakref_type类。

    和分析sp时一样,我们考虑要让wp指向一个对象(该对象的弱引用计数应该加1),可能通过wp的构造函数,也可能通过重载的“=”赋值运算符。我们来看wp的构造函数,例如以下:

    295template<typename T>
    296wp<T>::wp(T* other)
    297    : m_ptr(other)
    298{
    299    if (other) m_refs =other->createWeak(this);
    300}


    再来看重载的赋值运算符,例如以下:

    350template<typename T>
    351wp<T>& wp<T>::operator = (T* other)
    352{
    353    weakref_type* newRefs =
    354        other ?

    other->createWeak(this) : 0; 355 if (m_ptr)m_refs->decWeak(this); 356 m_ptr = other; 357 m_refs = newRefs; 358 return *this; 359}



    注意。这两个函数都没有直接添加对象other的弱引用计数(即RefBase.mRefs->mWeak),实际上,是通过调用other->createWeak(this)添加other的弱引用计数。该函数定义在system/core/libutils/RefBase.cpp文件里:

    568RefBase::weakref_type* RefBase::createWeak(const void* id) const
    569{
    570    mRefs->incWeak(id);
    571    return mRefs;
    572}


    570行调用mRefs即weakref_impl类的inWeak函数。给弱引用计数加1。

    571行,返回RefBase.mRefs,注意它是weakref_impl类型指针。

    而在wp构造函数和重载的赋值运算符中,createWeak函数的返回值赋值给wp.m_refs。这样。通过wp.m_refs和other.mRefs都能够訪问到引用计数器weakref_impl。

    该函数定义例如以下:

    387void RefBase::weakref_type::incWeak(const void* id)
    388{
    389    weakref_impl* const impl =static_cast<weakref_impl*>(this);
    390    impl->addWeakRef(id);
    391    const int32_t c =android_atomic_inc(&impl->mWeak);
    392    ALOG_ASSERT(c >= 0,"incWeak called on %p after last weak ref", this);
    393}


    390行,addWeakRef函数是空函数。没有实现。

    391行。调用android_atomic_inc。给弱引用计数mWeak加1。

    分析到这里。我们就清楚如何给弱引用计数加1的了。

    再来看wp的析构函数:

    344template<typename T>
    345wp<T>::~wp()
    346{
    347    if (m_ptr)m_refs->decWeak(this);
    348}


    其调用的是m_refs即weakref_type.decWeak函数,该函数定义例如以下:

    396void RefBase::weakref_type::decWeak(const void* id)
    397{
    398    weakref_impl* const impl =static_cast<weakref_impl*>(this);
    399    impl->removeWeakRef(id);
    400    const int32_t c =android_atomic_dec(&impl->mWeak);
    401    ALOG_ASSERT(c >= 1,"decWeak called on %p too many times", this);
    402    if (c != 1) return;
    403
    404    if((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
    405        // This is the regularlifetime case. The object is destroyed
    406        // when the last strongreference goes away. Since weakref_impl
    407        // outlive the object,it is not destroyed in the dtor, and
    408        // we'll have to do ithere.
    409        if (impl->mStrong ==INITIAL_STRONG_VALUE) {
    410            // Special case: wenever had a strong reference, so we need to
    411            // destroy theobject now.
    412            deleteimpl->mBase;
    413        } else {
    414            // ALOGV("Freeingrefs %p of old RefBase %p
    ", this, impl->mBase);
    415            delete impl;
    416        }
    417    } else {
    418        // less common case:lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
    419       impl->mBase->onLastWeakRef(id);
    420        if ((impl->mFlags&OBJECT_LIFETIME_MASK)== OBJECT_LIFETIME_WEAK) {
    421            // this is theOBJECT_LIFETIME_WEAK case. The last weak-reference
    422            // is gone, we candestroy the object.
    423            deleteimpl->mBase;
    424        }
    425    }
    426}


    400行。调用android_atomic_dec减小弱引用计数。

    402行,假设弱引用计数不为0,则直接退出。

    404-425行,依据是否是强引用,分别进行释放工作。

    假设用一个sp指针指向一个继承了RefBase的类对象时。会发生什么呢?从上一篇分析sp的文章中,我们知道此时会调用RefBase.incStrong函数。该函数定义例如以下:

    318void RefBase::incStrong(const void* id) const
    319{
    320    weakref_impl* const refs =mRefs;
    321    refs->incWeak(id);
    322
    323    refs->addStrongRef(id);
    324    const int32_t c =android_atomic_inc(&refs->mStrong);
    325    ALOG_ASSERT(c > 0,"incStrong() called on %p after last strong ref", refs);
    326#if PRINT_REFS
    327    ALOGD("incStrong of %pfrom %p: cnt=%d
    ", this, id, c);
    328#endif
    329    if (c !=INITIAL_STRONG_VALUE)  {
    330        return;
    331    }
    332
    333   android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
    334   refs->mBase->onFirstRef();
    335}


    320行,mRefs就是该RefBase相应的计数器。

    321行,添加弱引用计数。

    323行,addStrongRef是一个空函数。

    324行,调用android_atomic_inc添加强引用计数。即weakref_impl.mStrong。

    329-331行。假设不是第一次被强指针引用。直接返回。

    333行。假设是第一次被强指针引用。mStrong的值还须要减去INITIAL_STRONG_VALUE。其值才为1。

    334行。refs->mBase->onFirstRef()是一个空函数。

    强引用被释放时,会调用decStrong函数:

    337void RefBase::decStrong(const void* id) const
    338{
    339    weakref_impl* const refs =mRefs;
    340   refs->removeStrongRef(id);
    341    const int32_t c =android_atomic_dec(&refs->mStrong);
    342#if PRINT_REFS
    343    ALOGD("decStrong of %pfrom %p: cnt=%d
    ", this, id, c);
    344#endif
    345    ALOG_ASSERT(c >= 1,"decStrong() called on %p too many times", refs);
    346    if (c == 1) {
    347       refs->mBase->onLastStrongRef(id);
    348        if((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
    349            delete this;
    350        }
    351    }
    352    refs->decWeak(id);
    353}


    339行。mRefs就是该RefBase相应的计数器。

    340行,removeStrongRef函数是一个空函数。

    341行,将强引用计数mStrong减1。

    346行,当强引用所有被释放后,发行对象。

    352行。转让decWeak功能弱引用计数1。

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    H5调用Android播放视频
    JavaScript调Java
    Java调用JavaScript
    python的下载和安装
    s5_day1作业
    s5_day2作业
    pycharm激活(转)
    for…else和while…else
    小练习
    09 grep、正则表达式和sed
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4839557.html
Copyright © 2011-2022 走看看