Android轻量级指针 强指针 弱指针

这3种指针,在这篇博客http://blog.csdn.net/luoshengyang/article/details/6786239中讲的比较详细。我们这边自己再重新梳理,总结下。

这3种指针都是基于计数器的原理完成的。


一、轻量级指针

我们先来看第一个,LightRefBase类的实现在system/core/include/utils/Refbase.h中实现的

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:
    friend class ReferenceMover;
    inline static void renameRefs(size_t n, const ReferenceRenamer& renamer) { }
    inline static void renameRefId(T* ref,
            const void* old_id, const void* new_id) { }

private:
    mutable volatile int32_t mCount;
};

这个类的mCount变量就是一个计数的功能,incStrong和decStrong分别计数加1 减1.这里都是使用的原子操作。这两个函数都是给智能指针调用的,当调用decStrong函数时,当计数为1时,直接就delete这个对象了。这里delete this,因为对象使用的时候肯定要继承LightRefBase这个类,所有这里delete this就是delete最后的对象。

而上面说的智能指针,这里说的就是sp了,在system/core/include/utils/StrongPoint.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();

    // Assignment

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

    //! 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;
};

先看看其两个构造函数,m_ptr就是指的实际的对象,构造函数中直接调用对象的incStrong函数,另一个构造函数是以sp对象为参数的。

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

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

再来看析构函数,就是调用了实际对象的decStrong函数。

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

轻量级指针原理很简单,使用智能指针sp,sp的构造函数中调用对象的incStrong函数,析构函数中调用对象的decStrong函数。

下面我们举个例子:

#include <stdio.h>  
#include <utils/RefBase.h>  
  
using namespace android;  
  
class LightClass : public LightRefBase<LightClass>  
{  
public:  
        LightClass()  
        {  
                printf("Construct LightClass Object.");  
        }  
  
        virtual ~LightClass()  
        {  
                printf("Destory LightClass Object.");  
        }  
};  
  
int main(int argc, char** argv)  
{  
        LightClass* pLightClass = new LightClass();  
        sp<LightClass> lpOut = pLightClass;  
  
        printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());  
  
        {  
                sp<LightClass> lpInner = lpOut;  
  
                printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());  
        }  
  
        printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());  
  
        return 0;  
}  

我们创建一个自己的类LightClass,继承了LightRefBase模板类,这样类LightClass就具有引用计数的功能了。在main函数里面,我们首先new一个LightClass对象,然后把这个对象赋值给智能指针lpOut,这时候通过一个printf语句来将当前对象的引用计数值打印出来,从前面的分析可以看出,如果一切正常的话,这里打印出来的引用计数值为1。接着,我们又在两个大括号里面定义了另外一个智能指针lpInner,它通过lpOut间接地指向了前面我们所创建的对象,这时候再次将当前对象的引用计数值打印出来,从前面 的分析也可以看出,如果一切正常的话,这里打印出来的引用计数值应该为2。程序继承往下执行,当出了大括号的范围的时候,智能指针对象lpInner就被析构了,从前面的分析可以知道,智能指针在析构的时候,会减少当前对象的引用计数值,因此,最后一个printf语句打印出来的引用计数器值应该为1。当main函数执行完毕后,智能指针lpOut也会被析构,被析构时,它会再次减少当前对象的引用计数,这时候,对象的引用计数值就为0了,于是,它就会被delete了。

下面是Android.mk文件

LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
LOCAL_MODULE_TAGS := optional  
LOCAL_MODULE := lightpointer  
LOCAL_SRC_FILES := lightpointer.cpp  
LOCAL_SHARED_LIBRARIES := \  
        libcutils \  
        libutils  
include $(BUILD_EXECUTABLE)  

我们来看下结果:

Construct LightClass Object.  
Light Ref Count: 1.  
Light Ref Count: 2.  
Light Ref Count: 1.  
Destory LightClass Object. 


二、强指针

强指针所用的智能指针还是sp,但是计数器类是RefBase而不是LightRefBase,这个类就复杂多了。

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    = 0x0001
    };
    
            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);

private:
    friend class ReferenceMover;

    static void renameRefs(size_t n, const ReferenceRenamer& renamer);

    static void renameRefId(weakref_type* ref,
            const void* old_id, const void* new_id);

    static void renameRefId(RefBase* ref,
            const void* old_id, const void* new_id);

        weakref_impl* const mRefs;
};

       RefBase类和LightRefBase类一样,提供了incStrong和decStrong成员函数来操作它的引用计数器;而RefBase类与LightRefBase类最大的区别是,它不像LightRefBase类一样直接提供一个整型值(mutable volatile int32_t mCount)来维护对象的引用计数,前面我们说过,复杂的引用计数技术同时支持强引用计数和弱引用计数,在RefBase类中,这两种计数功能是通过其成员变量mRefs来提供的。


2.1 weakref_impl类

        RefBase类的成员变量mRefs的类型为weakref_impl指针,它实现也在RefBase.cpp文件中。我们看weakref_impl这个类看着很复杂,其实我们注意有一个宏DEBUG_REFS,当是release版本的时候,这个类所有的函数都是空实现,而是debug版本的时候这些函数才会实现,所以我们就不关注这些函数了。

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

    void addStrongRef(const void* /*id*/) { }
    void removeStrongRef(const void* /*id*/) { }
    void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void addWeakRef(const void* /*id*/) { }
    void removeWeakRef(const void* /*id*/) { }
    void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void printRefs() const { }
    void trackMe(bool, bool) { }

#else

    weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)
        , mWeak(0)
        , mBase(base)
        , mFlags(0)
        , mStrongRefs(NULL)
        , mWeakRefs(NULL)
        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
        , mRetain(false)
    {
    }
    ......

    void addStrongRef(const void* id) {
        //ALOGD_IF(mTrackEnabled,
        //        "addStrongRef: RefBase=%p, id=%p", mBase, id);
        addRef(&mStrongRefs, id, mStrong);
    }

    void removeStrongRef(const void* id) {
        //ALOGD_IF(mTrackEnabled,
        //        "removeStrongRef: RefBase=%p, id=%p", mBase, id);
        if (!mRetain) {
            removeRef(&mStrongRefs, id);
        } else {
            addRef(&mStrongRefs, id, -mStrong);
        }
    }

    void renameStrongRefId(const void* old_id, const void* new_id) {
        //ALOGD_IF(mTrackEnabled,
        //        "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
        //        mBase, old_id, new_id);
        renameRefsId(mStrongRefs, old_id, new_id);
    }

    void addWeakRef(const void* id) {
        addRef(&mWeakRefs, id, mWeak);
    }

    void removeWeakRef(const void* id) {
        if (!mRetain) {
            removeRef(&mWeakRefs, id);
        } else {
            addRef(&mWeakRefs, id, -mWeak);
        }
    }

    void renameWeakRefId(const void* old_id, const void* new_id) {
        renameRefsId(mWeakRefs, old_id, new_id);
    }
    ......

    void addRef(ref_entry** refs, const void* id, int32_t mRef)
    {
        if (mTrackEnabled) {
            AutoMutex _l(mMutex);

            ref_entry* ref = new ref_entry;
            // Reference count at the time of the snapshot, but before the
            // update.  Positive value means we increment, negative--we
            // decrement the reference count.
            ref->ref = mRef;
            ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
            ref->stack.update(2);
#endif
            ref->next = *refs;
            *refs = ref;
        }
    }

    void removeRef(ref_entry** refs, const void* id)
    {
        if (mTrackEnabled) {
            AutoMutex _l(mMutex);
            
            ref_entry* const head = *refs;
            ref_entry* ref = head;
            while (ref != NULL) {
                if (ref->id == id) {
                    *refs = ref->next;
                    delete ref;
                    return;
                }
                refs = &ref->next;
                ref = *refs;
            }

            ALOGE("RefBase: removing id %p on RefBase %p"
                    "(weakref_type %p) that doesn't exist!",
                    id, mBase, this);

            ref = head;
            while (ref) {
                char inc = ref->ref >= 0 ? '+' : '-';
                ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
                ref = ref->next;
            }

            CallStack stack(LOG_TAG);
        }
    }

    void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
    {
        if (mTrackEnabled) {
            AutoMutex _l(mMutex);
            ref_entry* ref = r;
            while (ref != NULL) {
                if (ref->id == old_id) {
                    ref->id = new_id;
                }
                ref = ref->next;
            }
        }
    }
    ......
    mutable Mutex mMutex;
    ref_entry* mStrongRefs;
    ref_entry* mWeakRefs;

    bool mTrackEnabled;
    // Collect stack traces on addref and removeref, instead of deleting the stack references
    // on removeref that match the address ones.
    bool mRetain;

#endif
};

而weakref_impl 是继承与weakref_type,这个只是接口与实现的问题。是让代码中接口与实现分离的一种编程模式。


2.2 RefBase的IncStrong函数

下面我们再次结合智能指针进一步分析

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

这里的other就是实际的对象,这个对象的类必须继承RefBase这个类,我们来看看RefBase的incStrong函数:

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();
}
mRefs成员变量是在构造函数中创建的
RefBase::RefBase()
    : mRefs(new weakref_impl(this))
{
}
在这个incStrong函数中,主要做了三件事情:

        一是增加弱引用计数:

refs->addWeakRef(id);  
refs->incWeak(id); 

        二是增加强引用计数:

refs->addStrongRef(id);  
const int32_t c = android_atomic_inc(&refs->mStrong);  

        三是如果发现是首次调用这个对象的incStrong函数,就会调用一个这个对象的onFirstRef函数,这个函数是个虚函数在RefBase中是空实现,一般在对象中实现,让对象有机会在对象被首次引用时做一些处理逻辑:

if (c != INITIAL_STRONG_VALUE)  {  
    return;  
}  
  
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);  
const_cast<RefBase*>(this)->onFirstRef();  

       这里的c返回的是refs->mStrong加1前的值,如果发现等于INITIAL_STRONG_VALUE,就说明这个对象的强引用计数是第一次被增加,因此,refs->mStrong就是初始化为INITIAL_STRONG_VALUE的,它的值为:

#define INITIAL_STRONG_VALUE (1<<28)  
        这个值加1后等于1<<28 + 1,不等于1,因此,后面要再减去INITIAL_STRONG_VALUE,也就是加上负的INITIAL_STRONG_VALUE。这样refs->mStrong就等于1了,就表示当前对象的强引用计数值为1了,这与这个对象是第一次被增加强引用计数值的逻辑是一致的。

        回过头来看弱引用计数是如何增加的,首先是调用weakref_impl类的addWeakRef函数,我们知道,在Release版本中,这个函数也不做,而在Debug版本我们就不分析了。接着又调用了weakref_impl类的incWeak函数,真正增加弱引用计数值就是在这个函数实现的了,weakref_impl类的incWeak函数继承于其父类weakref_type的incWeak函数:

void RefBase::weakref_type::incWeak(const void* id)  
{  
    weakref_impl* const impl = static_cast<weakref_impl*>(this);  
    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);  
}  

       增加弱引用计数是下面语句执行的:

const int32_t c = android_atomic_inc(&impl->mWeak);  

2.3 RefBase的decStrong函数

下面再看看sp的析构函数:

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

同样的我们看下RefBase类的decStrong函数

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);//release版本空实现不分析了
    const int32_t c = android_atomic_dec(&refs->mStrong);//强引用次数减1
#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);
}

先对引用次数减1,然后在减1前发现如果是1,也就是减1后变0了,先调用RefBase的onLastStrongRef函数。这个函数是虚函数在RefBase中为空实现,一般在对象中继承实现。而mask为OBJECT_LIFETIME_STRONG说明这个对象的生命周期是受强指针控制的,当强指针的引用次数为1,就需要delete这个对象。

而对弱引用计数减1是在decWeak中执行的,这个函数是在weakref_type类中实现的

void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);//release版本空实现
    const int32_t c = android_atomic_dec(&impl->mWeak);//弱引用次数减1
    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    if (c != 1) return;//减之前不为1,直接return。为1后面进行delete相关对象

    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {//对象生命周期受强引用控制
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlive the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong == INITIAL_STRONG_VALUE) {//这里代表强引用处于初始化状态,所有需要删除对象,删除对象的同时会删除impl的
            // Special case: we never had a strong reference, so we need to
            // destroy the object now.
            delete impl->mBase;
        } else {
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;//删除impl
        }
    } else {
        // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
        impl->mBase->onLastWeakRef(id);
        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {//对象生命周期受弱引用控制
            // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
            // is gone, we can destroy the object.
            delete impl->mBase;//删除对象
        }
    }
}

