智能指针到Android引用计数

  1. 智能指针
  2. LightRefBase
  3. RefBase
    1. StrongPointer
    2. WeakPointer

智能指针

这是自己实现的一个 SmartPointer.没有引入引用计数的概念.只是负责维护对象指针.

// SmartPointer.h
#ifndef SMART_POINTER_DEF_H
#define SMART_POINTER_DEF_H

template<typename T>
class SmartPointer
{
protected:
    T *m_ptr;

public:
    SmartPointer();
    SmartPointer(const T *ptr);
    ~SmartPointer();
    T* operator->();
    T& operator*();
};

template<typename T>
SmartPointer<T>::SmartPointer()
{
    m_ptr = NULL;
}

template<typename T>
SmartPointer<T>::SmartPointer(const T *ptr)
{
    m_ptr = const_cast<T*>(ptr);
}

template<typename T>
SmartPointer<T>::~SmartPointer()
{
    delete m_ptr;
}

template<typename T>
T* SmartPointer<T>::operator->()
{
    return m_ptr;
}

template<typename T>
T& SmartPointer<T>::operator*()
{
    return *m_ptr;
}

#endif // SMART_POINTER_DEF_H
// example.cpp
#include <cstdlib>
#include <iostream>

#include "SmartPointer.h"

using namespace std;

class Test {
public:
    int i;
    void print()
    {
        cout << i << endl;
    }
};

int main(int argc, char **argv)
{
    SmartPointer<int> pi = new int(5);
    SmartPointer<Test> pt = new Test();

    cout << *pi << endl;

    *pi = 10;

    cout << *pi << endl;

    pt->i = 20;
    pt->print();

    return 0;
}

上述中 SmartPointer 明显缺点就是没有 引用计数. 如果我们想引入引用计数, 那么需要思考一个问题, 引用计数由谁维护?

  • 引用计数由 智能指针 持有?

    一个对象的引用计数只能有一个,但是每引用一次对象都要创建一个智能指针,那么就有好多个引用计数.明显的不合逻辑.

  • 引用计数由 Object 自身持有

    这是合理的.
    接着的问题是如何维护 智能指针,引用计数,被引用对象 三者之间的关系.
    下文依据 Android 源码来回答这个问题.

LightRefBase

template <class T>
class LightRefBase
{
public:
    inline LightRefBase() : mCount(0) { }
    inline void incStrong(__attribute__((unused)) const void* id) const { // 增加引用计数
        mCount.fetch_add(1, std::memory_order_relaxed);
    }
    inline void decStrong(__attribute__((unused)) const void* id) const { // 减少引用计数
        if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
            std::atomic_thread_fence(std::memory_order_acquire);
            delete static_cast<const T*>(this);   // 删除被引用对象
            /*
             *  this 指针指向的是 LightRefBase 的 子类 对象.
            */
            
        }
    }
    //! DEBUGGING ONLY: Get current strong ref count.
    inline int32_t getStrongCount() const {
        return mCount.load(std::memory_order_relaxed);
    }

    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 std::atomic<int32_t> mCount; // 引用计数 -> 原子变量
};

在 AndroidO 源码中,有一个 LightRefBase 的 Demo,修改修改,可以测试.

class SPFoo : public LightRefBase<SPFoo> {
public:
    explicit SPFoo(bool* deleted_check) : mDeleted(deleted_check) {
        *mDeleted = false;
    }

    ~SPFoo() {
        *mDeleted = true;
    }
private:
    bool* mDeleted;
};

int main(int argc, char **argv)
{
    bool isDeleted;
    sp<SPFoo> foo = new SPFoo(&isDeleted);

    ALOGD("RefCnt = %d", foo->getStrongCount());
    if (isDeleted) {
        ALOGD("Already deleted...?");
    }

    sp<SPFoo> sp1(foo);
    ALOGD("RefCnt = %d", foo->getStrongCount());
    {
        sp<SPFoo> sp2 = std::move(sp1);
        /*
        * std::move 并不会增加引用计数.
        * 指向完后, sp1将变为 null.
        */
        ALOGD("foo = %d, sp2 = %d",
              foo->getStrongCount(), sp2->getStrongCount());
        if (2 != foo->getStrongCount()) {
            ALOGD("std::move failed, incremented refcnt");
        }
        if (nullptr != sp1.get()) {
            ALOGE("std::move failed, sp1 is still valid");
        }
        if (nullptr == sp2.get()) {
            ALOGE("sp2 is still valid");
        }
        sp1 = std::move(sp2);
        ALOGD("RefCnt = %d", foo->getStrongCount());
    }
    if (isDeleted) {
        ALOGD("deleted too early! still has a reference!");
    }
    {
        :sp<SPFoo> sp2 = std::move(sp1);
        ALOGD("RefCnt = %d", foo->getStrongCount());
    }
    if (!isDeleted) {
        ALOGD("foo was leaded!");
    }

    return 0;
}
  • sp 就是 Class StrongPointer.
  • StrongPointer 知道什么时候增加,减少引用计数. 具体引用计数的维护交给了 LightRefBase.

