初始化:
第一层 在weak_table中查找weak_entry:
__weak修饰后,会调用 storeWeak(id *location, objc_object *newObj) 这个方法。 location 为weak指针地址,newObj是被弱引用的对象。 然后调用weak_register_no_lock这个方法。 这里为最外层的hash查找,KEY为referent 即被引用的对象,value为weak_entry表,如果没有就创建。
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;
}
weak_register_no_lock(weak_table_t *weak_table, id referent_id,
id *referrer_id, bool crashIfDeallocating){
objc_object *referent = (objc_object *)referent_id;
objc_object **referrer = (objc_object **)referrer_id;
weak_entry_t *entry;
if ((entry = weak_entry_for_referent(weak_table, referent))) {
append_referrer(entry, referrer);
}
else {
weak_entry_t new_entry(referent, referrer);
weak_grow_maybe(weak_table);
weak_entry_insert(weak_table, &new_entry);
}
第二层 在entry表里插入referrer:
然后添加referrer到entry里面的数组里面,如果inline_referrers有空的,添加到inline_referrers里面。否则添加referrers数组里面。这里第二次用到哈希查找算法。
new_referrer 为 二级指针, *new_referrer 指向 指向newObj的指针 根据 new_referrer w_hash_pointer(new_referrer) & (entry->mask) 找出 referrers[index]为nil时候的index, 然后令 ref = new_referrer
size_t begin = w_hash_pointer(new_referrer) & (entry->mask);
size_t index = begin;
size_t hash_displacement = 0;
while (entry->referrers[index] != nil) {
hash_displacement++;
index = (index+1) & entry->mask;
if (index == begin) bad_weak_table(entry);
}
if (hash_displacement > entry->max_hash_displacement) {
entry->max_hash_displacement = hash_displacement;
}
weak_referrer_t &ref = entry->referrers[index];
ref = new_referrer;
entry->num_refs++;
调用完 register方法后,
*location = (id)newObj
使二级指针 所指向的指针 *new_referrer 指向 newObj
所以当weak表清空时, 先遍历出来所有的referrers, 然后置空的为一级指针 *referrer = nil;
weak_clear_no_lock(weak_table_t *weak_table, id referent_id)
for (size_t i = 0; i < count; ++i) {
objc_object **referrer = referrers[i];
if (referrer) {
if (*referrer == referent) {
*referrer = nil;
}
但是删除单个weak引用时,
remove_referrer(weak_entry_t *entry, objc_object **old_referrer)
entry->referrers[index] = nil;
这里是单个二级指针置为空