android智能指针

下面是android 7.1.1中的源码
先从简单的LightRefBase开始, 它里面只用了简单的mCount来计数.

## LightRefBase

template 
class LightRefBase
{
    public:
    inline LightRefBase() : mCount(0) { }
    //计数+1
    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 {
    //计数-1, 返回减1之前的值
       if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
            std::atomic_thread_fence(std::memory_order_acquire);
            delete static_cast(this); //如果减掉后引用计数为0, 删掉该引用
        }
}
    inline int32_t getStrongCount() const {
        return mCount.load(std::memory_order_relaxed);
    }
    private:
    mutable std::atomic mCount;
};
int main(int argc, char** argv)
{
    //自定义LightClass 继承LightRefBase
    LightClass* pLightClass = new LightClass();
    //调用① sp的一个参数的构造函数
    sp lpOut = pLightClass;
    //pLightClass 引用计数+1, 所以下面输出 1
    printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
 
    {
        //调用② sp的另一个构造函数
        sp lpInner = lpOut;
        //上面pLight的引用计数+1, 所以这里输出2
        printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
    }
    //上面作用域结束所以, lpInner调用析构函数③
    //pLightClass引用计数-1, 这里输出 1
    printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
 
    return 0;            
}

//StrongPointer.h
//① 
template
sp::sp(T* other) //other在上面的例子为pLightClass
        : m_ptr(other) {
    if (other)
        //调用LightRefBase的incStrong, LightRefBase的mCount+1;
        other->incStrong(this);
}
//②
template
sp::sp(const sp& other) //other参数在上面的例子中为lpOut
        : m_ptr(other.m_ptr) { //other.m_ptr为 pLightClass, m_ptr其实就是pLightClass的引用
    if (m_ptr)
        m_ptr->incStrong(this); //引用计数+1
}
//③
template
sp::~sp() {
    if (m_ptr) //m_ptr为pLightClass的引用
        m_ptr->decStrong(this);
}

## RefBase

# RefBase原型
//RefBase.h
class RefBase
{
    private:
        //weakref_impl为RefBase的内部类weakref_type的实现类, 
        //mRefs包含强引用计数, 弱引用计数, flag, 以及指向外部类RefBase的指针mBase
        weakref_impl* const mRefs;  
    protected:
        RefBase(); //构造函数中 new weakref_impl()
        virtual ~RefBase(); //析构做了较多工作
        //! Flags for extendObjectLifetime()
        enum { //没有了forever
            OBJECT_LIFETIME_STRONG  = 0x0000, //对象受强引用控制, 默认
            OBJECT_LIFETIME_WEAK    = 0x0001, //对象受弱引用控制
            OBJECT_LIFETIME_MASK    = 0x0001
        };
    public:
        void incStrong(const void* id) const;
        void decStrong(const void* id) const;
        weakref_type*   createWeak(const void* id) const;
    //...省略
}

上面是RefBase中的几个重要函数声明, 接下来是weakref_impl的声明

# weakref_type, weakref_impl原型
//RefBase.h
class weakref_type
{
public:
    void incWeak(const void* id);
    void decWeak(const void* id);
    bool attemptIncStrong(const void* id);
    //..省略
}
//RefBase.cpp
class RefBase::weakref_impl : public RefBase::weakref_type //weakref_type定义了几个函数
{
public:
    std::atomic    mStrong; //强引用计数
    std::atomic    mWeak;   //弱引用计数
    RefBase* const          mBase;   //引用外部指针
    std::atomic    mFlags;  //标记
    //..省略空方法
}

后面都是控制weakref_impl对象, 这里只要记住有四个变量, 和加减引用计数的方法, 接下来先看下它们的实现

# weakref_type, weakref_impl实现
//RefBase.cpp
weakref_impl(RefBase* base)
    : mStrong(INITIAL_STRONG_VALUE) //强引用计数默认值
    , mWeak(0)  //弱引用计数0
    , mBase(base) //引用外部对象 RefBase
    , mFlags(0){} //flag默认0, 表示受强引用控制
