iOS - 引用计数(ARC)

news2025/1/9 1:09:02

1. 基本数据结构

// 对象结构
struct objc_object {
    isa_t isa;  // isa 指针,包含引用计数信息
};

// isa 的位域结构
union isa_t {
    uintptr_t bits;
    struct {
        uintptr_t nonpointer        : 1;  // 是否启用优化的 isa 指针
        uintptr_t has_assoc         : 1;  // 是否有关联对象
        uintptr_t has_cxx_dtor      : 1;  // 是否有 C++ 析构函数
        uintptr_t shiftcls          : 33; // 类的指针
        uintptr_t magic             : 6;  // 用于调试
        uintptr_t weakly_referenced : 1;  // 是否有弱引用
        uintptr_t deallocating      : 1;  // 是否正在释放
        uintptr_t has_sidetable_rc  : 1;  // 引用计数是否在 SideTable 中
        uintptr_t extra_rc          : 19; // 额外的引用计数值
    };
}

2. 引用计数存储位置

2.1 isa 优化

inline bool 
objc_object::hasNonpointerIsa() {
    return isa.nonpointer;  // 判断是否使用优化的 isa
}

// 引用计数存储在 isa 的情况
if (isa.nonpointer) {
    // 引用计数存储在 isa.extra_rc 中
    // 最多可存储 2^19 - 1 个引用
}

2.2 SideTable 存储

struct SideTable {
    spinlock_t slock;
    RefcountMap refcnts;  // 引用计数哈希表
    weak_table_t weak_table;  // 弱引用表
};

// 当 isa 中的引用计数溢出时
if (isa.has_sidetable_rc) {
    // 引用计数存储在 SideTable 的 refcnts 中
}

3. 引用计数操作

3.1 retain 操作

id objc_retain(id obj) {
    if (!obj) return obj;
    if (obj->isTaggedPointer()) return obj;
    return obj->retain();
}

inline id 
objc_object::retain() {
    if (isTaggedPointer()) return this;
    
    if (fastpath(!ISA()->hasCustomRR())) {
        if (fastpath(isa.hasNonpointerIsa())) {
            addExtraRC_nolock();
        } else {
            sidetable_retain();
        }
    }
    return this;
}

3.2 release 操作

void objc_release(id obj) {
    if (!obj) return;
    if (obj->isTaggedPointer()) return;
    obj->release();
}

inline bool 
objc_object::release() {
    if (isTaggedPointer()) return false;
    
    if (fastpath(!ISA()->hasCustomRR())) {
        if (fastpath(isa.hasNonpointerIsa())) {
            return sidetable_release(true);
        }
        return sidetable_release(false);
    }
    return false;
}

4. 引用计数溢出处理

void objc_object::sidetable_addExtraRC_nolock(size_t delta_rc) {
    // 当 isa.extra_rc 即将溢出时
    if (isa.extra_rc + delta_rc > RC_MASK) {
        // 将引用计数迁移到 SideTable
        isa.has_sidetable_rc = true;
        auto &table = SideTables()[this];
        size_t& refcnt = table.refcnts[this];
        refcnt += delta_rc;
    } else {
        // 继续使用 isa 存储
        isa.extra_rc += delta_rc;
    }
}

5. 弱引用处理

5.1 弱引用表结构

struct weak_table_t {
    weak_entry_t *weak_entries;  // 弱引用数组
    size_t    num_entries;       // 条目数
    uintptr_t mask;             // 容量掩码
    uintptr_t max_hash_displacement;  // 最大哈希偏移
};

5.2 弱引用操作

id objc_loadWeakRetained(id *location) {
    id obj = *location;
    if (!obj) return nil;
    if (obj->isTaggedPointer()) return obj;
    return obj->rootRetain();
}

void objc_storeWeak(id *location, id obj) {
    _objc_weak_store(location, obj);
}

6. 自动释放池相关

void *objc_autoreleasePoolPush(void) {
    return AutoreleasePoolPage::push();
}

void objc_autoreleasePoolPop(void *ctxt) {
    AutoreleasePoolPage::pop(ctxt);
}

id objc_autorelease(id obj) {
    if (!obj) return obj;
    if (obj->isTaggedPointer()) return obj;
    return obj->autorelease();
}

7. 优化机制

7.1 Tagged Pointer

