创立行列底层源码剖析
经过上篇文章 iOS 深化了解 GCD 函数和行列中,咱们了解函数和行列,知道行列的创立时经过 GCD 中的dispatch_queue_create
办法,下面咱们在libdispatch.dylib
(libdispatch-1173.60.1) 去探究行列是如何创立的(源码下载)
- 查找
dispatch_queue_create
dispatch_queue_t
dispatch_queue_create(const char *label, dispatch_queue_attr_t attr) {
return _dispatch_lane_create_with_target(label, attr, DISPATCH_TARGET_QUEUE_DEFAULT, true);
}
- 查找
_dispatch_lane_create_with_target
DISPATCH_NOINLINE
static dispatch_queue_t
_dispatch_lane_create_with_target(const char *label, dispatch_queue_attr_t dqa,
dispatch_queue_t tq, bool legacy) {
// dqai 创立 -
dispatch_queue_attr_info_t dqai = _dispatch_queue_attr_to_info(dqa);
// 第一步:规范化参数,例如qos, overcommit, tq
...
// 拼接行列名称
const void *vtable;
dispatch_queue_flags_t dqf = legacy ? DQF_MUTABLE : 0;
if (dqai.dqai_concurrent) { //vtable表明类的类型
// OS_dispatch_queue_concurrent
vtable = DISPATCH_VTABLE(queue_concurrent);
} else {
vtable = DISPATCH_VTABLE(queue_serial);
}
....
// 拓荒内存 生成响应的目标 queue
dispatch_lane_t dq = _dispatch_object_alloc(vtable,
sizeof(struct dispatch_lane_s)); // alloc
// 结构办法
// 依据 dqai.dqai_concurrent 的值,就能判断行列是串行仍是并发
_dispatch_queue_init(dq, dqf, dqai.dqai_concurrent ?
DISPATCH_QUEUE_WIDTH_MAX : 1, DISPATCH_QUEUE_ROLE_INNER |
(dqai.dqai_inactive ? DISPATCH_QUEUE_INACTIVE : 0)); // init
// 设置行列 label 标识符
dq->dq_label = label;
// 优先级处理
dq->dq_priority = _dispatch_priority_make((dispatch_qos_t)dqai.dqai_qos, dqai.dqai_relpri);
...
// 类似于类与元类的绑定,不是直接的继承联系,而是类似于模型与模板的联系
dq->do_targetq = tq;
_dispatch_object_debug(dq, "%s", __func__);
return _dispatch_trace_queue_create(dq)._dq;
}
【第一步】第6行经过_dispatch_queue_attr_to_info
办法传入dqa
(即行列类型,串行、并发
等)创立dispatch_queue_attr_info_t
类型的目标dqai
,用于存储行列的相关特点信息
。
_dispatch_queue_attr_to_info
办法代码如下:
【第二步】看423 ~ 430行,判断当前传入的 dqa 是串行(NULL)仍是并发。如果是串行(NULL)就直接回来 dqa,否则就继续往下走看432 ~ 460行。438行是苹果的算法,441 ~ 458行是位域。
【第三步】看16行经过DISPATCH_VTABLE
拼接行列名称,即vtable
。其间DISPATCH_VTABLE
是宏界说,如下所示,行列的类型是经过OS_dispatch_
+ 行列类型queue_concurrent
拼接而成的。
-
串行
行列类型:OS_dispatch_queue_serial
,验证如下
-
并发
行列类型:OS_dispatch_queue_concurrent
,验证如下
#define DISPATCH_VTABLE(name) DISPATCH_OBJC_CLASS(name)
#define DISPATCH_OBJC_CLASS(name) (&DISPATCH_CLASS_SYMBOL(name))
#define DISPATCH_CLASS(name) OS_dispatch_##name
【第四步】看26 ~ 30行经过_dispatch_object_alloc + _dispatch_queue_init
初始化行列,即dq
。其间在_dispatch_queue_init
传参中依据dqai.dqai_concurrent
的布尔值,就能判断行列是串行
仍是并发
,而vtable
表明行列的类型,阐明行列也是目标
。
- 进入
_dispatch_object_alloc -> _os_object_alloc_realized
办法中设置了 isa 的指向,从这里可以验证行列也是目标
的说法。
_dispatch_object_alloc
办法代码如下:
_os_object_alloc_realized
办法代码如下:
- 进入
_dispatch_queue_init
办法,行列类型是dispatch_queue_t
,并设置行列的相关特点。
【第五步】经过_dispatch_trace_queue_create
对创立的行列进行处理,其间_dispatch_trace_queue_create
是_dispatch_introspection_queue_create
封装的宏界说,最后会回来处理过的_dq
。
进入_dispatch_introspection_queue_create_hook -> dispatch_introspection_queue_get_info -> _dispatch_introspection_lane_get_info
中可以看出,与咱们自界说的类仍是有所区别的,创立行列
在底层的实现是经过模板创立
的。
总结
- 行列创立办法
dispatch_queue_create
中的参数二(即行列类型), 决定了下层中max & 1
(用于区分是串行仍是并发), 其间1
表明串行
。 -
queue
也是一个目标
,也需求经过底层 alloc + init 创立, 并且在 alloc 中也有一个class
, 这个class
是经过宏界说拼接
而成,并且同时会指定isa的指向
。 -
创立行列
在底层的处理是经过模板创立的,其类型是dispatch_introspection_queue_s
结构体。
dispatch_queue_create
底层剖析流程如下图所示