引入计数存储在SideTables表中存储结构如图所示。
1.Retain实现原理。
1.1对对象retain之后实现过程。
id
objc_object::sidetable_retain()
{
#if SUPPORT_NONPOINTER_ISA
assert(!isa.nonpointer);
#endif
SideTable& table = SideTables()[this];//从SideTables中取出SideTable。
table.lock();
size_t& refcntStorage = table.refcnts[this];//根据this地址取出refcntStorage
if (! (refcntStorage & SIDE_TABLE_RC_PINNED)) {//如果没有超出引用计数最大值
refcntStorage += SIDE_TABLE_RC_ONE;//引用计数加4也就是向左移动两位。
}
table.unlock();
return (id)this;
}
复制代码
1.2引用计数值获取。
objc_object::sidetable_retainCount()
{
SideTable& table = SideTables()[this];
size_t refcnt_result = 1;
//对象初始化时默认为1之后每次对对象retain引入计数值加1
table.lock();
RefcountMap::iterator it = table.refcnts.find(this);//获取RefcountMap
if (it != table.refcnts.end()) {//能找到this对象
// this is valid for SIDE_TABLE_RC_PINNED too
refcnt_result += it->second >> SIDE_TABLE_RC_SHIFT;//
//it->second是获取到it的value
//>> SIDE_TABLE_RC_SHIFT上边获取的value向左移动两位获取到引用计数器的值。
}
table.unlock();
return refcnt_result;//返回引用计数值
}
复制代码
2.Release实现原理
objc_object::sidetable_release(bool performDealloc)
{
#if SUPPORT_NONPOINTER_ISA
assert(!isa.nonpointer);
#endif
SideTable& table = SideTables()[this];//获取到SideTable
bool do_dealloc = false;//是否要被dealloc
table.lock();//锁住table表
RefcountMap::iterator it = table.refcnts.find(this);//获取到RefcountMap
if (it == table.refcnts.end()) {//没有找到this
do_dealloc = true;
table.refcnts[this] = SIDE_TABLE_DEALLOCATING;//设置为需要dealloc
} else if (it->second < SIDE_TABLE_DEALLOCATING) {//没有引用计数值
// SIDE_TABLE_WEAKLY_REFERENCED may be set. Don't change it.
do_dealloc = true;
it->second |= SIDE_TABLE_DEALLOCATING;//给it->second赋值
} else if (! (it->second & SIDE_TABLE_RC_PINNED)) {//引用计数减一
it->second -= SIDE_TABLE_RC_ONE;
}
table.unlock();
if (do_dealloc && performDealloc) {//对象需要被销毁
((void(*)(objc_object *, SEL))objc_msgSend)(this, SEL_dealloc);//发送消息调用dealloc销毁对象。
}
return do_dealloc;
}
复制代码
2.1通过this没有找到RefcountMap
如果没找打RefcountMap对象do_dealloc 设置位 true table.refcnts[this] = SIDE_TABLE_DEALLOCATING设置标志位为1为下边清除weak——table——t表中的对象设置为nil做准备。 ##2.2引入计数已经清0
do_dealloc = true;
it->second |= SIDE_TABLE_DEALLOCATING;
复制代码
代码和2.1操作相同标志位设置。
2.3引用计数减1。
it->second -= SIDE_TABLE_RC_ONE;
复制代码
2.4根据标志位判断是否需要dealloc。
if (do_dealloc && performDealloc) {//对象需要被销毁
((void(*)(objc_object *, SEL))objc_msgSend)(this, SEL_dealloc);//发送消息调用dealloc销毁对象。
}
复制代码
如果标志位都为YES调用objc_msgSend销毁对象。
3.refcntStorage结构事例
SIDE_TABLE_WEAKLY_REFERENCED (1UL<<0)
SIDE_TABLE_WEAKLY_REFERENCED(是否有弱引用)1,有0,没有
复制代码
SIDE_TABLE_DEALLOCATING (1UL<<1)
SIDE_TABLE_DEALLOCATING(是否要被销毁)1,被标记 0,不需要被销毁
复制代码
SIDE_TABLE_RC_ONE (1UL<<2)
SIDE_TABLE_RC_ONE添加引用计数的值左移两位想当于加4.
复制代码
SIDE_TABLE_RC_PINNED (1UL<<(WORD_BITS-1))
SIDE_TABLE_RC_PINNE(如果为1引用计数到达最大值)
复制代码
#ifdef __LP64__
# define WORD_SHIFT 3UL
# define WORD_MASK 7UL
# define WORD_BITS 64//64位系统定义为64
#else
# define WORD_SHIFT 2UL
# define WORD_MASK 3UL
# define WORD_BITS 32
#endif
复制代码