static id storeWeak(id *location, objc_object *newObj) { //location是weak指针修饰的指针的地址,而objc_object *newObj就是weak指针指向的对象。 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: // 如果weak指针之前弱引用过一个obj,则将这个 obj 所对应的 SideTable 取出,赋值给 oldTable // 这里将对象当做Key就能取出之前的SideTale,SideTables是一个<StripedMap<SideTable>*>是一个对象为Key,SideTable为Values的字典。 // 如果这个对象之前有被弱应用过,则可以找到之前的SidesTable。 if (haveOld) { oldObj = *location; //因为location本来就是一个指针,所以拿到location之前指向的对象的地址。 oldTable = &SideTables()[oldObj]; } else { oldTable = nil; } //🌵🌵 这个地方感觉是要创建SideTables因为既然是新的值赋值给weak指针。 if (haveNew) { newTable = &SideTables()[newObj]; } else { newTable = nil; } //lockTwo 加锁,保证多线程安全 SideTable::lockTwo<haveOld, haveNew>(oldTable, newTable); // 有无旧值 && location与oldObj 是否一致 // 🌵如果 有旧值 但 location与oldObj 不同,说明当前的location已经处理过oldObj,可是又被其他线程给修改了 if (haveOld && *location != oldObj) { // 解锁, retry 重新处理 old SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable); goto retry; } // 通过确保弱引用的对象没有未初始化的isa,防止 弱引用 和 初始化 之间死锁 // 🌵这里为啥会导致死锁 // 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. // cls 赋值给 previouslyInitializedClass 重新 retry previouslyInitializedClass = cls;
goto retry; } } // 如果weak指针之前弱引用过别的对象oldObj,则调用weak_unregister_no_lock,在oldObj的weak_entry_t中移除该weak指针地址 // Clean up old value, if any. if (haveOld) { weak_unregister_no_lock(&oldTable->weak_table, oldObj, location); }
// Assign new value, if any. if (haveNew) { // 调用weak_register_no_lock方法,将weak指针的地址记录到newObj对应的weak_entry_t中 // weak_entry_t 插入到 全局 weak_table 哈希表中 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 // 更新newObj的isa指针的weakly_referenced bit标志位 // 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. // 这里__weak修饰的指针location的值最终被赋值为newObj的值,而应用计数没有变化。 *location = (id)newObj; } else { // No new value. The storage is not changed. } SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable);