博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内存管理Release和Retain实现原理
阅读量:6854 次
发布时间:2019-06-26

本文共 3072 字,大约阅读时间需要 10 分钟。

引入计数存储在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复制代码

转载于:https://juejin.im/post/5c7f59f3e51d454f8a0c4f70

你可能感兴趣的文章
Github 上 Star 最多的个人 Spring Boot 开源学习项目
查看>>
企业级大数据平台构建
查看>>
0302作业.
查看>>
关于:target与定位动画的奇怪现象
查看>>
linq
查看>>
css设置height 100%
查看>>
数据结构与算法基本学习笔记(5)
查看>>
【2-SAT】【DFS】【分类讨论】Gym - 101617K - Unsatisfying
查看>>
Eclipse+Tomcat+Ant 小记
查看>>
[转载]ubuntu防火墙设置
查看>>
poj3080
查看>>
java-注释、API之字符串(String)
查看>>
jQuery函数attr()和prop()的区别
查看>>
mysql 查询
查看>>
SAS9.4安装
查看>>
UIPageViewController-浅析
查看>>
[vscode] github travis 集成问题
查看>>
课后作业3:软件分析与用户体验分析
查看>>
Mysql空间数据,空间索引,Spatial Data,Spatial Index
查看>>
一周以来工作总结--关于位图索引
查看>>