RefBase

之前,我们先看下 StrongPointer.

StrongPointer

在 Android 中可以看到如下代码:

class A : public RefBase 
{
    ...
}

{
    sp<A> aa = new A();
}

就是说继承自 RefBase 也是使用 sp.

想说明的一个问题是, sp 可以适配 LightRefBase, 也可以适配 RefBase. sp 只是定义了什么时候增加引用计数,具体实现如何增加,由 LightRefBase 或 RefBase 管理.

下面来看 class sp 如何定义?

template<typename T> class wp;

// ---------------------------------------------------------------------------
// 操作符重载
// m_ptr 是实际分配的对象的地址,也就是 "new A()" 的地址.
#define COMPARE(_op_)                                           \
inline bool operator _op_ (const sp<T>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}                                                               \
inline bool operator _op_ (const T* o) const {                  \
    return m_ptr _op_ o;                                        \
}                                                               \
template<typename U>                                            \
inline bool operator _op_ (const sp<U>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}                                                               \
template<typename U>                                            \
inline bool operator _op_ (const U* o) const {                  \
    return m_ptr _op_ o;                                        \
}                                                               \
inline bool operator _op_ (const wp<T>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}                                                               \
template<typename U>                                            \
inline bool operator _op_ (const wp<U>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}

// ---------------------------------------------------------------------------

template<typename T>
class sp {
public:
    inline sp() : m_ptr(0) { }

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

    ~sp();

    // Assignment

    sp& operator = (T* other);
    sp& operator = (const sp<T>& other);
    sp& operator = (sp<T>&& other);

    template<typename U> sp& operator = (const sp<U>& other);
    template<typename U> sp& operator = (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;
};

// For code size reasons, we do not want this inlined or templated.
void sp_report_race();

#undef COMPARE

// ---------------------------------------------------------------------------
// No user serviceable parts below here.

template<typename T>
sp<T>::sp(T* other)
        : m_ptr(other) {
    if (other) {
        other->incStrong(this);  // other 指向 class A 的对象,A 可以继承自 RefBase,也可以继承自 LightRefBase
    }
}

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

template<typename T>
sp<T>::sp(sp<T>&& other)
        : m_ptr(other.m_ptr) {
    other.m_ptr = nullptr;      // 这里有意思, 引用的引用
}

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

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

template<typename T> template<typename U>
sp<T>::sp(sp<U>&& other)
        : m_ptr(other.m_ptr) {
    other.m_ptr = nullptr;
}

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

template<typename T>
sp<T>& sp<T>::operator =(const sp<T>& other) {
    // Force m_ptr to be read twice, to heuristically check for data races.
    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    m_ptr = otherPtr;
    return *this;
}

template<typename T>
sp<T>& sp<T>::operator =(sp<T>&& other) {
    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    m_ptr = other.m_ptr;
    other.m_ptr = nullptr;
    return *this;
}

template<typename T>
sp<T>& sp<T>::operator =(T* other) {
    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    if (other) other->incStrong(this);
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    m_ptr = other;
    return *this;
}

template<typename T> template<typename U>
sp<T>& sp<T>::operator =(const sp<U>& other) {
    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    m_ptr = otherPtr;
    return *this;
}

template<typename T> template<typename U>
sp<T>& sp<T>::operator =(sp<U>&& other) {
    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    if (m_ptr) m_ptr->decStrong(this);
    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    m_ptr = other.m_ptr;
    other.m_ptr = nullptr;
    return *this;
}

template<typename T> template<typename U>
sp<T>& sp<T>::operator =(U* other) {
    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    if (other) (static_cast<T*>(other))->incStrong(this);
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    m_ptr = other;
    return *this;
}

template<typename T>
void sp<T>::force_set(T* other) {
    other->forceIncStrong(this);  // 什么是 forceInStrong?
    m_ptr = other;
}

template<typename T>
void sp<T>::clear() {
    if (m_ptr) {
        m_ptr->decStrong(this);
        m_ptr = 0;
    }
}

template<typename T>
void sp<T>::set_pointer(T* ptr) {
    m_ptr = ptr;
}
  • StrongPointer 构造时 增加引用计数.
  • StrongPointer 析构时 减少引用计数.
  • StrongPointer 操作符 = 重载, 减少之前引用对象计数,增加新的引用对象计数.

ReBase 的定义

// RefBase.h
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
    };
    
    // Invoked after creation of initial strong pointer/reference.
    virtual void            onFirstRef();
    // Invoked when either the last strong reference goes away, or we need to undo
    // the effect of an unnecessary onIncStrongAttempted.
    virtual void            onLastStrongRef(const void* id);
    // Only called in OBJECT_LIFETIME_WEAK case.  Returns true if OK to promote to
    // strong reference. May have side effects if it returns true.
    // The first flags argument is always FIRST_INC_STRONG.
    // TODO: Remove initial flag argument.
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    // Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
    // kind goes away.  Unused.
    // TODO: Remove.
    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 的内部类 weakref_type 的子类 weakref_impl 维护.
  • weakref_impl 是 weakref_type 的子类, weakref_type 只是提供接口,具体实现由 weakref_impl 完成.
  • RefBase 中 强引用 相关 API:

    • incStorng
    • decStrong
    • forceIncStrong
    • getStrongCount
  • RefBase 中 弱引用 相关 API:

    • createWeak
    • weakref_type->incWeak
    • weakref_type->decWeak