这个函数,当弱引用次数不为1直接return,为1代表入弱引用次数减1后为0了,需要delete。

而为弱引用次数为1又分两种情况:

第一种对象生命周期受强引用控制,而当强引用计数为初始值,就要删除 impl->mBase就是删除实际对象。而RefBase被删除的时候调用析构函数,而在析构函数中决定是否delete mRefs。

RefBase::~RefBase()
{
    if (mRefs->mStrong == INITIAL_STRONG_VALUE) {//强引用初始值,直接删除mRefs
        // 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) {//弱引用次数为0 删除mRefs
                delete mRefs;
            }
        }
    }
    // for debugging purposes, clear this.
    const_cast<weakref_impl*&>(mRefs) = NULL;
}

而当强引用次数不是初始值的时候,直接delete impl。

第二种情况,对象生命周期不是受强引用控制,先调用onLastWeakRef函数,然后如果对象的生命周期是由弱引用控制,就直接删除RefBase对象,当然在RefBase的析构函数中也会删除mRefs对象的。

三、弱指针

这里分析弱指针。

3.1 wp类

弱指针wp的代码在RefBase.cpp中的:

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

    wp(T* other);
    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();
    
    // Assignment

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

    // promotion to sp
    
    sp<T> 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_WEAK(==)
    COMPARE_WEAK(!=)
    COMPARE_WEAK(>)
    COMPARE_WEAK(<)
    COMPARE_WEAK(<=)
    COMPARE_WEAK(>=)

    inline bool operator == (const wp<T>& o) const {
        return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
    }
    template<typename U>
    inline bool operator == (const wp<U>& o) const {
        return m_ptr == o.m_ptr;
    }

    inline bool operator > (const wp<T>& o) const {
        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
    }
    template<typename U>
    inline bool operator > (const wp<U>& o) const {
        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
    }

    inline bool operator < (const wp<T>& o) const {
        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
    }
    template<typename U>
    inline bool operator < (const wp<U>& o) const {
        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
    }
                         inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
    template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
                         inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
    template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
                         inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
    template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }

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

    T*              m_ptr;
    weakref_type*   m_refs;
};

与强指针类相比,它们都有一个成员变量m_ptr指向目标对象,但是弱指针还有一个额外的成员变量m_refs,它的类型是weakref_type指针,下面我们分析弱指针的构造函数时再看看它是如果初始化的。这里我们需要关注的仍然是弱指针的构造函数和析构函数。

先看wp的构造函数:

template<typename T>
wp<T>::wp(T* other)
    : m_ptr(other)
{
    if (other) m_refs = other->createWeak(this);
}

这里调用了RefBase的createWeak函数,返回值为m_refs。

在RefBase的createWeak函数中,直接调用了weakref_impl的incWeak函数,这个函数之前分析过了就是增加弱引用次数,然后返回mRefs.

RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);
    return mRefs;
}

再来看析构函数,这里直接调用了weakref_impl的decWeak函数,前面分析过这个函数了。在这个函数中弱引用次数减1,然后决定是否需要delete impl等。

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


3.2 升级强指针

分析到这里,弱指针还没介绍完,它最重要的特性我们还没有分析到。前面我们说过,弱指针的最大特点是它不能直接操作目标对象,这是怎么样做到的呢?秘密就在于弱指针类没有重载*和->操作符号,而强指针重载了这两个操作符号。但是,如果我们要操作目标对象,应该怎么办呢,这就要把弱指针升级为强指针了:

template<typename T>
sp<T> wp<T>::promote() const
{
    sp<T> result;
    if (m_ptr && m_refs->attemptIncStrong(&result)) {
        result.set_pointer(m_ptr);
    }
    return result;
}

在上面这个函数中就是将wp升级为sp。


四、强指针弱指针用法

源文件weightpointer.cpp的内容如下:

#include <stdio.h>  
#include <utils/RefBase.h>  
  
#define INITIAL_STRONG_VALUE (1<<28)  
  
using namespace android;  
  
class WeightClass : public RefBase  
{  
public:  
        void printRefCount()  
        {  
                int32_t strong = getStrongCount();  
                weakref_type* ref = getWeakRefs();  
  
                printf("-----------------------\n");  
                printf("Strong Ref Count: %d.\n", (strong  == INITIAL_STRONG_VALUE ? 0 : strong));  
                printf("Weak Ref Count: %d.\n", ref->getWeakCount());  
                printf("-----------------------\n");  
        }  
};  
  
class StrongClass : public WeightClass  
{  
public:  
        StrongClass()  
        {  
                printf("Construct StrongClass Object.\n");  
        }  
  
        virtual ~StrongClass()  
        {  
                printf("Destory StrongClass Object.\n");  
        }  
};  
  
  
class WeakClass : public WeightClass  
{  
public:  
        WeakClass()  
        {  
                extendObjectLifetime(OBJECT_LIFETIME_WEAK);// 设置对象生命周期受弱引用控制
  
                printf("Construct WeakClass Object.\n");  
        }  
  
        virtual ~WeakClass()  
        {  
                printf("Destory WeakClass Object.\n");  
        }  
};  
  
class ForeverClass : public WeightClass  
{  
public:  
        ForeverClass()  
        {  
                extendObjectLifetime(OBJECT_LIFETIME_FOREVER); //设置对象生命周期一直存在,就是普通指针。需要手动delete
  
                printf("Construct ForeverClass Object.\n");  
        }  
  
        virtual ~ForeverClass()  
        {  
                printf("Destory ForeverClass Object.\n");  
        }  
};  
  
  
void TestStrongClass(StrongClass* pStrongClass)  
{  
        wp<StrongClass> wpOut = pStrongClass;  
        pStrongClass->printRefCount();  
  
        {  
                sp<StrongClass> spInner = pStrongClass;  
                pStrongClass->printRefCount();  
        }  
  
        sp<StrongClass> spOut = wpOut.promote();  
        printf("spOut: %p.\n", spOut.get());  
}  
  
void TestWeakClass(WeakClass* pWeakClass)  
{  
        wp<WeakClass> wpOut = pWeakClass;  
        pWeakClass->printRefCount();  
  
        {  
                sp<WeakClass> spInner = pWeakClass;  
                pWeakClass->printRefCount();  
        }  
  
        pWeakClass->printRefCount();  
        sp<WeakClass> spOut = wpOut.promote();  
        printf("spOut: %p.\n", spOut.get());  
}  
  
  
void TestForeverClass(ForeverClass* pForeverClass)  
{  
        wp<ForeverClass> wpOut = pForeverClass;  
        pForeverClass->printRefCount();  
  
        {  
                sp<ForeverClass> spInner = pForeverClass;  
                pForeverClass->printRefCount();  
        }  
}  
  
int main(int argc, char** argv)  
{  
        printf("Test Strong Class: \n");  
        StrongClass* pStrongClass = new StrongClass();  
        TestStrongClass(pStrongClass);  
  
        printf("\nTest Weak Class: \n");  
        WeakClass* pWeakClass = new WeakClass();  
        TestWeakClass(pWeakClass);  
  
        printf("\nTest Froever Class: \n");  
        ForeverClass* pForeverClass = new ForeverClass();  
        TestForeverClass(pForeverClass);  
        pForeverClass->printRefCount();  
        delete pForeverClass;  
  
        return 0;  
}  

        首先定义了一个基类WeightClass,继承于RefBase类,它只有一个成员函数printRefCount,作用是用来输出引用计数。接着分别定义了三个类StrongClass、WeakClass和ForeverClass,其中实例化StrongClass类的得到的对象的标志位为默认值0,实例化WeakClass类的得到的对象的标志位为OBJECT_LIFETIME_WEAK,实例化ForeverClass类的得到的对象的标志位为OBJECT_LIFETIME_FOREVER,后两者都是通过调用RefBase类的extendObjectLifetime成员函数来设置的。

        在main函数里面,分别实例化了这三个类的对象出来,然后分别传给TestStrongClass函数、TestWeakClass函数和TestForeverClass函数来说明智能指针的用法,我们主要是通过考察它们的强引用计数和弱引用计数来验证智能指针的实现原理。

        编译脚本文件Android.mk的内容如下:

LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
LOCAL_MODULE_TAGS := optional  
LOCAL_MODULE := weightpointer  
LOCAL_SRC_FILES := weightpointer.cpp  
LOCAL_SHARED_LIBRARIES := \  
        libcutils \  
        libutils  
include $(BUILD_EXECUTABLE)  

        最后,我们参照如何单独编译Android源代码中的模块一文,使用mmm命令对工程进行编译:

USER-NAME@MACHINE-NAME:~/Android$ mmm ./external/weightpointer 
        编译之后,就可以打包了:

USER-NAME@MACHINE-NAME:~/Android$ make snod  

        最后得到可执行程序weightpointer就位于设备上的/system/bin/目录下。启动模拟器,通过adb shell命令进入到模拟器终端,进入到/system/bin/目录,执行weightpointer可执行程序,验证程序是否按照我们设计的逻辑运行:

USER-NAME@MACHINE-NAME:~/Android$ adb shell  
root@android:/ # cd system/bin/          
root@android:/system/bin # ./weightpointer    

        执行TestStrongClass函数的输出为:

Test Strong Class:   
Construct StrongClass Object.  
-----------------------  
Strong Ref Count: 0.  
Weak Ref Count: 1.  
-----------------------  
-----------------------  
Strong Ref Count: 1.  
Weak Ref Count: 2.  
-----------------------  
Destory StrongClass Object.  
spOut: 0x0.  

        在TestStrongClass函数里面,首先定义一个弱批针wpOut指向从main函数传进来的StrongClass对象,这时候我们可以看到StrongClass对象的强引用计数和弱引用计数值分别为0和1;接着在一个大括号里面定义一个强指针spInner指向这个StrongClass对象,这时候我们可以看到StrongClass对象的强引用计数和弱引用计数值分别为1和2;当程序跳出了大括号之后,强指针spInner就被析构了,从上面的分析我们知道,强指针spInner析构时,会减少目标对象的强引用计数值,因为前面得到的强引用计数值为1,这里减1后,就变为0了,又由于这个StrongClass对象的生命周期只受强引用计数控制,因此,这个StrongClass对象就被delete了,这一点可以从后面的输出(“Destory StrongClass Object.”)以及试图把弱指针wpOut提升为强指针时得到的对象指针为0x0得到验证。

        执行TestWeakClass函数的输出为:

Test Weak Class:   
Construct WeakClass Object.  
-----------------------  
Strong Ref Count: 0.  
Weak Ref Count: 1.  
-----------------------  
-----------------------  
Strong Ref Count: 1.  
Weak Ref Count: 2.  
-----------------------  
-----------------------  
Strong Ref Count: 0.  
Weak Ref Count: 1.  
-----------------------  
spOut: 0xa528.  
Destory WeakClass Object.  

        TestWeakClass函数和TestStrongClass函数的执行过程基本一样,所不同的是当程序跳出大括号之后,虽然这个WeakClass对象的强引用计数值已经为0,但是由于它的生命周期同时受强引用计数和弱引用计数控制,而这时它的弱引用计数值大于0,因此,这个WeakClass对象不会被delete掉,这一点可以从后面试图把弱批针wpOut提升为强指针时得到的对象指针不为0得到验证。

        执行TestForeverClass函数的输出来:

Test Froever Class:   
Construct ForeverClass Object.  
-----------------------  
Strong Ref Count: 0.  
Weak Ref Count: 1.  
-----------------------  
-----------------------  
Strong Ref Count: 1.  
Weak Ref Count: 2.  
-----------------------  

       当执行完TestForeverClass函数返回到main函数的输出来:

-----------------------  
Strong Ref Count: 0.  
Weak Ref Count: 0.  
-----------------------  
Destory ForeverClass Object.  
        这里我们可以看出,虽然这个ForeverClass对象的强引用计数和弱引用计数值均为0了,但是它不自动被delete掉,虽然由我们手动地delete这个对象,它才会被析构,这是因为这个ForeverClass对象的生命周期是既不受强引用计数值控制,也不会弱引用计数值控制。

        这样,从TestStrongClass、TestWeakClass和TestForeverClass这三个函数的输出就可以验证了我们上面对Android系统的强指针和弱指针的实现原理的分析。

        这样Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理就分析完成了。






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值