引入计数存储在SideTables表中存储结构如图所示。
1.Retain实现原理。
1.1对对象retain之后实现过程。
idobjc_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复制代码