RefBase 的构造

RefBase::RefBase()
    : mRefs(new weakref_impl(this))
{
    /*
     * mRefs 很重要.
    */
}

weakref_impl

weakref_impl 不只是维护弱引用计数,也维护强引用计数.也就是说 sp 调用 RefBase 的 incStrong ,最后会调到 weakref_impl 的某个接口或者直接修改 weakref_impl 中 维护强引用计数的变量 mStrong.

class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
    std::atomic<int32_t>    mStrong;   // 描述强引用计数
    std::atomic<int32_t>    mWeak;     // 描述弱引用计数
    RefBase* const          mBase;     // 指向父类对象
    std::atomic<int32_t>    mFlags;    // 描述对象的生命周期

/*
 * mFlags 说明:
 * mFlags 取值范围: OBJECT_LIFETIME_STRONG, OBJECT_LIFETIME_WEAK
 * OBJECT_LIFETIME_STRONG: 表示对象的生命周期只受强引用计数影响.
 * OBJECT_LIFETIME_WEAK: 表示对象寿命周期同事受强引用计数和弱引用计数的影响.
*/

/*
 * weakref_impl 提供了 DEBUG 版本, DEBUG 版本用来调试 weakref_impl.
 * 这里我都会进行详细分析.
*/
#if !DEBUG_REFS

    /*
     * weakref_impl 非调试 版本.
    */
    explicit weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)    // mStrong 初始值 为 : (1<<28)
        , mWeak(0)
        , mBase(base)
        , mFlags(0)  // mFlags 初始值为0 ,也就是 OBJECT_LIFETIME_STRONG. 默认对象只受引用计数影响.
    {
    }

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

    /*
     * mTrackEnabled : 如果 mTrackEnabled == false, addref 和 removeref 什么都不做.
     * mRetain: 调用 addref 或 removeref 时 收集 stack traces, 而不是 删除 引用堆栈.
    */
    
    ~weakref_impl()
    {
        bool dumpStack = false;
        if (!mRetain && mStrongRefs != NULL) {
            /*
             * 如果 mRetain == false, 在 析构 weakref_impl 时, mStrong 应该为 0, mStrongRefs 也该为 NULL; 如果不为0, 表示引用计数出错.
            */
            dumpStack = true;
            ALOGE("Strong references remain:");
            /*
             * 关于 ref_entry 下文详述.先跳到下文看 ref_entry 的详细描述.
            */
            /*
             * mStrongRefs 是 ref_entry * 类型, 而 ref_entry 是一个链表.
            */
            ref_entry* refs = mStrongRefs;

            /*
             * 遍历 mStrongRefs 这个链表
            */
            while (refs) {
                char inc = refs->ref >= 0 ? '+' : '-';  // 如果 refs->ref > 0, 这 inc = '+'
                ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); // 打印 debug log 信息.
#if DEBUG_REFS_CALLSTACK_ENABLED
                refs->stack.log(LOG_TAG);
#endif
                refs = refs->next;
            }
        }

        /*
         * 对 mWeakRefs 处理类似, mWeakRefs 也是一个 ref_entry 链表.
        */
        if (!mRetain && mWeakRefs != NULL) {
            dumpStack = true;
            ALOGE("Weak references remain!");
            ref_entry* refs = mWeakRefs;
            while (refs) {
                char inc = refs->ref >= 0 ? '+' : '-';
                ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
                refs->stack.log(LOG_TAG);
#endif
                refs = refs->next;
            }
        }
        if (dumpStack) {
            ALOGE("above errors at:");
            CallStack stack(LOG_TAG);
        }
    }

    /*
     * 再次强调: id 是 sp 或 wp 的地址
    */

    void addStrongRef(const void* id) {
        //ALOGD_IF(mTrackEnabled,
        //        "addStrongRef: RefBase=%p, id=%p", mBase, id);
        addRef(&mStrongRefs, id, mStrong.load(std::memory_order_relaxed));
        /*
         * addRef 将 id 和 mStrong 包装成 ref_entry , 添加到 mStrongRefs 这链表中.
        */
    }

    void removeStrongRef(const void* id) {
        //ALOGD_IF(mTrackEnabled,
        //        "removeStrongRef: RefBase=%p, id=%p", mBase, id);
        if (!mRetain) {
            /*
             * remoteRefs 删除 mStrongRefs 链表中 id 对应的 节点.
            */
            removeRef(&mStrongRefs, id);
        } else {
            /*
            * 这里很重要,如果 mRetain == true, 不是调用 removeRef 删除链表节点, 而是 增加一个 负数 节点.
            * 想想这么做也是有理的.
            */
            addRef(&mStrongRefs, id, -mStrong.load(std::memory_order_relaxed));
        }
    }

    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.load(std::memory_order_relaxed));
    }

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

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

    void trackMe(bool track, bool retain)
    { 
        mTrackEnabled = track;
        mRetain = retain;
    }

    void printRefs() const
    {
        String8 text;

        {
            Mutex::Autolock _l(mMutex);
            char buf[128];
            snprintf(buf, sizeof(buf),
                     "Strong references on RefBase %p (weakref_type %p):\n",
                     mBase, this);
            text.append(buf);
            printRefsLocked(&text, mStrongRefs);
            snprintf(buf, sizeof(buf),
                     "Weak references on RefBase %p (weakref_type %p):\n",
                     mBase, this);
            text.append(buf);
            printRefsLocked(&text, mWeakRefs);
        }

        {
            char name[100];
            snprintf(name, sizeof(name), DEBUG_REFS_CALLSTACK_PATH "/%p.stack",
                     this);
            int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
            if (rc >= 0) {
                write(rc, text.string(), text.length());
                close(rc);
                ALOGD("STACK TRACE for %p saved in %s", this, name);
            }
            else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
                      name, strerror(errno));
        }
    }

