// 有旧值,清除旧值 if (haveOld) { weak_unregister_no_lock(&oldTable->weak_table, oldObj, location); }
// Assign new value, if any. if (haveNew) { // 调用 weak_register_no_lock 方法,将 weakObj 的指针地址存储到 newObj 对应的 weak_entry_t 中 newObj = (objc_object *) weak_register_no_lock(&newTable->weak_table, (id)newObj, location, crashIfDeallocating); // 更新 newObj 中 isa 的 bitsweakly_referenced 标志位 if (newObj && !newObj->isTaggedPointer()) { newObj->setWeaklyReferenced_nolock(); }
把 weakObj 指针指向 newObj *location = (id)newObj; } else { // No new value. The storage is not changed. } SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable);
if (deallocating) { if (crashIfDeallocating) { _objc_fatal("Cannot form weak reference to instance (%p) of " "class %s. It is possible that this object was " "over-released, or is in the process of deallocation.", (void*)referent, object_getClassName((id)referent)); } else { return nil; } }
void weak_unregister_no_lock(weak_table_t *weak_table, id referent_id, id *referrer_id) { objc_object *referent = (objc_object *)referent_id; objc_object **referrer = (objc_object **)referrer_id;
weak_entry_t *entry;
if (!referent) return;
// 查询对应的 entry if ((entry = weak_entry_for_referent(weak_table, referent))) { remove_referrer(entry, referrer); // 执行移除操作 bool empty = true; if (entry->out_of_line() && entry->num_refs != 0) { empty = false; } else { for (size_t i = 0; i < WEAK_INLINE_COUNT; i++) { if (entry->inline_referrers[i]) { empty = false; break; } } } // 如果 entry 的 referrers 元素都移除了,从 weak_table 中移除 entry if (empty) { weak_entry_remove(weak_table, entry); } }
// 没有找到 entry 则不做任何处理 }
remove_referrer
staticvoidremove_referrer(weak_entry_t *entry, objc_object **old_referrer) { // 定长数组,遍历找到移除即可 if (! entry->out_of_line()) { for (size_t i = 0; i < WEAK_INLINE_COUNT; i++) { if (entry->inline_referrers[i] == old_referrer) { entry->inline_referrers[i] = nil; return; } } _objc_inform("Attempted to unregister unknown __weak variable " "at %p. This is probably incorrect use of " "objc_storeWeak() and objc_loadWeak(). " "Break on objc_weak_error to debug.\n", old_referrer); objc_weak_error(); return; }
// 动态数组,通过哈希计算找到对应的 weak 指针地址,置为 nil size_t begin = w_hash_pointer(old_referrer) & (entry->mask); size_t index = begin; size_t hash_displacement = 0; while (entry->referrers[index] != old_referrer) { index = (index+1) & entry->mask; if (index == begin) bad_weak_table(entry); hash_displacement++; if (hash_displacement > entry->max_hash_displacement) { _objc_inform("Attempted to unregister unknown __weak variable " "at %p. This is probably incorrect use of " "objc_storeWeak() and objc_loadWeak(). " "Break on objc_weak_error to debug.\n", old_referrer); objc_weak_error(); return; } } entry->referrers[index] = nil; entry->num_refs--; }
dealloc 对象销毁时如何处理弱引用?
对象引用计数为 0 时,底层会调用 rootDealloc 方法,进行销毁操作。
inlinevoid objc_object::rootDealloc() { // 根据 isa 标识位判断是否有弱引用,关联对象,自定义的 C++ 析构方法,是否有用到引用计数表 if (isTaggedPointer()) return; // fixme necessary?
void *objc_destructInstance(id obj) { if (obj) { // Read all of the flags at once for performance. bool cxx = obj->hasCxxDtor(); bool assoc = obj->hasAssociatedObjects();
// This order is important. if (cxx) object_cxxDestruct(obj); if (assoc) _object_remove_assocations(obj); obj->clearDeallocating(); }
return obj; }
objc_destructInstance 方法中对 C++ 析构方法和关联对象进行了处理。
inlinevoid objc_object::clearDeallocating() { if (slowpath(!isa.nonpointer)) { // Slow path for raw pointer isa. sidetable_clearDeallocating(); } elseif (slowpath(isa.weakly_referenced || isa.has_sidetable_rc)) { // 有弱引用或者使用了引用计数表 clearDeallocating_slow(); }