Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析(2)

简介:

  3. 强指针

       强指针所使用的引用计数类为RefBase,它LightRefBase类要复杂多了,所以才称后者为轻量级的引用计数基类吧。我们先来看看RefBase类的实现,它定义在frameworks/base/include/utils/RefBase.h文件中:


  
  
  1. class RefBase   
  2. {   
  3. public:   
  4.     void            incStrong(const void* id) const;   
  5.     void            decStrong(const void* id) const;   
  6.    
  7.     void            forceIncStrong(const void* id) const;   
  8.    
  9.     //! DEBUGGING ONLY: Get current strong ref count.   
  10.     int32_t         getStrongCount() const;   
  11.    
  12.     class weakref_type   
  13.     {   
  14.     public:   
  15.         RefBase*            refBase() const;   
  16.    
  17.         void                incWeak(const void* id);   
  18.         void                decWeak(const void* id);   
  19.    
  20.         bool                attemptIncStrong(const void* id);   
  21.    
  22.         //! This is only safe if you have set OBJECT_LIFETIME_FOREVER.   
  23.         bool                attemptIncWeak(const void* id);   
  24.    
  25.         //! DEBUGGING ONLY: Get current weak ref count.   
  26.         int32_t             getWeakCount() const;   
  27.    
  28.         //! DEBUGGING ONLY: Print references held on object.   
  29.         void                printRefs() const;   
  30.    
  31.         //! DEBUGGING ONLY: Enable tracking for this object.   
  32.         // enable -- enable/disable tracking   
  33.         // retain -- when tracking is enable, if true, then we save a stack trace   
  34.         //           for each reference and dereference; when retain == false, we   
  35.         //           match up references and dereferences and keep only the    
  36.         //           outstanding ones.   
  37.    
  38.         void                trackMe(bool enable, bool retain);   
  39.     };   
  40.    
  41.     weakref_type*   createWeak(const void* id) const;   
  42.    
  43.     weakref_type*   getWeakRefs() const;   
  44.    
  45.     //! DEBUGGING ONLY: Print references held on object.   
  46.     inline  void            printRefs() const { getWeakRefs()->printRefs(); }   
  47.    
  48.     //! DEBUGGING ONLY: Enable tracking of object.   
  49.     inline  void            trackMe(bool enable, bool retain)   
  50.     {   
  51.         getWeakRefs()->trackMe(enable, retain);   
  52.     }   
  53.    
  54. protected:   
  55.     RefBase();   
  56.     virtual                 ~RefBase();   
  57.    
  58.     //! Flags for extendObjectLifetime()   
  59.     enum {   
  60.         OBJECT_LIFETIME_WEAK    = 0x0001,   
  61.         OBJECT_LIFETIME_FOREVER = 0x0003   
  62.     };   
  63.    
  64.     void            extendObjectLifetime(int32_t mode);   
  65.    
  66.     //! Flags for onIncStrongAttempted()   
  67.     enum {   
  68.         FIRST_INC_STRONG = 0x0001   
  69.     };   
  70.    
  71.     virtual void            onFirstRef();   
  72.     virtual void            onLastStrongRef(const void* id);   
  73.     virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);   
  74.     virtual void            onLastWeakRef(const void* id);   
  75.    
  76. private:   
  77.     friend class weakref_type;   
  78.     class weakref_impl;   
  79.    
  80.     RefBase(const RefBase& o);   
  81.     RefBase&        operator=(const RefBase& o);   
  82.    
  83.     weakref_impl* const mRefs;   
  84. };   

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

     RefBase类的成员变量mRefs的类型为weakref_impl指针,它实现在frameworks/base/libs/utils/RefBase.cpp文件中:


  
  
  1. class RefBase::weakref_impl : public RefBase::weakref_type   
  2. {   
  3. public:   
  4.     volatile int32_t    mStrong;   
  5.     volatile int32_t    mWeak;   
  6.     RefBase* const      mBase;   
  7.     volatile int32_t    mFlags;   
  8.    
  9.    
  10. #if !DEBUG_REFS   
  11.    
  12.     weakref_impl(RefBase* base)   
  13.         : mStrong(INITIAL_STRONG_VALUE)   
  14.         , mWeak(0)   
  15.         , mBase(base)   
  16.         , mFlags(0)   
  17.     {   
  18.     }   
  19.    
  20.     void addStrongRef(const void* /*id*/) { }   
  21.     void removeStrongRef(const void* /*id*/) { }   
  22.     void addWeakRef(const void* /*id*/) { }   
  23.     void removeWeakRef(const void* /*id*/) { }   
  24.     void printRefs() const { }   
  25.     void trackMe(bool, bool) { }   
  26.    
  27. #else   
  28.     weakref_impl(RefBase* base)   
  29.         : mStrong(INITIAL_STRONG_VALUE)   
  30.         , mWeak(0)   
  31.         , mBase(base)   
  32.         , mFlags(0)   
  33.         , mStrongRefs(NULL)   
  34.         , mWeakRefs(NULL)   
  35.         , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)   
  36.         , mRetain(false)   
  37.     {   
  38.         //LOGI("NEW weakref_impl %p for RefBase %p", this, base);   
  39.     }   
  40.    
  41.     ~weakref_impl()   
  42.     {   
  43.         LOG_ALWAYS_FATAL_IF(!mRetain && mStrongRefs != NULL"Strong references remain!");   
  44.         LOG_ALWAYS_FATAL_IF(!mRetain && mWeakRefs != NULL"Weak references remain!");   
  45.     }   
  46.    
  47.     void addStrongRef(const void* id)   
  48.     {   
  49.         addRef(&mStrongRefs, id, mStrong);   
  50.     }   
  51.    
  52.     void removeStrongRef(const void* id)   
  53.     {   
  54.         if (!mRetain)   
  55.             removeRef(&mStrongRefs, id);   
  56.         else   
  57.             addRef(&mStrongRefs, id, -mStrong);   
  58.     }   
  59.    
  60.     void addWeakRef(const void* id)   
  61.     {   
  62.         addRef(&mWeakRefs, id, mWeak);   
  63.     }   
  64.     void removeWeakRef(const void* id)   
  65.     {   
  66.         if (!mRetain)   
  67.             removeRef(&mWeakRefs, id);   
  68.         else   
  69.             addRef(&mWeakRefs, id, -mWeak);   
  70.     }   
  71.    
  72.     void trackMe(bool track, bool retain)   
  73.     {   
  74.         mTrackEnabled = track;   
  75.         mRetain = retain;   
  76.     }   
  77.    
  78.     ......   
  79.    
  80. private:   
  81.     struct ref_entry   
  82.     {   
  83.         ref_entry* next;   
  84.         const void* id;   
  85. #if DEBUG_REFS_CALLSTACK_ENABLED   
  86.         CallStack stack;   
  87. #endif   
  88.         int32_t ref;   
  89.     };   
  90.    
  91.     void addRef(ref_entry** refs, const void* id, int32_t mRef)   
  92.     {   
  93.         if (mTrackEnabled) {   
  94.             AutoMutex _l(mMutex);   
  95.             ref_entry* ref = new ref_entry;   
  96.             // Reference count at the time of the snapshot, but before the   
  97.             // update.  Positive value means we increment, negative--we   
  98.             // decrement the reference count.   
  99.             ref->ref = mRef;   
  100.             ref->id = id;   
  101. #if DEBUG_REFS_CALLSTACK_ENABLED   
  102.             ref->stack.update(2);   
  103. #endif   
  104.    
  105.             ref->next = *refs;   
  106.             *refs = ref;   
  107.         }   
  108.     }   
  109.    
  110.     void removeRef(ref_entry** refs, const void* id)   
  111.     {   
  112.         if (mTrackEnabled) {   
  113.             AutoMutex _l(mMutex);   
  114.    
  115.             ref_entry* ref = *refs;   
  116.             while (ref != NULL) {   
  117.                 if (ref->id == id) {   
  118.                     *refs = ref->next;   
  119.                     delete ref;   
  120.                     return;   
  121.                 }   
  122.    
  123.                 refs = &ref->next;   
  124.                 ref = *refs;   
  125.             }   
  126.    
  127.             LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p (weakref_type %p) that doesn't exist!",   
  128.                 id, mBase, this);   
  129.         }   
  130.     }   
  131.    
  132.     ......   
  133.    
  134.     Mutex mMutex;   
  135.     ref_entry* mStrongRefs;   
  136.     ref_entry* mWeakRefs;   
  137.    
  138.     bool mTrackEnabled;   
  139.     // Collect stack traces on addref and removeref, instead of deleting the stack references   
  140.     // on removeref that match the address ones.   
  141.     bool mRetain;   
  142.    
  143.     ......   
  144. #endif   
  145. };   