private:
    struct ref_entry
    {
        ref_entry* next;          // 这是一个链表
        const void* id;           // id 是 sp 或 wp 的地址. id 很好追查.
#if DEBUG_REFS_CALLSTACK_ENABLED
        CallStack stack;          // CallStack
#endif
        int32_t ref;              // ref 是引用计数, 如果 ref_entry 描述的是 强引用计数,那么就是 mStrong 的值.
    };

    /*
     * 这是 核心函数.非常清楚.就是构造节点,插入链表
    */
    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;
        }
    }

    /*
     * 遍历链表,找到 id 对应的节点,并且删除该节点.
    */
    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);
        }
    }

    /*
     * 将 old_id 对应的 链表节点 ref_entry 中的 id 元素替换成 new_id.
    */
    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;
            }
        }
    }

    void printRefsLocked(String8* out, const ref_entry* refs) const
    {
        char buf[128];
        while (refs) {
            char inc = refs->ref >= 0 ? '+' : '-';
            snprintf(buf, sizeof(buf), "\t%c ID %p (ref %d):\n",
                     inc, refs->id, refs->ref);
            out->append(buf);
#if DEBUG_REFS_CALLSTACK_ENABLED
            out->append(refs->stack.toString("\t\t"));
#else
            out->append("\t\t(call stacks disabled)");
#endif
            refs = refs->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_impl 只是负责定义 4 个变量, 且是 public 变量:mStrong, mWeak, mBase, mFlags.

在 调试版本中, weakref_impl 负责打印 debug message.

如何实现强引用计数?

增加强引用计数

void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->incWeak(id);

    refs->addStrongRef(id); // Debug 相关,已经分析过
    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);    // 增加强引用计数
    if (c != INITIAL_STRONG_VALUE)  {                                           // 如果不是第一次被强引用,直接返回
        return;
    }

    // mStrong 的初始值: 0x10000000
    // 第一次引用后 mStrong 的值是 0x10000000+1, old = 0x10000000+1

    int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
            std::memory_order_relaxed);
    /*
     * 执行完后: mStrong == 1 ;  真是折腾啊!!
    */
    // A decStrong() must still happen after us.
    ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
    refs->mBase->onFirstRef();  // 这里是关键, 回调 onFirstRef()
}

