iOS - 弱引用表(Weak Reference Table)
1. 基本数据结构
// 弱引用表的基本结构
struct weak_table_t {weak_entry_t *weak_entries; // 保存所有的弱引用对象size_t num_entries; // 当前存储的弱引用数量uintptr_t mask; // 哈希表大小掩码uintptr_t max_hash_displacement; // 最大哈希偏移值
};// 单个对象的弱引用信息
struct weak_entry_t {DisguisedPtr<objc_object> referent; // 被引用的对象union {struct {weak_referrer_t *referrers; // 动态数组uintptr_t out_of_line : 1; // 是否使用动态数组uintptr_t num_refs : PTR_MINUS_1; // 引用计数uintptr_t mask; // 容量掩码uintptr_t max_hash_displacement;};struct {// 内联存储,用于优化少量弱引用的情况weak_referrer_t inline_referrers[WEAK_INLINE_COUNT];};};
};
2. 核心操作
2.1 添加弱引用
id weak_register_no_lock(weak_table_t *weak_table, id referent, id *referrer, bool crashIfDeallocating) {// 1. 查找或创建 entryweak_entry_t *entry = weak_entry_for_referent(weak_table, referent);if (entry == nil) {entry = new_entry_for_referent(referent, referrer);weak_entry_insert(weak_table, entry);}// 2. 添加弱引用append_referrer(entry, referrer);return referent;
}
2.2 移除弱引用
void weak_unregister_no_lock(weak_table_t *weak_table, id referent, id *referrer) {weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);if (entry == nil) return;// 移除引用remove_referrer(entry, referrer);// 如果 entry 为空,则移除if (entry->out_of_line && entry->num_refs == 0) {weak_entry_remove(weak_table, entry);}
}
3. 存储优化
3.1 内联存储
#define WEAK_INLINE_COUNT 4struct weak_entry_t {union {// 当弱引用数量少时,使用内联数组struct {weak_referrer_t inline_referrers[WEAK_INLINE_COUNT];};// 当弱引用数量多时,使用动态数组struct {weak_referrer_t *referrers;uintptr_t out_of_line : 1;};};
};
3.2 动态扩展
static void grow_refs_and_insert(weak_entry_t *entry, objc_object **new_referrer) {assert(entry->out_of_line());size_t old_size = TABLE_SIZE(entry);size_t new_size = old_size ? old_size * 2 : 8;// 分配新空间weak_referrer_t *new_refs = (weak_referrer_t *)calloc(new_size, sizeof(weak_referrer_t));// 迁移数据for (size_t i = 0; i < old_size; i++) {weak_referrer_t oldref = entry->referrers[i];if (oldref) {weak_referrer_t *new_ref = new_refs + hash_pointer(oldref);*new_ref = oldref;}}
}
4. 线程安全
4.1 锁保护
struct SideTable {spinlock_t slock; // 自旋锁RefcountMap refcnts;weak_table_t weak_table;void lock() { slock.lock(); }void unlock() { slock.unlock(); }
};// 使用示例
void weak_register_no_lock(weak_table_t *weak_table, id referent) {SideTable& table = SideTables()[referent];table.lock();// 操作 weak_tabletable.unlock();
}
4.2 原子操作
bool weak_entry_insert(weak_table_t *weak_table, weak_entry_t *new_entry) {return OSAtomicCompareAndSwapPtr(nil, new_entry, (void * volatile *)&weak_table->weak_entries);
}
5. 清理机制
5.1 对象释放时的清理
void weak_clear_no_lock(weak_table_t *weak_table, id referent) {weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);if (entry == nil) return;// 将所有弱引用置为 nilweak_referrer_t *referrers = entry->referrers;size_t count = entry->num_refs;for (size_t i = 0; i < count; ++i) {objc_object **referrer = referrers[i];if (referrer) {*referrer = nil;}}// 移除 entryweak_entry_remove(weak_table, entry);
}
5.2 表格清理
void weak_compact_maybe(weak_table_t *weak_table) {size_t old_size = TABLE_SIZE(weak_table);// 当表使用率低于 1/4 时进行收缩if (weak_table->num_entries < old_size / 4) {weak_resize(weak_table, old_size / 2);}
}
6. 性能优化
6.1 哈希优化
static inline uintptr_t hash_pointer(objc_object **p) {return ((uintptr_t)p) >> 3; // 去除对齐位
}static inline size_t index_for_pointer(uintptr_t ptr, size_t mask) {return ptr & mask; // 快速取模
}
6.2 空间优化
// 使用内联数组优化小对象
if (entry->num_refs < WEAK_INLINE_COUNT) {// 使用内联存储entry->inline_referrers[entry->num_refs++] = referrer;
} else {// 转换为动态数组move_to_dynamic_storage(entry);
}
7. 注意事项
1. 线程安全:
- 所有操作都需要加锁保护
- 使用原子操作进行关键更新
- 内存管理:
- 及时清理无用的 entry
- 动态调整表大小避免内存浪费
3. 性能考虑:
- 使用内联存储优化小对象
- 哈希算法优化查找效率
- 正确性保证:
- 对象释放时正确清理所有弱引用
- 维护引用计数的准确性
这个设计在保证功能正确的同时,通过多种优化手段提供了良好的性能。
相关文章:
iOS - 弱引用表(Weak Reference Table)
1. 基本数据结构 // 弱引用表的基本结构 struct weak_table_t {weak_entry_t *weak_entries; // 保存所有的弱引用对象size_t num_entries; // 当前存储的弱引用数量uintptr_t mask; // 哈希表大小掩码uintptr_t max_hash_displacement; /…...
C#语言的网络编程
C#语言的网络编程 引言 随着互联网的飞速发展,网络编程成为了软件开发中的一个重要领域。C#语言作为一种现代编程语言,凭借其丰富的类库、良好的可读性和强大的功能,广泛应用于开发各种网络应用程序。无论是Windows应用、Web应用还是云服务…...

