当前位置: 首页 > news >正文

Android系统之onFirstRef自动调用原理

前言:抽丝剥茧探究onFirstRef究竟为何在初始化sp<xxx>第一个调用?

1.onFirstRef调用位置

<1>.system/core/libutils/RefBase.cpp

#include <utils/RefBase.h>//1.初始化强指针
void RefBase::incStrong(const void* id) const
{weakref_impl* const refs = mRefs;refs->incWeak(id);refs->addStrongRef(id);const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);refs->mBase->onFirstRef();//调用onFirstRef
}//2.weakref_impl类
class RefBase::weakref_impl : public RefBase::weakref_type
{public:RefBase* const  mBase; //RefBase定义全局变量mBase.
};

RefBase基类中定义调用onFirstRef(),如果有实例化sp<T> ttt = new Test()后,将会自动调用onFirstRef()函数。

<2>.system/core/libutils/RefBase.cpp

void RefBase::decStrong(const void* id) const
{weakref_impl* const refs = mRefs;refs->removeStrongRef(id);const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);//在调用析构函数时,自动调用onLastStrongRef()函数。refs->mBase->onLastStrongRef(id);}refs->decWeak(id);
}

在sp<T>的析构函数时,会自动调用onLastStrongRef();

2.onFirstRef定义位置

<1>.system/core/libutils/include/utils/RefBase.h

#include <utils/LightRefBase.h>
#include <utils/StrongPointer.h>class RefBase{protected:// Invoked after creation of initial strong pointer/reference.virtual void     onFirstRef();//定义虚函数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);//定义onLastStrongRefprivate:weakref_impl* const mRefs;};

在RefBase中定义虚函数onFirstRef()、onLastStrongRef()、以及weakref_impl类。

3.sp<T>实现位置

<1>.system/core/libutils/include/utils/StrongPointer.h

sp<T>构造函数

template<typename T>
sp<T>::sp(const sp<T>& other): m_ptr(other.m_ptr) {if (m_ptr)m_ptr->incStrong(this);
}

StrongPointer.h头文件中才是真正定义sp<T>智能指针的强指针的出处。

~sp<T>析构函数

template<typename T>
sp<T>::~sp() {if (m_ptr)m_ptr->decStrong(this);
}

4.Test onFirstRef Sample

写了一个sample帮助理解RefBase结构的onFirstRef原理。

<1>.Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)LOCAL_SRC_FILES := main.cpp
LOCAL_SHARED_LIBRARIES := libcutils libutils liblog libbaseLOCAL_MODULE := test_onfirstRef
include $(BUILD_EXECUTABLE)

<2>.main.cpp

#define LOG_TAG "Main"#include <utils/Log.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>//using namespace android;/*
1.system/core/libutils/include/utils/RefBase.hclass RefBase{protected:// Invoked after creation of initial strong pointer/reference.virtual void            onFirstRef();};2.system/core/libutils/include/utils/Threads.hclass Thread : virtual public RefBase{public:virtual status_t run(const char* name,int32_t priority = PRIORITY_DEFAULT, size_t stack = 0);private:virtual bool threadLoop() = 0;};3.system/core/libutils/Threads.cppstatus_t Thread::run(const char* name, int32_t priority, size_t stack){res = androidCreateRawThreadEtc(_threadLoop,this, name, priority, stack, &mThread);}
*/class Test: public android::RefBase {
public:// Test(int id, char *name){//   printf("xxx------->%s(), line = %d, id = %d, name = %s\n",__FUNCTION__,__LINE__,id,name);// }void onFirstRef(){printf("xxx------->%s(), line = %d\n",__FUNCTION__,__LINE__);}void onLastStrongRef(__unused const void* id){printf("xxx------->%s(), line = %d\n",__FUNCTION__,__LINE__);}bool onIncStrongAttempted(__unused uint32_t flags, __unused const void* id){printf("xxx------->%s(), line = %d\n",__FUNCTION__,__LINE__);return true;}void onLastWeakRef(__unused const void* id){printf("xxx------->%s(), line = %d\n",__FUNCTION__,__LINE__);}
};void print(android::sp<Test> tt){printf("xxx------------->%s(), line = %d, strong_count = %d\n",__FUNCTION__,__LINE__,tt->getStrongCount());
}int main(){//char name[] = "onFirstRef";//1.没有调用onFirstRef//new Test(1234, name);//2.sp强智能指针自动调用onFirstRefandroid::sp<Test>  test = new Test(); //invoke onFirstRef() and onLastStrongRef().printf("xxx------------->%s(), line = %d, strong_count = %d\n",__FUNCTION__,__LINE__,test->getStrongCount());//3.wp弱智能指针// android::wp<Test> wp_test = new Test();// android::sp<Test> sp_test =  wp_test.promote(); // invoke onLastStrongRef()// printf("xxx------------->%s(), line = %d, strong_count = %d\n",__FUNCTION__,__LINE__,sp_test->getStrongCount());//4.将普通引用修改为常引用,为了避免函数使用时,防止test对象被修改.const android::sp<Test>  &test = new Test(); //invoke onFirstRef() and onLastStrongRef().//android::sp<Test>  &test = new Test(); //编译报错printf("xxx------------->%s(), line = %d, strong_count = %d\n",__FUNCTION__,__LINE__,test->getStrongCount());print(new Test());return 0;
}
http://www.lryc.cn/news/4339.html

相关文章:

  • ipv6上网配置
  • python实现聚类技术—复杂网络社团检测 附完整代码
  • 如何判断两架飞机在汇聚飞行?(如何计算两架飞机的航向夹角?)内含程序源码
  • Scipy稀疏矩阵bsr_array
  • LeetCode笔记:Weekly Contest 332
  • autox.js在vscode(win7)与雷神模拟器上的开发环境配置
  • 创建阿里云物联网平台
  • 【链式二叉树】数据结构链式二叉树的(万字详解)
  • Koa2篇-简单介绍及使用
  • Linux ALSA 之十一:ALSA ASOC Path 完整路径追踪
  • 【Spring Cloud总结】1、服务提供者与服务消费者快速上手
  • 若依项目学习之登录生成验证码
  • 计算机网络5:数据在两台计算机之间是怎样传输的?
  • 就现在!为元宇宙和Web3对互联网的改造做准备!
  • 【mysql数据库】
  • 【测试开发】web 自动化测试 --- selenium4
  • Elasticsearch7.8.0版本进阶——路由计算
  • c#反射-获取属性和字段的值
  • 前后端分离-小项目-1前端布局
  • 基于jsp的网络电子相册的设计与实现
  • Python快速上手系列--类--详解篇
  • Dubbo基本原理和用法讲解
  • TCP详解及面试相关问题
  • LVGL V9.0基于VS2022仿真搭建
  • 多线程面试题开胃菜2(5道)
  • 第三次作业
  • 基础算法(直接插入,希尔排序,快排,归并,折半查找)
  • 电子学会2022年12月青少年软件编程(图形化)等级考试试卷(一级)答案解析
  • 基于JAVA的超级玛丽设计与实现
  • 硬件工程师入门基础知识(一)基础元器件认识(二)