incStrong 做了 3 件事:

  • 增加弱引用计数
  • 增加强引用计数
  • 如果是第一次被强引用,调用 onFirstRef 来通知对象. onFirstRef 由 RefBase 子类重写.

incWeak

void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);  // this 指向 weakref_impl
    impl->addWeakRef(id);                                         // debug
    const int32_t c __unused = impl->mWeak.fetch_add(1,
            std::memory_order_relaxed);                           // mWeak + 1
    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}

减少强引用计数

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);  // debug
    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release); // mStrong - 1
#if PRINT_REFS
    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
            refs);
    if (c == 1) { // 如果在当前是 最后一个 强引用, 那么就要考虑释放对象了
        std::atomic_thread_fence(std::memory_order_acquire);
        // 首先通过 onLastSrongRef 通知对象
        refs->mBase->onLastStrongRef(id);
        // 读取 mFlags 的值
        int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            // 此时,说明 OBJECT_LIFETIME_WEAK 没有设置.所以 对象的生命周期 只受 强引用计数的影响.
            /*
             * Object 的声明周期要想和 弱引用计数 相关,需要 设置 mFlags 为 OBJECT_LIFETIME_WEAK.
             * 这是通过调用 RefBase::extendObjectLifetime 方法实现的.
             * 在 ./framework 下,查找 extendObjectLifetimed 的调用, 只有 Binder 中有.
             * 说明一般使用者,可以不去 Care 弱引用计数.
            */
            // this 指向的就是对象.所以删除对象.
            delete this;
            // The destructor does not delete refs in this case.
        }
    }
    // Note that even with only strong reference operations, the thread
    // deallocating this may not be the same as the thread deallocating refs.
    // That's OK: all accesses to this happen before its deletion here,
    // and all accesses to refs happen before its deletion in the final decWeak.
    // The destructor can safely access mRefs because either it's deleting
    // mRefs itself, or it's running entirely before the final mWeak decrement.
    refs->decWeak(id);  // 不管如何, 还是要 decWeak 来减少弱引用计数的
}

~RefBase

RefBase::~RefBase()
{
    int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
    // Life-time of this object is extended to WEAK, in
    // which case weakref_impl doesn't out-live the object and we
    // can free it now.
    if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
        // It's possible that the weak count is not 0 if the object
        // re-acquired a weak reference in its destructor
        if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
            delete mRefs;
        }
    } else if (mRefs->mStrong.load(std::memory_order_relaxed)
            == INITIAL_STRONG_VALUE) {
        // We never acquired a strong reference on this object.
        LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
                "RefBase: Explicit destruction with non-zero weak "
                "reference count");
        // TODO: Always report if we get here. Currently MediaMetadataRetriever
        // C++ objects are inconsistently managed and sometimes get here.
        // There may be other cases, but we believe they should all be fixed.
        delete mRefs;
    }
    // For debugging purposes, clear mRefs.  Ineffective against outstanding wp's.
    const_cast<weakref_impl*&>(mRefs) = NULL;
    /*
     * 如果没有扩展 RefBase 的生命周期, 那么这个调用只执行最后一句话.
    */
}

decWeak

void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);
    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
    LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
            this);
    if (c != 1) return;
    atomic_thread_fence(std::memory_order_acquire);

    int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
    /*
     * 对象 生命周期 只受 强引用计数 影响.
    */
    if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlives the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong.load(std::memory_order_relaxed)
                == INITIAL_STRONG_VALUE) {
            // Decrementing a weak count to zero when object never had a strong
            // reference.  We assume it acquired a weak reference early, e.g.
            // in the constructor, and will eventually be properly destroyed,
            // usually via incrementing and decrementing the strong count.
            // Thus we no longer do anything here.  We log this case, since it
            // seems to be extremely rare, and should not normally occur. We
            // used to deallocate mBase here, so this may now indicate a leak.
            ALOGW("RefBase: Object at %p lost last weak reference "
                    "before it had a strong reference", impl->mBase);
        } else {
            ALOGD("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;
            /*
             * 这里删除 weakref_impl.
            */
        }
    } else {
        // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
        // is gone, we can destroy the object.
        /*
         * 如果对象的生命周期受 弱引用计数 的影响.
         * 1. 回调 onLastWeakRef
         * 2. 删除 impl->mBase,也就是销毁对象.
        */
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;
    }
}

如何实现弱引用计数?

非常重要的一点:

