ios底层核心模板结构 - list_array_tt & entsize_list_tt

探索objc底层原理过程中,经常会碰到一个模板 list_array_tt

你在类加载,方法查找,散列表,同步锁等等都会碰到这个结构,c++的模板功能十分强大,但代码看上去确实比较头疼

其实没那么糟了,我们可以尝试了解下这个结构,对探索ios底层源码很有帮助,如果不以模板的角度去考虑,那么在分析源码的过程中,很多逻辑就会想淡然,底层的理解上就会止步不前

初步预览 list_array_tt

image.png

list_array_tt 是个模板,存在于runtime头文件中,可见它对于runtime api的重要性了

最简单粗俗理解,从模板命名看,List Element,逻辑上就是一个容器List 与 元素Element的关系,不过不是简单的线性关系

image.png

list_array_tt 鸟瞰结构

  • 一个array_t 结构体

  • 一个迭代器

  • 一个list指针,不过比较特殊,它还有一个附加功能,可以表述数组

list_array_tt 关键方法整理

  • hasArray() 是否有数组功能

  • array() 返回数组容器

  • setArray(array_t *array)

  • count() 元素数量

  • begin() end() ... 迭代器迭代功能

  • countLists() 数组array的元素list的数量 也就是有多少个list

  • beginLists() endLists() 第一个list 与 最后一个list

  • attachLists(List* const * addedLists, uint32_t addedCount) array添加list逻辑 很重要

预览 entsize_list_tt

image.png

entsize_list_tt 也是个模板,也存在于runtime 头文件中

image.png

entsize_list_tt 鸟瞰结构

  • entsizeAndFlags 除了记录元素大小,同时额外比特位包含flag信息

  • count 可以粗俗理解为模板元素的数量

  • 也有一个迭代器

entsize_list_tt 关键方法整理

  • entsize() 元素大小

  • get(uint32_t i) 获取元素

  • byteSize() 模板List字节大小

  • begin() end() 迭代器迭代功能

此处发现有个迭代器,list_array_tt也有个迭代器,会感觉烦乱,后面我会拆解

entsize_list_tt 迭代分析

迭代器iterator是个内部结构体 内部结构

  • entsize 迭代元素大小

  • index 索引 主要是重载运算符号 中使用

  • element 迭代元素指针

迭代器iterator的迭代功能其实很简单,主要通过运算符号重载实现迭代器的 ++ -- *取元素 ->取元素指针 ==判断元素相等 != > < 比较大小

operator 重载符号 是c++的重载运算符的语法,就是把运算符重载为迭代器的函数,运算符当作函数,通过传惨调用函数 实现迭代过程中的运算逻辑

image.png

自增1 自减1 都是通过迭代器当前元素指针偏移 指针节点个数来实现的,可以对照链表偏移节点那样去理解 但你再仔细看下,这是内存偏移

可以简单猜测一下 此处的迭代器 在 list_array_tt中也会使用到,先不用考虑list_array_tt中的迭代器结构,从鸟瞰代码预览中,大致已经知道 list_array_tt 是个两层嵌套结构

list_array_tt 双层嵌套结构

  • 外层可以类似看作是个数组结构,数组元素为模板List

  • 模板List是内层结构,作为 list_array_tt的一个元素,而前面提到的迭代器主要是为了迭代List模板容器中的元素而创建的

  • 对于 list_array_tt中的迭代器,相信最终调用的还是 此处entsize_list_tt中的迭代器

回到 list_array_tt

list_array_tt 中的迭代器分析

image.png

可能会有人觉得这个List::iterator 理解起来有点困难

其实这个List就是模板 entsize_list_tt ,这么说可能还是有点迷糊 举个实例或许比较容易理解一些

image.png

objc类的底层结构 method_array_t property_array_t protocol_array_t 都是继承自list_array_t

而且 这几个数据结构 都采用了一样的模板结构,不管是叫 method_list_t, property_list_t, 还是 protocol_list_t

image.png

在 list_array_tt 中 都对应了 模板List,元素都是Element

我们再分别看下 method_list_t, property_list_t 这几个模板具体定义

  • method_list_t
image.png
  • property_list_t
image.png
image.png

不管 method_list_t, property_list_t 的名字怎么起,最终都是继承自 entsize_list_tt模板结构而来, 就是模板容器List

上面的例子稍微总结下

  • method_array_t properties_array_t protocol_array_t 或者其他什么结构,都套用一个通用嵌套模板容器

  • 如果你的结构复杂些,就用双层嵌套结构

  • 而结构如果简单,就复用这个双层嵌套,当作单层List容器使用,只不过外层array只有一个元素而已

  • 你可以试想一下ios中的分类,如果存在多个分类,均扩展同名方法,你会怎么设计呢?

  • 再者如果设计一个哈希结构,你又会怎么设计,我们都知道哈嘻是个函数,不同的参数,得到的哈嘻位置可能会重复,你又会怎么设计这个哈嘻结构呢?

试着多想想,发散开了想,既然runtime中这么多的复用这个结构,自然这个结构很重要了,其实不只iOS底层了,其他很多语言都有这样的类似结构

c++本身就是跨平台的,而你也许听过了解c++,就必须深入了解它的模板机制

好了 回归到上面的 list_array_tt 迭代器,在这个迭代器里,出现了 List::iterator

  • 仔细看前面的例子,看 method_list_t, property_list_t 继承关系截图 如 method_list_t 与 <> 中的 模板名字method_list_t 是一样的

  • 既然 method_list_t 继承自 entsize_list_tt, 那么 method_list_t中的迭代器就是 method_list_t::iterator

  • 这是具体实例,再还原为抽象模板就是 List::iterator

  • 如此 list_array_tt 迭代器就是调用了 entsize_list_tt中的迭代器而已

image.png

这是 list_array_tt 中的迭代器

Ptr就是模板List的指针封装而已,就是List的begin end函数,也就是 entsize_list_tt中的迭代器 begin end函数

至此 前面的关于 外层迭代器调用 内层迭代器的猜想得证

list_array_tt 中的迭代器操作理解

  • 重载运算符++ 外层元素也就当前访问从数组中的当前元素List ,平移到下一个元素List上

    然后迭代器中的m指向目标List的第一个元素,mEnd指向目标List的最后一个元素

  • 重载运算符 *取出 当前访问的目标List 中正指向的元素 也就是m指向的元素

list_array_tt 中成员array_t 与 list理解

  • 如果 list_array_tt 中设置了array,那么当前生效的就是 array_t结构,使用时遵循两层嵌套结构

    每次访问一定需要知道 begin end,就是 先找到 array_t, 初始取到 lists(array结构中的首地址 也就是第0个元素的地址)

    每次遍历 如 ++ 或 -- 也就是 lists移动到 后一个List 或 前一个List,同时 m指向目标List的第一个元素 mEnd指向目标List的最后一个元素

  • 而如果 list_array_tt 中未设置 array,那么就是单层结构

    使用list这个成员 就不存在 array的目标List平移查找逻辑了

  • 是否有双层嵌套结构 通过 arrayAndFlag & 1 来判断

  • 双层嵌套结构数组获取 arrayAndFlag & ~1 取得

list_array_tt - attachLists流程分析

到这儿就是这篇文章最核心的内容了,但是没有前面的铺垫,这块没法阐述

为什么重要,如果要了解ios类的加载流程,这个attachLists流程你肯定绕不过去,不然你没办法理解 rwe 以及分类的加载逻辑 那这块的认知始终会处于坍缩状态

void attachLists(List* const * addedLists, uint32_t addedCount)

  • 注意 参数 addedLists 是个模板List集合,存在多个模板List

  • 先判断是否有双层嵌套结构

  • 如果没有双层结构,也就是目前还没有数组,并且 addedLists中只有一个元素模板List

    那就继续保持无数组状态,只把 addedLists中唯一的元素List(addedLists[0])取出,赋给list

  • 如果没有双层结构,但addedLists中有多个元素模板List

    开辟一个数组array,数组元素个数为 addedCount 或者 addedCount + 1,取决于原来是否有list

    attachLists中的元素按顺序 从第0个位置开始,依次存放进 array中

    如果原来list存在,就把原list放进 array最后一个位置

  • 如果有双层嵌套结构,也就是已有数组

    新开辟一个数组newArray,数组元素个数为 addedCount + 原数组array中List个数count

    array中的旧元素,依次存放进 newArray中的 最后count个位置上

    addedLists中的元素,依次存放进 newArray中的前 addedCount 个位置上

    释放旧的array空间

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容