
根据调试信息,发现两者的区别是:
所以重点就在 storeweak这个方法中,let's do it
storeweak源码的如下:
ps:初始化isa那部分为何能阻止死锁,我没有看懂 该函数流程如下:
重点来了:
sidetable
sidetable是一个结构体,定义如下
taggedpointer
简单的说,这是一种优化手段,即将对象的值,存入对象的地址中,这些工程师简直丧心病狂,就为了省一点内存嘛!
进入正题,看看怎么实现弱引用的
先看看注册的过程吧
先从这行数的参数说起,参数有4个
后三个参数不用解释,主要解释第一个参数,weak_table_t,定义如下
没错,weak_table_t就是寄存在sidetable中
定义中我们重点关注weak_entry_t
weak_entry_t是最终存放对象和引用指针的地方,referent是被引用的对象,联合体union释义如下
注册引用过程中,重点关注下面代码:
新建
通过weak_entry_t的源码,可以看到新建一个weak_entry_t的过程是
调整weak_table_t的容量大小
当实际的数目大于old_size(old_size就是mask的大小+1),就去调整大小,同时重置max_hash_displacement为0,通过calloc函数,动态分配mask个的内存,然后通过循环,将原有的weak_entry_t插入到新的容器中,在插入的过程中,更新max_hash_displacement.
在weak_table_t插入weak_entry_t
过程比较简单,也是利用hash处理,方便后面查找。
在weak_table_t查找对象是通过循环遍历的方式,过程如下
在已有的weak_entry_t中加入引用
该过程同在weak_table_t中插入weak_entry_t如出一辙,要注意的是需要判断引用的个数,当引用个数大于weak_inline_count时,需要将原有的引用指针也移到referrers中,同时更新相关计数器。 上面过程的流程如下:
消除弱引用
消除弱引用过程同注册大致相同,只是部分地方是相反操作,不做赘述了