弱引用计数不直接操作它所引用的对象, 因为它所引用的对象可能不受引用计数控制,即它所引用的对象是一个无效的对象.

因此,如果需要操作一个弱指针所引用的对象,那么就需要将这个若指针升级为强指针, 这是通过成员函数 promote 来实现的.

如果升级成功,说明该若指针所引用的对象还没有被销毁,可以正常使用.

wp

#define COMPARE_WEAK(_op_)                                      \
inline bool operator _op_ (const sp<T>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}                                                               \
inline bool operator _op_ (const T* o) const {                  \
    return m_ptr _op_ o;                                        \
}                                                               \
template<typename U>                                            \
inline bool operator _op_ (const sp<U>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}                                                               \
template<typename U>                                            \
inline bool operator _op_ (const U* o) const {                  \
    return m_ptr _op_ o;                                        \
}


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

    inline wp() : m_ptr(0) { }

    wp(T* other);  // NOLINT(implicit)
    wp(const wp<T>& other);
    explicit wp(const sp<T>& other);
    template<typename U> wp(U* other);  // NOLINT(implicit)
    template<typename U> wp(const sp<U>& other);  // NOLINT(implicit)
    template<typename U> wp(const wp<U>& other);  // NOLINT(implicit)

    ~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;   // 维护弱引用计数
};

template <typename T>
TextOutput& operator<<(TextOutput& to, const wp<T>& val);

#undef COMPARE_WEAK

// ---------------------------------------------------------------------------
// No user serviceable parts below here.

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)
    : m_ptr(other)
{
    if (other) m_refs = other->createWeak(this);
}

template<typename T> template<typename U>
wp<T>::wp(const wp<U>& other)
    : m_ptr(other.m_ptr)
{
    if (m_ptr) {
        m_refs = other.m_refs;
        m_refs->incWeak(this);
    }
}

template<typename T> template<typename U>
wp<T>::wp(const sp<U>& other)
    : m_ptr(other.m_ptr)
{
    if (m_ptr) {
        m_refs = m_ptr->createWeak(this);
    }
}

template<typename T>
wp<T>::~wp()
{
    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;
}

template<typename T>
wp<T>& wp<T>::operator = (const wp<T>& other)
{
    weakref_type* otherRefs(other.m_refs);
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherRefs->incWeak(this);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = otherPtr;
    m_refs = otherRefs;
    return *this;
}

template<typename T>
wp<T>& wp<T>::operator = (const sp<T>& other)
{
    weakref_type* newRefs =
        other != NULL ? other->createWeak(this) : 0;
    T* otherPtr(other.m_ptr);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = otherPtr;
    m_refs = newRefs;
    return *this;
}

template<typename T> template<typename U>
wp<T>& wp<T>::operator = (U* other)
{
    weakref_type* newRefs =
        other ? other->createWeak(this) : 0;
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = other;
    m_refs = newRefs;
    return *this;
}

template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const wp<U>& other)
{
    weakref_type* otherRefs(other.m_refs);
    U* otherPtr(other.m_ptr);
    if (otherPtr) otherRefs->incWeak(this);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = otherPtr;
    m_refs = otherRefs;
    return *this;
}

template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const sp<U>& other)
{
    weakref_type* newRefs =
        other != NULL ? other->createWeak(this) : 0;
    U* otherPtr(other.m_ptr);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = otherPtr;
    m_refs = newRefs;
    return *this;
}

template<typename T>
void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
{
    if (other) refs->incWeak(this);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = other;
    m_refs = refs;
}

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

template<typename T>
void wp<T>::clear()
{
    if (m_ptr) {
        m_refs->decWeak(this);
        m_ptr = 0;
    }
}

template <typename T>
inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
{
    return printWeakPointer(to, val.unsafe_get());
}
  • createWeak
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);
    return mRefs;
}

incWeak 已经分析过.

wp 是无法操作所引用对象的,因为 wp 没有重载 -> 和 * 操作符. wp 要想 操作对象,需要通过 promote 方法升级为强指针.

promote

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

