引用计数在 SideTables 中有介绍

引用计数在 SideTables 中有介绍

引用计数管理

alloc 实现

经过一系列调用,最终调用了 C 函数 calloc, 此时并没有设置引用计数为 1

Tagged Pointer 对象

retain 时。

id objc_object::rootRetain(bool tryRetain, bool handleOverflow) {
    if (isTaggedPointer()) return (id)this;
    ...
}


release 时。

bool  objc_object::rootRelease(bool performDealloc, bool handleUnderflow) {
    if (isTaggedPointer()) return false;
    ...
}


retainCount 时。

uintptr_t objc_object::rootRetainCount() {
    if (isTaggedPointer()) return (uintptr_t)this;
    ...
}


由此可见对于 Tagged Pointer 对象,并没有任何的引用计数操作,引用计数数量也只是单纯的返回自己地址罢了。

开启了 Non-pointer

retain 时。

id objc_object::rootRetain(bool tryRetain, bool handleOverflow) {
    ...
    //其实就是对isa的extra_rc变量进行+1,前面说到isa会存很多东西
    addc(newisa.bits, 1, 0, &carry);
    ...
}


release 时。

bool  objc_object::rootRelease(bool performDealloc, bool handleUnderflow) {
    ...
    //其实就是对isa的extra_rc变量进行-1
    subc(newisa.bits, 1, 0, &carry);
    ...
}


retainCount 时。

uintptr_t objc_object::rootRetainCount() {
    ...
    //其实就是获取isa的extra_rc值再+1,alloc新建一个对象时bits.extra_rc为0并不是1,这个要注意。
    uintptr_t rc = 1 + bits.extra_rc;
    ...
}


未开启 Non-pointer isa

alloc 实现

经过一系列调用,最终调用了 C 函数 calloc, 此时并没有设置引用计数为 1

此时并没有设置引用计数为 1

此时并没有设置引用计数为 1

retain 实现

SideTable &table = SideTables()[this];
//在tables里面,根据当前对象指针获取对应的sidetable

size_t &refcntStorage = table.refcnts[this];
//获得引用计数

//添加引用计数
refcntStorage += SIDE_TABLE_RC_ONE(4,位计算)


release 实现

SideTable &table = SideTables()[this];
RefcountMap::iterator it = table.refcnts.find[this];
it->second -= SIDE_TABLE_RC_ONE


retianCount

SideTable &table = SideTables()[this];
size_t refcnt_result = 1;
RefcountMap::iterator it = table.refcnts.find[this];
refcnt_result += it->second >> SIDE_TABLE_RC_SHIFT;(将向右偏移操作)


Reference

1.iOS 引用计数管理之揭秘计数存储
2.roadmap.isylar.com