【操作系统】课程 4调度与死锁 同步测练 章节测验
4.1知识点导图 处理机调度与死锁相关内容的文字整理: 基本准则 资源利用率:使系统中的处理机和其他所有资源都尽可能地保持忙碌状态。系统吞吐量:单位时间内系统所完成的作业数。公平性:使各进程都获得合理的CPU时间,而…...

如何查看已经安装的python版本和相关路径信息
如何查看已经安装的python版本和相关路径信息 本文目录: 一、通过命令行模式查询 1、通过命令where python 2、通过命令print(sys.executable) 二、在 Anaconda Navigator 中 三、只安装python的环境下 一、通过命令行模式查询 同时按windowR键,输入cmd&#x…...
设计模式-结构型-适配器模式
在软件开发中,随着系统的不断扩展和模块的不断增加,往往会遇到不同模块之间接口不兼容的情况。此时,如果我们能通过某种方式将一个接口转化为另一个接口,那么开发工作将变得更加灵活和高效。适配器模式(Adapter Patter…...
鸿蒙操作系统(HarmonyOS)
鸿蒙操作系统(HarmonyOS)是华为公司推出的一款面向未来、面向全场景的分布式操作系统。它旨在为用户提供一个更加智能、便捷和安全的操作环境,支持多种终端设备之间的无缝协作。在鸿蒙应用开发中,ArkUI作为官方推荐的用户界面开发…...

基于海思soc的智能产品开发(camera sensor的两种接口)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 对于嵌入式开发设备来说,除了图像显示,图像输入也是很重要的一部分。说到图像输入,就不得不提到camera。目前ca…...
解密LLM结构化输出:代码示例与原理分析
解密LLM结构化输出:代码示例与原理分析 一、LLM结构化输出概述 1. 结构化输出的定义与优势 结构化输出指的是语言模型(LLM)生成的遵循特定格式(如JSON、XML)的数据,这些数据易于解析和处理。相较于非结构…...
Go语言的数据类型
Go语言的数据类型详解 Go语言是一门具有简洁、高效并且强类型的编程语言。它的设计理念之一是让程序员能够以清晰、简明的方式表达自己的意图。在Go语言中,数据类型是其基础构建块之一,理解不同数据类型的特点和使用场景对于编写高效的Go程序至关重要。…...

复杂园区网基本分支的构建
目录 1、各主机进行网络配置。2、交换机配置。3、配置路由交换,进行测试。4、配置路由器接口和静态路由,进行测试。5、最后测试任意两台主机通信情况 模拟环境链接 拓扑结构 说明: VLAN标签在上面的一定是GigabitEthernet接口的,…...

如何很快将文件转换成另外一种编码格式?编码?按指定编码格式编译?如何检测文件编码格式?Java .class文件编码和JVM运行期内存编码?
如何很快将文件转换成另外一种编码格式? 利用VS Code右下角的"选择编码"功能,选择"通过编码保存"可以很方便将文件转换成另外一种编码格式。尤其,在测试w/ BOM或w/o BOM, 或者ANSI编码和UTF编码转换,特别方便。VS文件另…...

《C++11》Lambda 匿名函数从入门到进阶 优缺点分析 示例
Lambda 匿名函数从入门到进阶 C11 引入了 lambda 表达式,这是一种非常强大的功能,可以让我们在代码中定义匿名函数。它们不仅使代码更加简洁,而且在处理回调、算法和多线程编程时极为方便。本文将带你从入门到进阶,全面了解 C11 …...

连接Milvus
连接到Milvus 验证Milvus服务器正在侦听哪个本地端口。将容器名称替换为您自己的名称。 docker port milvus-standalone 19530/tcp docker port milvus-standalone 2379/tcp docker port milvus-standalone 192.168.1.242:9091/api/v1/health 使用浏览器访问连接地址htt…...
Linux——修改文件夹的所属用户组和用户
一、命令 举例: 授权 MOT17 文件夹 给 hust_xxx 用户: sudo chown -R hust_xxx:hust_xxx MOT17参考 Linux授权文件夹给用户...

Vue Amazing UI 组件库(Vue3+TypeScript+Vite 等最新技术栈开发)
Vue Amazing UI 一个 Vue 3 组件库 使用 TypeScript,都是单文件组件 (SFC),支持 tree shaking 有点意思 English | 中文 Vue Amazing UI 是一个基于 Vue 3、TypeScript、Vite 等最新技术栈开发构建的现代化组件库,包含丰富的 UI 组件和常…...

计算机Steam报错failedtoloadsteamui.dll怎么解决?DLL报错要怎么修复?
计算机Steam报错“Failed to Load SteamUI.dll”?这里有专业的解决方案! 作为软件开发领域的一名从业者,我深知电脑在运行过程中可能会遇到的各种问题,尤其是像Steam这样的大型游戏平台。今天,我将为大家科普一下Stea…...

如何开发一个简单的 dApp
后端合约 执行 sui move new resource_manage 创建一个包 接着就可以开始编写合约了 首先创建两个 Struct 用来创建 Profile 并记录在 State 中 public struct State has key {id: UID,users: Table<address, address>, }public struct Profile has key {id: UID,nam…...
TDengine 签约智园数字,助力化工园区智联未来
近年来,随着化工行业对安全、环保、高效运营的要求日益提高,化工园区的数字化转型成为必然趋势。从数据孤岛到全面互联,从基础监控到智能分析,如何高效管理和利用时序数据已成为化工园区智能化升级的关键环节。作为一家专注于时序…...

《Python游戏编程入门》注-第9章8
2 游戏信息的显示 在游戏窗口的上部会显示游戏分数、游戏关卡、剩余砖块数以及剩余小球数等信息,如图12所示。 图12 游戏信息显示 使用如图13所示的代码实现以上功能。 图13 显示游戏信息的代码 其中,print_text()函数MyLibrary....

js逆向实战(1)-- 某☁️音乐下载
下载某云音乐源文件.mp4格式 首先随便点进一首歌,如图所示获取该音乐id,然后点击播放键,打开F12进行查询XHR 由此可知,实际请求网址是 https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token「你的token」url需带…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...

MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...