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; }
// 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(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 - 继续 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 位置 附赋上新值 *location = (id)newObj; } else { // No new value. The storage is not changed. }