attemptIncStrong

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.load(std::memory_order_relaxed); // 获取当前的强引用计数

    ALOG_ASSERT(curCount >= 0,
            "attemptIncStrong called on %p after underflow", this);

    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
        // we're in the easy/common case of promoting a weak-reference
        // from an existing strong reference.
        /*
         * 当预期的值与对象真正持有的值相等,那么它将返回成功并把所需的值写入内存。否则,预期值会被内存中实际的值覆盖更新,并返回失败。
         * 关于 C++ automic 是个大学问,需要深入了解.
         * 这里只需要明白,这是在将 引用计数 + 1
        */
        if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                std::memory_order_relaxed)) {
            break;
        }
        // the strong count has changed on us, we need to re-assert our
        // situation. curCount was updated by compare_exchange_weak.
    }
    
    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
        // we're now in the harder case of either:
        // - there never was a strong reference on us
        // - or, all strong references have been released
        int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            // this object has a "normal" life-time, i.e.: it gets destroyed
            // when the last strong reference goes away
            /*
             * 对象生命周期由引用计数确定.
            */
            if (curCount <= 0) { // 说明目标对象已经被释放.
                // the last strong-reference got released, the object cannot
                // be revived.
                decWeak(id);
                return false;
            }

            // here, curCount == INITIAL_STRONG_VALUE, which means
            // there never was a strong-reference, so we can try to
            // promote this object; we need to do that atomically.
            while (curCount > 0) {
                if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                        std::memory_order_relaxed)) {
                    break;
                }
                // the strong count has changed on us, we need to re-assert our
                // situation (e.g.: another thread has inc/decStrong'ed us)
                // curCount has been updated.
            }

            if (curCount <= 0) {
                // promote() failed, some other thread destroyed us in the
                // meantime (i.e.: strong count reached zero).
                decWeak(id);
                return false;
            }
        } else {
            // this object has an "extended" life-time, i.e.: it can be
            // revived from a weak-reference only.
            // Ask the object's implementation if it agrees to be revived
            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
                // it didn't so give-up.
                decWeak(id);
                return false;
            }
            // grab a strong-reference, which is always safe due to the
            // extended life-time.
            curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
            // 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->addStrongRef(id);

#if PRINT_REFS
    ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
#endif

    // curCount is the value of mStrong before we incremented it.
    // Now we need to fix-up the count if it was INITIAL_STRONG_VALUE.
    // This must be done safely, i.e.: handle the case where several threads
    // were here in attemptIncStrong().
    // curCount > INITIAL_STRONG_VALUE is OK, and can happen if we're doing
    // this in the middle of another incStrong.  The subtraction is handled
    // by the thread that started with INITIAL_STRONG_VALUE.
    if (curCount == INITIAL_STRONG_VALUE) {
        impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
                std::memory_order_relaxed);
    }

    return true;
}

set_pointer

template<typename T>
void sp<T>::set_pointer(T* ptr) {
    m_ptr = ptr;
}

循环引用

namespace andorid {
 
class Bigclass : public RefBase 
{ 
public:
    Bigclass(char *name){
        strcpy(mName, name);
        ALOGD("Construct: %s", mName);
    }
 
    ~Bigclass(){
        ALOGD("destruct: %s", mName);
    }
    
    void setStrongRefs(sp<Bigclass> b) {
        spB = b;
    }       
 
private:    
    sp<Bigclass> spB;
    char mName[64]; 
};
 
};

using name android;

void testStrongCrossRef()
{
    sp<Bigclass> A = new Bigclass("testStrongClassA"); // A -> ref_cnt = 1
    sp<Bigclass> B = new Bigclass("testStrongClassB"); // B -> ref_cnt = 1
  
    A->setStrongRefs(B);  // B->ref_cnt = 2, B->ref_cnt = 3, B->ref_cnt = 2
    B->setStrongRefs(A);  // A->ref_cng = 2, A->ref_cnt = 3, A->ref_cnt = 2

    /*
     * 说明: 实际参数到形似参数的传递也会 构造 sp, 增加 引用计数.但是在函数执行完后,会进行析构.
    */

    /*
     * A->ref_cnt = 1
     * B->ref_cnt = 1
     * 结果就是 ref_cnt != 0, 导致对象无法释放.
    */
}
 
int main()
{
    ALOGD("Start testStrongClasses..");  
    testStrongCrossRef();
    ALOGD("testStrongClasses Should be destructed!!");
 
    return 0;
}

如何解决?

namespace andorid {
 
class Bigclass : public RefBase 
{ 
public:
    Bigclass(char *name){
        strcpy(mName, name);
        ALOGD("Construct: %s", mName);
    }
 
    ~Bigclass(){
        ALOGD("destruct: %s", mName);
    }

    void setStrongRefs(sp<Bigclass> b) {
        spB = b;
    }
    
    void setWeakRefs(sp<Bigclass> b) {
        wpB = b;
    }   
 
private:
    wp<Bigclass> wpB;
    sp<Bigclass> spB;
    char mName[64]; 
};
 
};

using name android;

