weak 源码分析

说明:本文摘出的源码均来自 objc4-818.2 这个版本。

目录

头文件声明

注释

objc-weak.h 的开头处有一段注释:

The weak table is a hash table governed by a single spin lock.

An allocated blob of memory, most often an object, but under GC any such allocation, may have its address stored in a __weak marked storage location through use of compiler generated write-barriers or hand coded uses of the register weak primitive. Associated with the registration can be a callback block for the case when one of the allocated chunks of memory is reclaimed.

The table is hashed on the address of the allocated memory. When __weak marked memory changes its reference, we count on the fact that we can still see its previous reference.

So, in the hash table, indexed by the weakly referenced item, is a list of all locations where this address is currently being stored.

For ARC, we also keep track of whether an arbitrary object is being deallocated by briefly placing it in the table just prior to invoking dealloc, and removing it via objc_clear_deallocating just prior to memory reclamation.

翻译

弱引用表是一个由自旋锁(已改用互斥锁 os_unfair_lock )管理的哈希表。

。。。后面的没看太懂。。。❓

weak_table_t

全局弱引用表:

struct weak_table_t {
    weak_entry_t *weak_entries;
    size_t    num_entries;
    uintptr_t mask;
    uintptr_t max_hash_displacement;
};

注释:

The global weak references table. Stores object ids as keys, and weak_entry_t structs as their values.

哈希表的键值:

  • key :对象的地址(object ids);

  • value :weak_entry_t 结构体,里面存有弱引用指针的地址(二级指针)的数组。

weak_entry_t

weak_entry_t 是全局弱引用表中 value 的类型。弱引用指针的地址存储在 weak_entry_t 内的 weak_referrer_t 类型中。

弱引用指针的地址(二级指针)最初存储在 inline_referrers 中(定长数组),当弱引用指针的数量超过 WEAK_INLINE_COUNT(值为 4 )时,才申请内存创建一个 referrers 数组。

struct weak_entry_t {
    DisguisedPtr<objc_object> referent;
    union {
        struct {
            weak_referrer_t *referrers;
            uintptr_t        out_of_line_ness : 2;
            uintptr_t        num_refs : PTR_MINUS_2;
            uintptr_t        mask;
            uintptr_t        max_hash_displacement;
        };
        struct {
            // out_of_line_ness field is low bits of inline_referrers[1]
            weak_referrer_t  inline_referrers[WEAK_INLINE_COUNT];
        };
    };

    bool out_of_line() {
        return (out_of_line_ness == REFERRERS_OUT_OF_LINE);
    }

    weak_entry_t& operator=(const weak_entry_t& other) {
        memcpy(this, &other, sizeof(other));
        return *this;
    }

    weak_entry_t(objc_object *newReferent, objc_object **newReferrer)
        : referent(newReferent)
    {
        inline_referrers[0] = newReferrer;
        for (int i = 1; i < WEAK_INLINE_COUNT; i++) {
            inline_referrers[i] = nil;
        }
    }
};

weak_referrer_t

typedef DisguisedPtr<objc_object *> weak_referrer_t;

注释:

The address of a __weak variable. These pointers are stored disguised so memory analysis tools don't see lots of interior pointers from the weak table into objects.

翻译:

weak_referrer_t__weak 弱引用指针的地址。

参考

Last updated

Was this helpful?