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,如需转载请自行联系原作者

目录
相关文章
|
3月前
|
安全 API 开发工具
Android平台RTMP推送|轻量级RTSP服务如何实现麦克风|扬声器声音采集切换
Android平台扬声器播放声音的采集,在无纸化同屏等场景下,意义很大,早期低版本的Android设备,是没法直接采集扬声器audio的(从Android 10开始支持),所以,如果需要采集扬声器audio,需要先做系统版本判断,添加相应的权限。
|
3月前
|
编解码 开发工具 Android开发
Android平台实现屏幕录制(屏幕投影)|音频播放采集|麦克风采集并推送RTMP或轻量级RTSP服务
Android平台屏幕采集、音频播放声音采集、麦克风采集编码打包推送到RTMP和轻量级RTSP服务的相关技术实现,做成高稳定低延迟的同屏系统,还需要有配套好的RTMP、RTSP直播播放器
|
4月前
|
数据处理 开发工具 数据安全/隐私保护
Android平台RTMP推送|轻量级RTSP服务|GB28181接入之文字、png图片水印的精进之路
本文探讨了Android平台上推流模块中添加文字与PNG水印的技术演进。自2015年起,为了满足应急指挥及安防领域的需求,逐步发展出三代水印技术:第一代为静态文字与图像水印;第二代实现了动态更新水印内容的能力,例如实时位置与时间信息;至第三代,则优化了数据传输效率,直接使用Bitmap对象传递水印数据至JNI层,减少了内存拷贝次数。这些迭代不仅提升了用户体验和技术效率,也体现了开发者追求极致与不断创新的精神。
|
4月前
|
数据采集 编解码 开发工具
Android平台实现无纸化同屏并推送RTMP或轻量级RTSP服务(毫秒级延迟)
一个好的无纸化同屏系统,需要考虑的有整体组网、分辨率、码率、实时延迟、音视频同步和连续性等各个指标,做容易,做好难
|
4月前
|
监控 开发工具 Android开发
Android平台实现RTSP拉流转发至轻量级RTSP服务
为满足Android平台上从外部RTSP摄像头拉流并提供轻量级RTSP服务的需求,利用大牛直播SDK实现了相关功能。SDK支持开始与停止拉流、音频视频数据回调处理及RTSP服务的启动与发布等操作。拉流仅需将未解码数据回调,对性能影响小。音频和视频数据经由特定接口传递给发布端进行处理。此外,SDK还提供了获取RTSP会话数量的功能。此方案适用于监控和巡检等低延迟应用场景,并支持二次水印添加等功能。
|
4月前
|
开发者 算法 虚拟化
惊爆!Uno Platform 调试与性能分析终极攻略,从工具运用到代码优化,带你攻克开发难题成就完美应用
【8月更文挑战第31天】在 Uno Platform 中,调试可通过 Visual Studio 设置断点和逐步执行代码实现,同时浏览器开发者工具有助于 Web 版本调试。性能分析则利用 Visual Studio 的性能分析器检查 CPU 和内存使用情况,还可通过记录时间戳进行简单分析。优化性能涉及代码逻辑优化、资源管理和用户界面简化,综合利用平台提供的工具和技术,确保应用高效稳定运行。
97 0
|
4月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
全面解析TensorFlow Lite:从模型转换到Android应用集成,教你如何在移动设备上轻松部署轻量级机器学习模型,实现高效本地推理
【8月更文挑战第31天】本文通过技术综述介绍了如何使用TensorFlow Lite将机器学习模型部署至移动设备。从创建、训练模型开始,详细演示了模型向TensorFlow Lite格式的转换过程,并指导如何在Android应用中集成该模型以实现预测功能,突显了TensorFlow Lite在资源受限环境中的优势及灵活性。
381 0
|
5月前
|
运维
系统日志使用问题之如何防止在打印参数时遇到NPE(空指针异常)
系统日志使用问题之如何防止在打印参数时遇到NPE(空指针异常)
|
4月前
|
编解码 API 开发工具
Android平台轻量级RTSP服务模块二次封装版调用说明
本文介绍了Android平台上轻量级RTSP服务模块的二次封装实践,旨在简化开发流程,让开发者能更专注于业务逻辑。通过`LibPublisherWrapper`类提供的API,可在应用中轻松初始化RTSP服务、配置视频参数(如分辨率、编码类型)、启动与停止RTSP服务及流发布,并获取RTSP会话数量。此外,还展示了如何处理音频和视频数据的采集与推送。最后,文章提供了从启动服务到销毁资源的完整示例,帮助开发者快速集成实时流媒体功能。
|
4月前
|
编解码 开发工具 Android开发
Android平台轻量级RTSP服务模块技术接入说明
为满足内网无纸化/电子教室等内网超低延迟需求,避免让用户配置单独的服务器,大牛直播SDK在推送端发布了轻量级RTSP服务SDK。 轻量级RTSP服务解决的核心痛点是避免用户或者开发者单独部署RTSP或者RTMP服务,实现本地的音视频数据(如摄像头、麦克风),编码后,汇聚到内置RTSP服务,对外提供可供拉流的RTSP URL,轻量级RTSP服务,适用于内网环境下,对并发要求不高的场景,支持H.264/H.265,支持RTSP鉴权、单播、组播模式,考虑到单个服务承载能力,我们支持同时创建多个RTSP服务,并支持获取当前RTSP服务会话连接数。