bool isTaggedPointer() {
    return ((uintptr_t)this & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}

// Tagged Pointer 对象不参与引用计数
if (obj->isTaggedPointer()) {
    return obj;  // 直接返回,不进行引用计数操作
}

7.2 散列表优化

// SideTable 的哈希表实现
struct RefcountMap : public objc::DenseMap<DisguisedPtr<objc_object>,size_t,true> {
    // 使用 DenseMap 提高查找效率
};

8. 内存管理策略

8.1 dealloc 流程

inline void 
objc_object::rootDealloc() {
    if (isTaggedPointer()) return;
    
    if (fastpath(isa.hasNonpointerIsa())) {
        // 快速释放路径
        if (fastpath(!isa.weakly_referenced && !isa.has_assoc)) {
            free(this);
            return;
        }
    }
    object_dispose((id)this);
}

8.2 引用计数检查

bool objc_object::rootTryRetain() {
    if (isTaggedPointer()) return true;
    
    if (fastpath(!ISA()->hasCustomRR())) {
        if (fastpath(isa.hasNonpointerIsa())) {
            // 尝试增加引用计数
            return sidetable_tryRetain();
        }
    }
    return false;
}

这个引用计数系统的设计考虑了:

  1. 性能优化(isa 优化、Tagged Pointer)
  2. 内存效率(分散存储策略)
  3. 线程安全(自旋锁、原子操作)
  4. 扩展性(支持自定义引用计数)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2273505.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【docker系列】可视化Docker 管理工具——Portainer

1. 介绍 Portainer是一个可视化的Docker操作界面&#xff0c;提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作&#xff08;包括上传下载镜像&#xff0c;创建容器等操作&#xff09;、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录…

机器学习基础-大语言模型

目录 大语言模型的基本概念 “大”体现在什么地方&#xff1f; 预训练微调两阶段的基本流程和作用 第一阶段&#xff1a;利用语言模型进行无监督预训练 第二阶段&#xff1a;通过监督微调的模式解决下游任务 BERT模型中MLM和NSP机制基本概念 MLM NSP Prompt学习的基本概…

Ubuntu挂载Windows 磁盘,双系统

首先我们需要在终端输入这个命令&#xff0c;来查看磁盘分配情况 lsblk -f 找到需要挂载的磁盘&#xff0c;检查其类型&#xff08; 我的/dev/nvme2n1p1类型是ntfs&#xff0c;名字叫3500winData&#xff09; 然后新建一个挂载磁盘的目录&#xff0c;我的是/media/zeqi/3500wi…

Java设计模式 —— 【行为型模式】命令模式(Command Pattern) 详解

文章目录 模式介绍优缺点适用场景结构案例实现注意事项 模式介绍 有时候需要向某些对象发送请求&#xff0c;但是并不知道请求的接收者是谁&#xff0c;也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序&#xff0c;使得请求发送者和请求接收者能够消除彼此…

如何很快将文件转换成另外一种编码格式?编码?按指定编码格式编译?如何检测文件编码格式?Java .class文件编码和JVM运行期内存编码?

如何很快将文件转换成另外一种编码格式? 利用VS Code右下角的"选择编码"功能&#xff0c;选择"通过编码保存"可以很方便将文件转换成另外一种编码格式。尤其&#xff0c;在测试w/ BOM或w/o BOM, 或者ANSI编码和UTF编码转换&#xff0c;特别方便。VS文件另…

AnaConda下载PyTorch慢的解决办法

使用Conda下载比较慢&#xff0c;改为pip下载 复制下载链接到迅雷下载 激活虚拟环境&#xff0c;安装whl&#xff0c;即可安装成功 pip install D:\openai.wiki\ChatGLM2-6B\torch-2.4.1cu121-cp38-cp38-win_amd64.whl

opencv摄像头标定程序实现

摄像头标定是计算机视觉中的一个重要步骤&#xff0c;用于确定摄像头的内参&#xff08;如焦距、主点、畸变系数等&#xff09;和外参&#xff08;如旋转矩阵和平移向量&#xff09;。OpenCV 提供了方便的工具来进行摄像头标定。下面分别给出 C 和 Python 的实现。 1. C 实现…

UE5AI感知组件

官方解释&#xff1a; AI感知系统为Pawn提供了一种从环境中接收数据的方式&#xff0c;例如噪音的来源、AI是否遭到破坏、或AI是否看到了什么。 AI感知组件&#xff08;AIPerception Component&#xff09;是用于实现游戏中的非玩家角色&#xff08;NPC&#xff09;对环境和其…

Python生日祝福烟花

1. 实现效果 2. 素材加载 2个图片和3个音频 shoot_image pygame.image.load(shoot(已去底).jpg) # 加载拼接的发射图像 flower_image pygame.image.load(flower.jpg) # 加载拼接的烟花图 烟花不好去底 # 调整图像的像素为原图的1/2 因为图像相对于界面来说有些大 shoo…

智能手机租赁系统全新模式改变消费习惯与商家盈利路径

内容概要 智能手机租赁系统的崛起&#xff0c;让我们瞄到了一个消费市场的新风向标。想象一下&#xff0c;传统上人们总是为了最新款手机奋不顾身地排队、借钱甚至是透支信用卡。现在&#xff0c;通过灵活的租赁选项&#xff0c;消费者可以更加随意地体验高科技产品&#xff0…

【简博士统计学习方法】第1章:3. 统计学习方法的三要素

3. 统计学习方法的三要素 3.1 监督学习的三要素 3.1.1 模型 假设空间&#xff08;Hypothesis Space&#xff09;&#xff1a;所有可能的条件概率分布或决策函数&#xff0c;用 F \mathcal{F} F表示。 若定义为决策函数的集合&#xff1a; F { f ∣ Y f ( X ) } \mathcal{F…

牛客网刷题 ——C语言初阶(2分支和循环-for)——打印菱形

1. 题目描述 用C语言在屏幕上输出以下图案&#xff1a; 2. 思路 我是先上手&#xff0c;先把上半部分打印出来&#xff0c;然后慢慢再来分析&#xff0c;下面这是我先把整个上半部分打印出来&#xff0c;因为空格不方便看是几个&#xff0c;这里先用&代替空格了 然后这里…

STM32——系统滴答定时器(SysTick寄存器详解)

文章目录 1.SysTick简介2.工作原理3.SysTick寄存器4.代码延时逻辑5.附上整体代码6.一些重要解释 1.SysTick简介 Cortex-M处理器内集成了一个小型的名为SysTick(系统节拍)的定时器,它属于NVIC的一部分,且可以产生 SysTick异常(异常类型#15)。SysTick为简单的向下计数的24位计数…

《Opencv》信用卡信息识别项目

目录 一、项目介绍 二、数据材料介绍 1、模板图片&#xff08;1张&#xff09; 2、需要处理的信用卡图片&#xff08;5张&#xff09; 三、实现过程 1、导入需要用到的库 2、设置命令行参数 3、模板图像中数字的定位处理 4、信用卡图像处理 5、模板匹配 四、总结 一…

密码学科普

1 信息传输中的安全隐患 1. 窃听 解决方案&#xff1a;明文加密&#xff0c;X只能窃听到密文 2. 假冒 解决方案&#xff1a;消息认证码或者数字签名 3. 篡改 解决方案&#xff1a;消息认证码或者数字签名 4. 事后否认 解决方案&#xff1a;数字签名 2 对称加密/非对称加密 1…

复合机器人助力手机壳cnc加工向自动化升级

在当今竞争激烈的制造业领域&#xff0c;如何提高生产效率、降低成本、提升产品质量&#xff0c;成为众多企业面临的关键挑战。尤其是在手机壳 CNC 加工这一细分行业&#xff0c;随着市场需求的持续增长&#xff0c;对生产效能的要求愈发严苛。而复合机器人的出现&#xff0c;正…

爬虫学习记录

1.概念 通过编写程序,模拟浏览器上网,然后让其去互联网上抓取数据的过程 通用爬虫:抓取的是一整张页面数据聚焦爬虫:抓取的是页面中的特定局部内容增量式爬虫:监测网站中数据更新的情况,只会抓取网站中最新更新出来的数据 robots.txt协议: 君子协议,网站后面添加robotx.txt…

黑马头条平台管理实战

黑马头条 08平台管理 1.开始准备和开发思路1.1.开发网关1.2编写admin-gateway 代码 2.开发登录微服务2.1编写登录微服务 3.频道管理4.敏感词管理5.用户认证审核6.自媒体文章人工审核99. 最后开发中碰到的问题汇总1.关于nacos 配置 问题2.在开发频道管理新增频道后端无法接收到前…

实验四 数组和函数

实验名称 实验四 数组和函数 实验目的 &#xff08;1&#xff09;掌握一维、二维数组以及字符数组的定义、元素引用和编程方法。 &#xff08;2&#xff09;掌握字符串常用程序的设计方法。 &#xff08;3&#xff09;掌握函数定义和调用的方法&#xff0c;以及函数参数传…

Idea(中文版) 项目结构/基本设置/设计背景

目录 1. Idea 项目结构 1.1 新建项目 1.2 新建项目的模块 1.3 新建项目模块的包 1.4 新建项目模块包的类 2. 基本设置 2.1 设置主题 2.2 设置字体 2.3 设置注释 2.4 自动导包 2.5 忽略大小写 2.6 设置背景图片 3. 项目与模块操作 3.1 修改类名 3.2 关闭项目 1. I…