void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast(this);
    impl->addWeakRef(id); //空方法
    const int32_t c __unused = impl->mWeak.fetch_add(1, //弱引用计数+1
            std::memory_order_relaxed);
}
void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast(this);
    impl->removeWeakRef(id); //空方法
    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); //弱引用-1
    if (c != 1) return; //减1后弱引用计数不为0, 直接返回
    //弱引用计数为0, 接着往下执行
    //弱引用计数>=强引用计数
    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) { 
        // 受强引用计数影响, 默认
        if (impl->mStrong.load(std::memory_order_relaxed)
                == INITIAL_STRONG_VALUE) {
            //如果强引用计数为初始值, 回收RefBase
            delete impl->mBase;
        } else {
            //强引用计数为0, 回收weakref_impl
            delete impl;
        }
    } else {
        // 受弱引用计数控制, 回收RefBase
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;
    }
}

bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
    //该方法是, 弱引用变为强引用, 所以强引用计数+1, 弱引用计数也需要+1
    //这里弱引用计数先+1, 如果变为强引用失败, 则再-1
    incWeak(id);
    
    weakref_impl* const impl = static_cast(this);
    int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);
    
    //下面判断成立, 说明已经有强引用, 说明可以, 升级为强引用
    //while为了解决多线程的问题
    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
        if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                std::memory_order_relaxed)) {
            break;
        }
    }
    
    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
        // 两种情况
        // - 没有过强引用
        // - 或者强引用都被回收了
        int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            // 默认受强引用控制时
            // 当最后的强引用被释放了, 所以curCount<=0
            if (curCount <= 0) {
                // 强引用<=0 肯定是从1减到了0, 根据decStrong()方法, 受强引用控制时, 释放RefBase
                // 所以不能升级为强引用
                decWeak(id); //弱引用计数-1, 因为上面加过1
                return false;
            }

            //curCount为初始值, 说明没有过强引用, 可以尝试一下
            while (curCount > 0) {
                //mStrong + 1
                if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                        std::memory_order_relaxed)) {
                    break;
                }
            }
            if (curCount <= 0) {
                // 其他线程破坏了这次的升级, promote()失败
                decWeak(id);
                return false;
            }
        } else {
            // 受弱引用控制
            // onIncStrongAttempted()默认为true, 但是可以重写该方法
            // 能否promote()成功取决于开发者.
            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
                decWeak(id);
                return false;
            }
            // 可以升级为强引用, 强引用计数+1
            curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
            // 多线程问题, 别的线程动了强引用计数
            if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
                impl->mBase->onLastStrongRef(id);
            }
        }
    }
    impl->addStrongRef(id);// 空方法
    // 修正强引用计数为1
    if (curCount == INITIAL_STRONG_VALUE) {
        impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
                std::memory_order_relaxed);
    }

    return true;
}
# RefBase实现
//RefBase.cpp
RefBase::RefBase() //无参构造函数
    : mRefs(new weakref_impl(this)){}
RefBase::~RefBase() //析构函数
{
    if (mRefs->mStrong.load(std::memory_order_relaxed)
            == INITIAL_STRONG_VALUE) {
        //没有用过强引用, 删除weakref_impl
        delete mRefs;
    } else {
        int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
        if ((flags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
            if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
                //受弱引用控制, 并且若引用计数 = 0, 删除weakref_impl
                delete mRefs;
            }
        }
    }
    // for debugging purposes, clear this.
    const_cast(mRefs) = NULL;
}

