weak指针的实现原理
weak指针的实现原理
也就是,weak指针指向对象销毁的时候,weak指针怎么做到变为nil的。
Runtime维护了一个weak表,用于存储指向某个对象的所有weak指针。weak表其实是一个Hash(哈希)表,
Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象的地址)数组。
举个例子:
__weak NSObject *obj1 = [[NSObject alloc] init];
__weak NSObject *obj2 = obj1;
Key指的是[[NSObject alloc] init]
Value指的是[obj1, ibj2]
struct weak_table_t {
// 保存了所有指向指定对象的 weak 指针
weak_entry_t *weak_entries;
// 存储空间
size_t num_entries;
// 参与判断引用计数辅助量
uintptr_t mask;
// hash key 最大偏移值
uintptr_t max_hash_displacement;
};
dealloc
当一个对象要释放时,会自动调用dealloc,接下来调用的是:
dealloc
_objc_rootDealloc
rootDealloc
object_dispose
objc_destructInstance、free
- (void)dealloc {
_objc_rootDealloc(self);
}
void
_objc_rootDealloc(id obj)
{
assert(obj);
obj->rootDealloc();
}
inline void
objc_object::rootDealloc()
{
if (isTaggedPointer()) return; // fixme necessary?
//weakly_referenced是弱指针引用
//强引用走yes,弱引用走no
if (fastpath(isa.nonpointer &&
!isa.weakly_referenced &&
!isa.has_assoc &&
!isa.has_cxx_dtor &&
!isa.has_sidetable_rc))
{
assert(!sidetable_present());
free(this);
}
else {
object_dispose((id)this);
}
}
id
object_dispose(id obj)
{
if (!obj) return nil;
objc_destructInstance(obj);
free(obj);
return nil;
}
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();//将指向当前对象的弱指针置为nil
}
return obj;
}
inline void
objc_object::clearDeallocating()
{
if (slowpath(!isa.nonpointer)) {
// Slow path for raw pointer isa.
sidetable_clearDeallocating();
}
else if (slowpath(isa.weakly_referenced || isa.has_sidetable_rc)) {
// Slow path for non-pointer isa with weak refs and/or side table data.
clearDeallocating_slow();
}
assert(!sidetable_present());
}
NEVER_INLINE void
objc_object::clearDeallocating_slow()
{
assert(isa.nonpointer && (isa.weakly_referenced || isa.has_sidetable_rc));
SideTable& table = SideTables()[this];
table.lock();
if (isa.weakly_referenced) {//如果是弱指针
weak_clear_no_lock(&table.weak_table, (id)this);
}
if (isa.has_sidetable_rc) {
table.refcnts.erase(this);
}
table.unlock();
}
一句话,在64位下,weak指针存储在一个weak_table哈希表中,在dealloc中进行判断,如果是weak指针,则置为nil。
更多关于weak学习:
[weak 弱引用的实现方式](https://www.desgard.com/iOS-Source-Probe/Objective-C/Runtime/weak 弱引用的实现方式.html)
[iOS开发 - 底层解析weak的实现原理](