weak引用表原理探究
一、weak引用实现原理探究
首先对《Xcode 10 下如何调试objc4-723》建立的objc源码调试工程表示感谢!
地址:https://www.jianshu.com/p/9e0fc8295c4b
大多数文章阐述了基本过程:
1.初始化一个weak对象时,runtime会调用一个objc_initWeak函数,初始化一个新的weak指针指向该对象的地址 2.在objc_initWeak函数中会继续调用objc_storeWeak函数,在这个过程是用来更新weak指针的指向,同时创建对应的弱引用表 3.在对象释放时,会调用clearDeallocating函数,这个函数会根据对象地址获取所有weak指针数组,然后遍历这个数组置为nil。最后把该条对象的记录从weak表中删除。
id objc_initWeak(id *location, id newObj) {
// 查看对象实例是否有效
// 无效对象直接导致指针释放
if (!newObj) {
*location = nil;
return nil;
}
// 这里传递了三个 bool 数值
// 使用 template 进行常量参数传递是为了优化性能
return storeWeak<false/*old*/, true/*new*/, true/*crash*/>
(location, (objc_object*)newObj);
} template <bool HaveOld, bool HaveNew, bool CrashIfDeallocating>
static id
storeWeak(id *location, objc_object *newObj)
{
assert(HaveOld || HaveNew);
if (!HaveNew) assert(newObj == nil); Class previouslyInitializedClass = nil;
id oldObj;
SideTable *oldTable;
SideTable *newTable; // Acquire locks for old and new values.
// Order by lock address to prevent lock ordering problems.
// Retry if the old value changes underneath us.
retry:
if (HaveOld) {
oldObj = *location;
oldTable = &SideTables()[oldObj];
} else {
oldTable = nil;
}
if (HaveNew) {
newTable = &SideTables()[newObj];
} else {
newTable = nil;
} SideTable::lockTwo<HaveOld, HaveNew>(oldTable, newTable); if (HaveOld && *location != oldObj) {
SideTable::unlockTwo<HaveOld, HaveNew>(oldTable, newTable);
goto retry;
} // Prevent a deadlock between the weak reference machinery
// and the +initialize machinery by ensuring that no
// weakly-referenced object has an un-+initialized isa.
if (HaveNew && newObj) {
Class cls = newObj->getIsa();
if (cls != previouslyInitializedClass &&
!((objc_class *)cls)->isInitialized())
{
SideTable::unlockTwo<HaveOld, HaveNew>(oldTable, newTable);
_class_initialize(_class_getNonMetaClass(cls, (id)newObj)); // If this class is finished with +initialize then we're good.
// If this class is still running +initialize on this thread
// (i.e. +initialize called storeWeak on an instance of itself)
// then we may proceed but it will appear initializing and
// not yet initialized to the check above.
// Instead set previouslyInitializedClass to recognize it on retry.
previouslyInitializedClass = cls; goto retry;
}
} // Clean up old value, if any.
if (HaveOld) {
weak_unregister_no_lock(&oldTable->weak_table, oldObj, location);
} // Assign new value, if any.
if (HaveNew) {
newObj = (objc_object *)weak_register_no_lock(&newTable->weak_table,
(id)newObj, location,
CrashIfDeallocating);
// weak_register_no_lock returns nil if weak store should be rejected // Set is-weakly-referenced bit in refcount table.
if (newObj && !newObj->isTaggedPointer()) {
newObj->setWeaklyReferenced_nolock();
} // Do not set *location anywhere else. That would introduce a race.
*location = (id)newObj;
}
else {
// No new value. The storage is not changed.
} SideTable::unlockTwo<HaveOld, HaveNew>(oldTable, newTable); return (id)newObj;
}
其中涉及到一个数据结构
struct SideTable {
spinlock_t slock; // 因为操作对象的引用计数频率很快,因此系统在这里设置了一把自旋锁,保证是原子操作
RefcountMap refcnts; // 引用计数器哈希表,根据对象地址查找对象的引用计数
weak_table_t weak_table; // 维护weak指针的结构体
}
通过下面的代码取得
也就是全局的sidetables本身是一个hash表,总共大小为64;每一个value对应的是 sidetable,sidetable中保存引用计数表和weak引用表
找到一个sidetable表之后,要根据weak所指对象的地址hash值,找到对应存储weak指针的value结构体
接下来的操作就是修改weak引用表了
weak引用表原理探究的更多相关文章
- iOS 底层解析weak的实现原理(包含weak对象的初始化,引用,释放的分析)
原文 很少有人知道weak表其实是一个hash(哈希)表,Key是所指对象的地址,Value是weak指针的地址数组.更多人的人只是知道weak是弱引用,所引用对象的计数器不会加一,并在引用对象被释放 ...
- 弱类型变量原理探究(转载 http://www.csdn.net/article/2014-09-15/2821685-exploring-of-the-php)
N首页> 云计算 [问底]王帅:深入PHP内核(一)——弱类型变量原理探究 发表于2014-09-19 09:00| 13055次阅读| 来源CSDN| 36 条评论| 作者王帅 问底PHP王帅 ...
- iOS weak底层实现原理
今年年底做了很多决定,离开工作三年的深圳,来到了上海,发现深圳和上海在苹果这方面还是差距有点大的,上海的市场8成使用swift编程,而深圳8成的使用OC,这点还是比较让准备来上海打拼的苹果工程师有点小 ...
- 04 (OC)* weak的实现原理
一:Weak 表 1: Runtime 维护了一个 Weak 表,用于存储所有 Weak 指针.Weak 表是一个哈希表,Key 是对象的地址,Value 是一个数组,数组里面放的是 Weak 指针的 ...
- [原] KVM 虚拟化原理探究(5)— 网络IO虚拟化
KVM 虚拟化原理探究(5)- 网络IO虚拟化 标签(空格分隔): KVM IO 虚拟化简介 前面的文章介绍了KVM的启动过程,CPU虚拟化,内存虚拟化原理.作为一个完整的风诺依曼计算机系统,必然有输 ...
- [原] KVM 虚拟化原理探究(4)— 内存虚拟化
KVM 虚拟化原理探究(4)- 内存虚拟化 标签(空格分隔): KVM 内存虚拟化简介 前一章介绍了CPU虚拟化的内容,这一章介绍一下KVM的内存虚拟化原理.可以说内存是除了CPU外最重要的组件,Gu ...
- lua的弱弱引用表
lua有GC.细节无需太关注.知道些主要的即可,能local就一定不要global: 还有在数组里的对象,除非显式=nil,否则非常难回收: 只是能够用弱引用表来告诉GC. 外部引用为0,就不要管我, ...
- Objective-C 引用计数原理
http://www.cocoachina.com/ios/20160112/14933.html 引用计数如何存储 有些对象如果支持使用 TaggedPointer,苹果会直接将其指针值作为引用计数 ...
- ThreadPoolExcutor 原理探究
概论 线程池(英语:thread pool):一种线程使用模式.线程过多会带来调度开销,进而影响缓存局部性和整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务.这避免了在处理短时间 ...
- [原] KVM 虚拟化原理探究(1)— overview
KVM 虚拟化原理探究- overview 标签(空格分隔): KVM 写在前面的话 本文不介绍kvm和qemu的基本安装操作,希望读者具有一定的KVM实践经验.同时希望借此系列博客,能够对KVM底层 ...
随机推荐
- ionic 4 app 自动版本更新
前言 介绍一下ionic4 app的自动更新.ionic 不多介绍了,后面一个后系列,背负着骂名的ionic其实还是可以的,如果刚入门ionic可能觉得很坑,但是呢,往后你就发现另外一件事,那就是其他 ...
- JVM简明笔记3:类加载机制
1 类的加载 类的加载指的是将类的 .class 文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class 对象,用来封装类在方法区内的数据结 ...
- Dapr Outbox 执行流程
Dapr Outbox 是1.12中的功能. 本文只介绍Dapr Outbox 执行流程,Dapr Outbox基本用法请阅读官方文档 .本文中appID=order-processor,topic= ...
- ESXI 6.5 零基础从安装到批量生成/管理虚拟机简易教程
制造U盘安装盘 1 先提前下载好,ESXI 6.5 ISO文件. 2 下载制作U盘安装工具,RUFUS. Rufus非常小巧的绿色EXE文件,默认配置选中ISO文件就可以,点击开始,就自动制作,非常方 ...
- 零信任策略下K8s安全监控最佳实践(K+)
简介: 本文重点将围绕监控防护展开,逐层递进地介绍如何在复杂的分布式容器化环境中借助可观测性平台,持续监控K8s集群,及时发现异常的 API 访问事件.异常流量.异常配置.异常日志等行为,并且结合合理 ...
- Hologres+Hologres+Flink流批一体首次落地4982亿背后的营销分析大屏Flink流批一体首次落地4982亿背后的营销分析大屏
简介: 本篇将重点介绍Hologres在阿里巴巴淘宝营销活动分析场景的最佳实践,揭秘Flink+Hologres流批一体首次落地阿里双11营销分析大屏背后的技术考验. 概要:刚刚结束的2020天猫双1 ...
- 如何迁移 Flink 任务到实时计算
简介: 本文由阿里巴巴技术专家景丽宁(砚田)分享,主要介绍如何迁移Flink任务到实时计算 Flink 中来. 通常用户在线下主要使用 Flink run,这会造成一些问题,比如:同一个配置因版本而变 ...
- MaxCompute Tunnel 技术原理及开发实战
简介: MaxCompute(原名ODPS)是一种快速.完全托管的EB级数据仓库解决方案, 致力于批量结构化数据的存储和计算,为用户提供数据仓库的解决方案及分析建模服务.Tunnel是MaxCompu ...
- Quick BI电子表格: 新手亦可表格自由
简介: 随着企业业务快速增长,单纯的表或交叉表展现的数据模式相对固定,已不能满足企业中不同角色用户.不同业务场景数据可视化分析展现的诉求.在满足业务人员可视化需求层面,Quick BI不仅提供了丰富 ...
- [FAQ] 钉钉 Excel 回车键不能换行 ? 在线编辑如何换行
Win 端表格换行:AIT+ENTER Mac 端表格换行:AIT OPTION+ENTER Tool:ChatAI Refer:钉钉技巧 Refer:https://www.dingtalk.c ...