这个类看起来实现得很复杂,其实不然,这个类的实现可以分成两部分:

  1. #if !DEBUG_REFS  
  2.   
  3. ......  
  4.   
  5. #else  

  编译指令之间的这部分源代码是Release版本的源代码,它的成员函数都是空实现;

  1. #else   
  2.   
  3. ......  
  4.   
  5. #endif  

   编译指令之间的部分源代码是Debug版本的源代码,它的成员函数都是有实现的,实现这些函数的目的都是为了方便开发人员调试引用计数用的,除此之外,还在内部实现了一个结构体ref_entry:


  
  
  1. struct ref_entry   
  2. {   
  3.     ref_entry* next;   
  4.     const void* id;   
  5. #if DEBUG_REFS_CALLSTACK_ENABLED   
  6.     CallStack stack;   
  7. #endif   
  8.     int32_t ref;   
  9. };   

   这个结构体也是为了方便调试而使用的,我们可以不关注这部分用于调试的代码。

        总的来说,weakref_impl类只要提供了以下四个成员变量来维护对象的引用计数:


  
  
  1. volatile int32_t    mStrong;   
  2. volatile int32_t    mWeak;   
  3. RefBase* const      mBase;   
  4. volatile int32_t    mFlags;   

   其中mStrong和mWeak分别表示对象的强引用计数和弱引用计数;RefBase类包含了一个weakref_impl类指针mRefs,而这里的weakref_impl类也有一个成员变量mBase来指向它的宿主类RefBase;mFlags是一个标志位,它指示了维护对象引用计数所使用的策略,后面我们将会分析到,它的取值为0,或者以下的枚举值:


  
  
  1. //! Flags for extendObjectLifetime()   
  2.     enum {   
  3.         OBJECT_LIFETIME_WEAK    = 0x0001,   
  4.         OBJECT_LIFETIME_FOREVER = 0x0003   
  5.     };   

