Anroid中强指针和弱智针介绍

一 RefBase类介绍

RefBase提供了引用计数器的功能,所有接受sp、wp管理的类都需要继承RefBase。RefBase类定义了一个内部接口类weakref_type,它提供了操作弱引用计数的一系列接口,具体的实现位于weakref_impl类中。RefBase持有weakref_impl*类型的指针成员mRefs,通过mRefs实现对强、弱引用的计数管理。

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);
        bool       attemptIncStrong(const void* id);
    };

    weakref_type*   createWeak(const void* id) const;
    weakref_type*   getWeakRefs() const;
protected:
    RefBase();
    virtual  ~RefBase();

    //! Flags for extendObjectLifetime()
    enum {
        OBJECT_LIFETIME_WEAK    = 0x0001,
        OBJECT_LIFETIME_FOREVER = 0x0003
    };

    void  extendObjectLifetime(int32_t mode);

    //! Flags for onIncStrongAttempted()
    enum {
        FIRST_INC_STRONG = 0x0001
    };

    virtual void  onFirstRef();
    virtual void  onLastStrongRef(const void* id);
    virtual bool  onIncStrongAttempted(uint32_t flags, const void* id);
    virtual void  onLastWeakRef(const void* id);
private:
    friend class weakref_type;
    class weakref_impl;

    RefBase(const RefBase& o);
    RefBase& operator=(const RefBase& o);

    weakref_impl* const mRefs;//管理强、弱引用计数值
};

1. RefBase的构造函数:

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

RefBase在构造函数中创建了weakref_impl类型的对象,以初始化mRefs。

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

可见,构造函数中mStrong为INITIAL_STRONG_VALUE,mWeak为0。

2. RefBase的析构函数

C++中析构函数中务必注意的是申请资源的释放,这里要考虑释放mRef对象。

RefBase::~RefBase()
{
    if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
        // 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) {
                delete mRefs;
            }
        }
    }
    // for debugging purposes, clear this.
    const_cast<weakref_impl*&>(mRefs) = NULL;
}

二 强指针sp

sp对泛型T*类型指针进行了封装,而T就是RefBase或其子类,因此sp或wp就是管理RefBase系列的指针的。

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

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

    // Operator
    COMPARE(==)
    COMPARE(!=)
    COMPARE(>)
    COMPARE(<)
    COMPARE(<=)
    COMPARE(>=)

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

    // Optimization for wp::promote().
    sp(T* p, weakref_type* refs);

    T*              m_ptr;//类型T必须是继承自RefBase。
};

2.1 sp的构造函数

  • 强引用部分
    调用mRefs->addStrongRef()函数,这个在Release版本中什么也不做;
    将mRefs的mStrong加1。注意,mStrong表示被强引用的次数,第一次被引用时mStrong值为1,同时会调用RefBase类的onFirstRef()函数。
  • 弱引用部分
    调用mRefs->incWeak()函数,它包含了:
    将mRefs的mWeak加1,mWeak表示被弱引用的次数;
    调用mRefs的addWeakRef()函数,这个在Release版本中什么也不做。

2.2 sp的析构函数

  • 强引用部分
      调用mRefs的removeStrongRef(),这个在Release版本中为空;
      将mRefs的mStrong减去1,若果是最后一次调用,则:
      首先会调用onLastStrongRef(),默认实现为空,如果需要可以在子类中实现;然后,如果生命周期是受OBJECT_LIFETIME_STRONG控制,则delete当前RefBase对象(注意这里RefBase对象中的mRefs所指weak_impl对象还没有被释放掉,有内存泄露的风险)。
      
  • 弱引用部分
      调用decWeak(), 将mWeak减去1。如果是最后一次引用,则一定要考虑指针释放的问题,如下:
      (1) 如果生命周期是受OBJECT_LIFETIME_STRONG控制,则
      mStrong的值为INITIAL_STRONG_VALUE,表示根本没有创建过sp对象,直接delete RefBase对象,那它里面的mRef指针呢?答案是在RefBase的析构函数中,会判断如果mRefs->mStrong == INITIAL_STRONG_VALUE则delete mRefs。
      mStrong的值不为INITIAL_STRONG_VALUE时,则delete掉 mRefs所指对象。
      (2) 如果生命周期受OBJECT_LIFETIME_WEAK控制,因为这是最后一次弱引用,我们终于可以delete RefBase对象了,那它里面的mRef指针呢?答案是在RefBase的析构函数中,有这样的判断: 
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) {
  delete mRefs;
  }
}

(3) 如果生命周期受OBJECT_LIFETIME_FOREVER控制,什么也不做。

三、 弱指针wp

3.1 wp的构造函数

只有sp中的弱引用部分

3.2 wp的析构函数

只有sp中的弱引用部分

四、弱指针升级为强指针

弱指针wp不能直接操作其封装的T*类型的对象,它没有重载*和->操作符;不过wp类提供了一个将当前的弱指针对象升级为强指针对象的函数promote()。

emplate <typename T>
class wp {
public:
    // promotion to sp
  sp<T> promote() const;
private:
    T*              m_ptr;
    weakref_type*   m_refs;
};

template<typename T>
sp<T> wp<T>::promote() const
{
    return sp<T>(m_ptr, m_refs);
}

可见,升级的方式就是使用变量m_ptr和m_refs来构造一个强指针对象。

template<typename T>
sp<T>::sp(T* p, weakref_type* refs)
    : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
{
}

重点是attemptIncStrong()函数,返回true时即表示可以升级;否则m_ptr为0。具体的方法是:
判断m_refs所持有的mStrong值,用curCount表示,分以下3种情况:

(1) curCount > 0 && curCount != INITIAL_STRONG_VALUE

 表示已经有强指针在引用T对象,所以只需把m_refs所持有的mWeak和mStrong都加1即可;

(2)curCount = INITIAL_STRONG_VALUE

表示对象T还没有被强指针引用过,分两种模式:
OBJECT_LIFETIME_WEAK:默认返回true,不过受限于RefBase::onIncStrongAttempted()的函数返回值(默认true);不过这个函数可以被RefBase的子类修改,如果被重写为返回false则表示设计者不希望升级;
OBJECT_LIFETIME_STRONG: 返回true;

(3)curCount <=0

表示对象T已经被销毁掉,正在尝试救活(revive)它,如果该对象确实有更长的生命周期(longer lifetime)的话是被允许的。
OBJECT_LIFETIME_WEAK:默认返回true,不过受限于RefBase::onIncStrongAttempted()的函数返回值(默认true);不过这个函数可以被RefBase的继承类修改,如果被重写为返回false则表示设计者不希望升级;
OBJECT_LIFETIME_STRONG: 返回false。
如果返回true,则将强、弱引用计数分别加1, 如果是第一次引用,会调用onFirstRef()。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值