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的实现原理](

posted @ 2022-09-29 14:05  任淏  阅读(169)  评论(0编辑  收藏  举报