这里我们还需要注意的一点的是,从weakref_impl的类名来看,它应该是一个实现类,那么,就必然有一个对应的接口类,这个对应的接口类的就是RefBase类内部定义的weakref_type类了,这是一种把类的实现与接口定义分离的设计方法。学习过设计模式的读者应该知道,在设计模式里面,非常强调类的接口定义和类的实现分离,以便利于后续扩展和维护,这里就是用到了这种设计思想。

 

        说了这多,RefBase类给人的感觉还是挺复杂的,不要紧,我们一步步来,先通过下面这个图来梳理一下这些类之间的关系:

 从这个类图可以看出,每一个RefBase对象包含了一个weakref_impl对象,而weakref_impl对象实现了weakref_type接口,同时它可以包含多个ref_entry对象,前面说过,ref_entry是调试用的一个结构体,实际使用中可以不关注。





本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966559,如需转载请自行联系原作者

目录
相关文章
|
7月前
|
搜索推荐 C语言 C++
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现3
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现
|
7月前
|
存储
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现2
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现
|
7月前
|
C语言
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现1
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现
|
5月前
|
运维
系统日志使用问题之如何防止在打印参数时遇到NPE(空指针异常)
系统日志使用问题之如何防止在打印参数时遇到NPE(空指针异常)
|
6月前
|
C++
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
|
7月前
入门后指针进阶习题深度分析
入门后指针进阶习题深度分析
42 1
|
7月前
|
机器学习/深度学习 计算机视觉
LabVIEW开发自动读取指针式仪表测试系统
LabVIEW开发自动读取指针式仪表测试系统
60 7
|
7月前
|
存储 C语言
链表—初始化指针变和创建新的节点------区别应用分析
链表—初始化指针变和创建新的节点------区别应用分析
|
7月前
|
设计模式 安全 Java
【Linux 系统】多线程(生产者消费者模型、线程池、STL+智能指针与线程安全、读者写者问题)-- 详解
【Linux 系统】多线程(生产者消费者模型、线程池、STL+智能指针与线程安全、读者写者问题)-- 详解
|
7月前
|
搜索推荐 算法
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现4
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现