void testStrongCrossRef()
{
    sp<Bigclass> A = new Bigclass("testStrongClassA"); // A -> ref_cnt = 1
    sp<Bigclass> B = new Bigclass("testStrongClassB"); // B -> ref_cnt = 1
  
    A->setWeakRefs(B);  // B->ref_cnt = 2, B->ref_cnt = 1
    B->setWeakRefs(A);  // A->ref_cng = 2, A->ref_cnt = 1

    /*
     * 说明: 实际参数到形似参数的传递也会 构造 sp, 增加 引用计数.但是在函数执行完后,会进行析构.
    */

    /*
     * A->ref_cnt = 0
     * B->ref_cnt = 0
    */
}
 
int main()
{
    ALOGD("Start testStrongClasses..");  
    testStrongCrossRef();
    ALOGD("testStrongClasses Should be destructed!!");
 
    return 0;
}

Android中,最常用的肯定不是上面两种:

  • 强强引用——互不相让,互相绑死,这是绝对禁止的。
  • 弱弱引用——互不相干,各管生死。这个对于想要使用引用计数自动管理对象生命周期来说,没什么用处。

最常用的一般是强弱引用关系。强弱引用需要是有从属关系的,具体那个类是用sp引用,哪个是用wp引用,要看设计的逻辑了。

测试示例:

void testCrossRef(){
 sp<Bigclass> A = new Bigclass("testNormalClassA");
 sp<Bigclass> B = new Bigclass("testNormalClassB");
 
  A->setStrongRefs(B);
  B->setWeakRefs(A);
}

这种情况下,消除了循环引用,没有了内存泄露问题。 和上一个弱弱引用的例子比较,这里testNormalClassB的析构在testWeakClassA之后,testWeakClassB的生命周期是受testWeakClassA控制的,只有testWeakClassA析构,testWeakClassB才会析构。(上面的弱弱引用的测例,说明在无干预的情况下,应该是testWeakClassB先析构的)

对于强弱指针的使用,使用弱指针是需要特别注意,弱指针指向的对象,可能已经被销毁了,使用前需要通过promote()方法探测一下,详细信息可参考《深入理解Android》

循环引用问题2

namespace android {
 
class Bigclass : public RefBase 
{ 
public:
    Bigclass(char *name) {
        strcpy(mName, name);
        ALOGD("Construct: %s", mName);
    }
 
    ~Bigclass() {
        ALOGD("destruct: %s", mName);
    }
    
    void setStrongRefs(sp<Bigclass> b) {
        spB = b;
    }       
 
    void setWeakRefs(sp<Bigclass> b) {
        ALOGD("--1---%s------", mName);
        wpB = b;
        sp<Bigclass> s = wpB.promote();    // 这里 promote 会将 弱引用转换为 强引用,会不会引起 retain cycle 呢?
        if (s != NULL) {
            s->printName();
        }
        ALOGD("--2---%s------", mName);
    }

    void printName() {
        ALOGD("Name : %s", mName);
    }
 
private:    
    sp<Bigclass> spB;
    wp<Bigclass> wpB;
    char mName[64]; 
};
 
};


void testStrongCrossRef()
{
    sp<Bigclass> A = new Bigclass("testStrongClassA");
    sp<Bigclass> B = new Bigclass("testStrongClassB");
  
    A->setWeakRefs(B);
    B->setWeakRefs(A);
}
 
int main()
{
    ALOGD("Start testStrongClasses..");  
    testStrongCrossRef();
    ALOGD("testStrongClasses Should be destructed!!");
 
    return 0;
}

答案是: 不会.

上述例子中,只要 强引用计数 没有增加到 3, 就不会 retain cycle.

在实际参数到形式参数的传递中,也就是形式参数中的 wp 构造,并没有增加 引用计数.所以没有问题.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 指针 在传统的C++编程中,指针的使用一直是一把双刃剑。指针赋予了我们直接操作硬件地址的能力,但同时也带来了诸多问...
    passerbywhu阅读 2,831评论 0 2
  • 前言 Java 和 C/C++ 的一个重大区别,就是它没有"指针"的概念,这并不代表 Java 不需要只用指针,而...
    seraphzxz阅读 2,471评论 0 54
  • Android跨进程通信IPC整体内容如下 1、Android跨进程通信IPC之1——Linux基础2、Andro...
    隔壁老李头阅读 4,766评论 2 5
  • 引言:由于未来需要深入android底层进行系统级别的开发,所以最近在看老罗的《Android系统源代码情景分析》...
    拿破轮阅读 2,192评论 0 9
  • 下面是android 7.1.1中的源码先从简单的LightRefBase开始, 它里面只用了简单的mCount来...
    康迪437阅读 1,533评论 0 50