Android P 源码分析 2 - 强弱指针的实现

继上篇我们学习了 Android 轻量级指针的实现,是时候来看“重量级”指针的实现了。在 Android 里,“重量级”指针指的是 RefBasesp/wp 配合使用的情况,它提供了完整的强、弱指针的支持。

考虑这样一种情况,A 持有 B,B 持有 A,C 持有 A。如果只使用简单的引用计数,在 C 释放 A 后,A、B 各自的计数值都为 1,永远不会被销毁,也无法再访问。这就是经典的循环引用问题。

引入弱指针后,我们可以让 A 持有 B 的强指针,而 B 指持有 A 的弱指针。这样一来,在 C 释放 A 后,A 的引用计数将降为 0 从而被销魂;A 销毁的同时,A 所持有的 B 的强指针也会销毁,于是 B 的引用计数也降为 0,B 被销毁。

了解了这些基础知识后,下面我们就来看看 RefBase 的源码

RefBase

类定义

这里我先把 RefBase 的定义摆上来,后面我们捡最重要的几个看。

// system/core/libutils/include/utils/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:
        weakref_impl* const mRefs;
};

在看他的函数的实现前,我们先对比一下 LightRefBase,看看他们两个有什么不同。首先最明显的是,RefBase 不是一个类模板,这个我们在上篇已经提到了;也因此 RefBase::~RefBase 是一个虚函数。其次,RefBase 还定义了一个 weakref_type,他的真正实现是 weakref_impl,所有的引用计数都记录在 weakref_impl 里。

好事者这个时候就要问了,为什么 RefBase 不像 LightRefBase 把引用计数直接用成员变量来存储?(人家这么写,肯定是有理由的呀)这里的关键就在弱指针上。当用户持有弱指针的时候,需要提供一种途径,让他尝试转换成强指针。如果把引用计数等信息都存放在 RefBase 里,当对象已经销毁但有弱指针指向它的时候,

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值