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

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

其实没那么糟了,咱们能够尝试了解下这个结构,对探究ios底层源码很有帮助,假如不以模板的视点去考虑,那么在剖析源码的过程中,很多逻辑就会想漠然,底层的了解上就会止步不前

预览 list_array_tt

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

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

最简略粗鄙了解,从模板命名看,List Element,逻辑上便是一个容器List 与 元素Element的联系,不过不是简略的线性联系

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

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

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

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

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

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++的重载运算符的语法,便是把运算符重载为迭代器的函数,运算符当作函数,经过传参调用函数 完成迭代过程中的运算逻辑

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

自增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 中的迭代器剖析

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

或许会有人觉得这个List::iterator 了解起来有点困难

其实这个List便是模板 entsize_list_tt ,这么说或许仍是有点模糊 举个实例或许比较容易了解一些

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

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

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

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

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

咱们再分别看下 method_list_t, property_list_t 这几个模板详细定义

  • method_list_t

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

  • property_list_t

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

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

不管 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中的迭代器罢了

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

这是 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空间