//wp中需要调用
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);
    return mRefs;
}
//incStrong
  void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->incWeak(id); //弱引用计数+1
    refs->addStrongRef(id); //空方法
    //强引用+1
    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
    if (c != INITIAL_STRONG_VALUE)  {
        return;
    }
    //强引用默认值为1<<28, 减去1<<28, 现在值为1
    int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
            std::memory_order_relaxed);
    refs->mBase->onFirstRef();
}
  void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);//空方法
    //强引用-1
    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
    if (c == 1) { //减去后强引用计数 = 0
        std::atomic_thread_fence(std::memory_order_acquire);
        refs->mBase->onLastStrongRef(id);//可继承
        int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            //受强引用计数控制, 默认, 删掉RefBase, 并且调用RefBase的析构函数
            delete this;
        }
    }
    refs->decWeak(id);
}
  • RefBase::RefBase()

    new weakref_impl(), weakref_impl初始化

  • RefBase::~RefBase()

    强引用计数为初始值 || (受弱引用控制&&弱引用计数==0) -> 删掉weakref_impl

  • RefBase::incStrong()

    调用 weakref_type::incWeak (弱引用+1)

    强引用+1(如果第一次加1, 那么减掉初始值, 最终为1),

  • RefBase::decStrong()

    强引用-1, 减去后如果强引用计数为0, 并且受强引用控制, 释放RefBase(实际对象)

    调用 weakref_type::decWeak (弱引用-1, 还有其他逻辑)

  • RefBase::weakref_type::incWeak()

    强引用+1

  • RefBase::weakref_type::decWeak()

    弱引用-1, 减去后如果弱引用计数为0, 分两种情况, 受强引用控制, 受弱引用控制

    其实弱引用计数为0, 不管受强引用还是弱引用控制, RefBase和weakref_impl都需要释放, 下面的判断是为了不重复释放

    1. 受强引用控制, 强引用计数为初始值, 释放RefBase, 不为初始值, 释放weakref_impl

      1. 强引用计数为初始值, 释放RefBase, RefBase调用析构函数, 释放weakref_impl

      2. 强引用计数不为初始值说明, 调用过decStrong(), 并且受强引用控制, 所以会释放RefBase, 这里只需再释放weakref_impl就可以了

    2. 受弱引用控制, 释放RefBase

      受弱引用控制, 释放RefBase, RefBase调用析构函数, 释放weakref_impl

  • RefBase::weakref_type::attemptIncStrong()

    不考虑多线程的情况下, 首先如果已经有强引用, 那么可以直接升级强引用.

    当强引用<=0, 或者没有初始化过强引用时分两种情况, 受强引用或者弱引用控制

    1. 受强引用控制

      1. 强引用<=0, 说明RefBase已经被释放了, 升级失败

      2. 强引用为默认值, 说明没有过强引用, 可以升级

    2. 受弱引用控制

      首先判断开发者是否希望可以升级, 默认为true, 升级OK

RefBase的重要函数都说明完了, 接下来是strong pointer和 weak pointer, 如果上面的RefBase弄明白了, sp和wp就很简单, 只要关注它们的构造函数和析构函数, 加上wp的promote()函数即可.

## sp和wp

# sp实现
//StrongPointer.h
template
class sp {
public:
    inline sp() : m_ptr(0) { }
    
    //构造方法很多, 其他也都一样调用RefBase的incStrong()函数
    template
    sp::sp(const sp& other)
        : m_ptr(other.m_ptr) {
        if (m_ptr)
            m_ptr->incStrong(this);
    }
        
    //析构函数
    template
    sp::~sp() {
        if (m_ptr)
            m_ptr->decStrong(this);
    }
    
  
    // 特殊! 用于ProcessState, 不关注
    void force_set(T* other);
  
    // 操作符重载 sp可以自由使用引用对象
    inline  T&      operator* () const  { return *m_ptr; }
    inline  T*      operator-> () const { return m_ptr;  }
    inline  T*      get() const         { return m_ptr; }
    
    // 也是为了 sp自由使用引用对象, 宏定义就不贴了
    COMPARE(==)
    COMPARE(!=)
    COMPARE(>)
    COMPARE(<)
    COMPARE(<=)
    COMPARE(>=)

private:    
    template friend class sp;
    template friend class wp;
    void set_pointer(T* ptr) { m_ptr = ptr; }
    T* m_ptr; //引用对象
};

