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;
}
相关文章:
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_i…...
ipv6上网配置
一般现在的宽带都已经支持ipv6了,但是需要一些配置才能真正用上ipv6。记录一下配置过程。 当前测试环境为移动宽带,光猫下面接了一个路由器,家里所有的设备都挂到这个路由器下面的。 1. 光猫改桥接 光猫在使用路由模式下,ipv6无…...
python实现聚类技术—复杂网络社团检测 附完整代码
实验内容 某跆拳道俱乐部数据由 34 个节点组成,由于管理上的分歧,俱乐部要分解成两个社团。 该实验的任务即:要求我们在给定的复杂网络上检测出两个社团。 分析与设计 实验思路分析如下: 聚类算法通常可以描述为用相似度来衡量两个数据的远近,搜索可能的划分方案,使得目标…...
如何判断两架飞机在汇聚飞行?(如何计算两架飞机的航向夹角?)内含程序源码
ok,在开始一切之前,让我先猜一猜,你是不是想百度“二维平面下如何计算两个移动物体的航向夹角?”如果是,那就请继续往下看。 首先,我们要明确一个概念:航向角≠航向夹角!࿰…...
Scipy稀疏矩阵bsr_array
文章目录基本原理初始化内置方法基本原理 bsr,即Block Sparse Row,bsr_array即块稀疏行矩阵,顾名思义就是将稀疏矩阵分割成一个个非0的子块,然后对这些子块进行存储。通过输入维度,可以创建一个空的bsr数组࿰…...
LeetCode笔记:Weekly Contest 332
LeetCode笔记:Weekly Contest 332 1. 题目一 1. 解题思路2. 代码实现 2. 题目二 1. 解题思路2. 代码实现 3. 题目三 1. 解题思路2. 代码实现 4. 题目四 1. 解题思路2. 代码实现 比赛链接:https://leetcode.com/contest/weekly-contest-332/ 1. 题目一…...
autox.js在vscode(win7)与雷神模拟器上的开发环境配置
目录 下载autox.js 安装autox.js? 在电脑上搭建autox.js开发环境 安装vscode 安装autox.js插件 雷神模拟器连接vscode 设置雷神模拟器IP 设置autox.js应用IP地址等 下载autox.js 大体来说,就是一个运行在Android平台上的JavaScript 运行环境 和…...
创建阿里云物联网平台
创建阿里云物联网平台 对云平台设备创建过程做记录,懒得再看视频 文章参考视频:https://www.bilibili.com/video/BV1jP4y1E7TJ?p26&vd_source50694678ae937a743c59db6b5ff46c31 阿里云:https://www.aliyun.com 1.物联网平…...
【链式二叉树】数据结构链式二叉树的(万字详解)
前言: 在上一篇博客中,我们已经详解学习了堆的基本知识,今天带大家进入的是二叉树的另外一种存储方式----“链式二叉树”的学习,主要用到的就是“递归思想”!! 本文目录1.链式二叉树的实现1.1前置说明1.2结…...
Koa2篇-简单介绍及使用
一.简介koa2是基于 Node.js 平台的下一代 web 开发框架, 致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 可以避免异步嵌套. express中间件是异步回调,Koa2原生支持async/await二.async/awaitconst { rejects } require("assert"); const { resolve } req…...
Linux ALSA 之十一:ALSA ASOC Path 完整路径追踪
ALSA ASOC Path 完整路径追踪一、ASoc Path 简介二、ASoc Path 完整路径2.1 tinymix 设置2.2 完整路径 route一、ASoc Path 简介 如前面小节所描述,ASoc 中 Machine Driver 是 platform driver 和 codec driver 的粘合剂,audio path 离不开 FE/BE/DAI l…...
【Spring Cloud总结】1、服务提供者与服务消费者快速上手
目录 文件结构 代码 1、api 1.1实体类(Dept ) 1.2数据库 2、provider 2.1 DeptController 2.2 DeptDao 2.3 DeptService 2.4 DeptServiceImpl 2.5 application.yml 3、consumer 3.1 ConfigBean 3.2 DeptConsumerController 测试 1.启动…...
若依项目学习之登录生成验证码
若依项目学习之登录生成验证码 使用DefaultKaptcha生成验证码 /*** 验证码配置* * author ruoyi*/ Configuration public class CaptchaConfig {/*** 生成字符类型的验证码**/Bean(name "captchaProducer")public DefaultKaptcha getKaptchaBean(){DefaultKaptcha…...
计算机网络5:数据在两台计算机之间是怎样传输的?
数据在两台计算机之间的传输总的来说包括了封装和解封两个过程 封装(5层协议) 以传送一张图片为例 **应用层:**将jpg格式的图片数据转化成计算机可以识别的0101的二进制的比特流 **传输层:**将应用层传输下来的数据进行分段&…...
就现在!为元宇宙和Web3对互联网的改造做准备!
欢迎来到Hubbleverse 🌍 关注我们 关注宇宙新鲜事 📌 预计阅读时长:8分钟 本文仅代表作者个人观点,不代表平台意见,不构成投资建议。 如今,互联网是各种不同的网站、应用程序和平台的集合。由于彼此分离…...
【mysql数据库】
目录SQL数据库分页聚合函数表跟表之间的关联关系SQL中怎么将行转成列SQL注入将一张表的部分数据更新到另一张表WHERE和HAVING的区别索引索引分类如何创建及保存MySQL的索引?怎么判断要不要加索引?索引设计原理只要创建了索引,就一定会走索引吗…...
【测试开发】web 自动化测试 --- selenium4
目录1. 什么是自动化为什么要做自动化2. 为什么选择selenium作为我使用的web自动化工具3. 什么是驱动?驱动的工作原理是什么5. 第一个自动化程序演示6. selenium基本语法6.1 定位元素的方法6.2 操作页面元素6.3 等待6.4 信息打印获取当前页面句柄,窗口切…...
Elasticsearch7.8.0版本进阶——路由计算
目录一、路由计算1.1、路由计算的前提理解1.2、路由计算的概述1.3、路由计算的概述一、路由计算 1.1、路由计算的前提理解 当索引一个文档的时候,文档会被存储到一个主分片中。Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时…...
c#反射-获取属性和字段的值
演示类 示例类具有一个私有实例字段,一个实例属性,一个实例字段,一个静态私有属性。 class Fight {private int hp;public int Hp{get > hp; set{if (value > 0){ hp value; }else if (-value > Def){ hp value - Def; }}}publi…...
前后端分离-小项目-1前端布局
技术栈前后端分离开发,前端主体框架Vue3后端基础框架Spring-Boot1.前端技术栈:Vue3AxiosElementPlus2.后端技术栈:Spring BootMyBatis Plus3.数据库-MySQL4.项目的依赖管理-Maven5.分页-MyBatis Plus的分页插件环境搭建安装Node.js LTSnode.j…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