这里只需明白3点:

  1. 构造函数调用 incStrong(), 强引用+1, 弱引用+1
  2. 析构函数调用 decStrong(), 强引用-1, 弱引用-1 (还有其他一些逻辑)
  3. sp可以自由操作引用对象
# wp实现
//RefBase.h
template 
class wp
{
public:
template //构造函数
    wp::wp(T* other): m_ptr(other)
    {
        //createWeak()方法很简单, 上面有实现, 只是调用下incWeak, 返回weakref_impl对象      
        if (other) m_refs = other->createWeak(this);
    }
template //析构函数
    wp::~wp()
    {
        if (m_ptr) m_refs->decWeak(this);
    }
template
    sp wp::promote() const //重点方法, wp升级sp
    {
        sp result;
        if (m_ptr && m_refs->attemptIncStrong(&result)) {
        result.set_pointer(m_ptr);
    }
    return result; //如果升级失败, 引用对象为空
}  
private:
template friend class sp;
template friend class wp;
T*              m_ptr; //引用对象
weakref_type*   m_refs; //RefBase中的weakref_impl, 因为要调用weakref_impl的方法
};

wp的要明白4点:

  1. 构造函数调用 createWeak(), 弱引用+1
  2. 析构函数调用 decWeak() 弱引用-1 (还有其他一些逻辑)
  3. wp不可以自由操作引用对象
  4. wp的promote()方法, 可以升级为sp, 但是如果升级失败sp的引用对象为空, 所以需要做判断

OK, 智能指针的基本方法都已经讲清楚, 这里用老罗的例子实践一下.

class WeightClass : public RefBase
{
public:
    void printRefCount()
    {
        int32_t strong = getStrongCount();
        weakref_type* ref = getWeakRefs();
        printf("-----------------------\n");
        printf("Strong Ref Count: %d.\n", 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");
    }
};

void TestStrongClass(StrongClass* pStrongClass)
{
    wp wpOut = pStrongClass; //弱引用计数 +1
    pStrongClass->printRefCount();
    
    {
        sp spInner = pStrongClass; //强引用计数+1, 弱引用计数+1
        pStrongClass->printRefCount();
    }//调用sp的析构函数, 强引用 = 0, 弱引用 = 1, 因受强引用控制, 所以对象被删除
    
    sp spOut = wpOut.promote(); //升级失败
    printf("spOut: %p.\n", spOut.get());
}

void TestWeakClass(WeakClass* pWeakClass)
{
    wp wpOut = pWeakClass; //弱引用计数 +1
    pWeakClass->printRefCount();
    
    {
        sp spInner = pWeakClass; //强引用计数+1, 弱引用计数+1
        pWeakClass->printRefCount();
    }//调用sp的析构函数, 强引用 = 0, 弱引用 = 1, 因受弱引用控制, 所以对象不会被删除
    
    pWeakClass->printRefCount();
    sp spOut = wpOut.promote(); //升级成功
    printf("spOut: %p.\n", spOut.get());
}

int main(int argc, const char * argv[]) {
    
    printf("Test Strong Class: \n");
    StrongClass* pStrongClass = new StrongClass();
    TestStrongClass(pStrongClass);
    
    printf("\nTest Weak Class: \n");
    WeakClass* pWeakClass = new WeakClass();
    TestWeakClass(pWeakClass);

    return 0;
}
//输出:
/*
Test Strong Class: 
Construct StrongClass Object.
-----------------------
Strong Ref Count: 268435456.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
Destory StrongClass Object.
spOut: 0x0.


Test Weak Class: 
Construct WeakClass Object.
-----------------------
Strong Ref Count: 268435456.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
spOut: 0x100300060.
Destory WeakClass Object.
*/

你可能感兴趣的:(android智能指针)