本文是作者在学习iOS底层代码时所著,文章中会尽量使用确定性的词汇,旨在帮助想要轻度深入的读者能够快速了解iOS底层实现。文章中内容的逻辑自洽,但内容的正确性需要读者自行甄别,仅供参考。
在之前的文章中,我们学习了队列创建、异步任务创建执行的原理,在这个过程中,我们多次提到主队列、全局队列、自定义队列、root队列等等。这篇文章我们一起来看看,这些队列究竟是什么?
队列
主队列
要知道主队列是什么,我们需要知道,当我们在执行DispatchQueue.main时,我们在做什么,
public class var main: DispatchQueue {
return _swift_dispatch_get_main_queue()
}
继续看_swift_dispatch_get_main_queue,
static inline dispatch_queue_t
_swift_dispatch_get_main_queue(void) {
return dispatch_get_main_queue();
}
继续看dispatch_get_main_queue,
dispatch_queue_main_t
dispatch_get_main_queue(void)
{
// DISPATCH_GLOBAL_OBJECT是一个强转的宏,把后面的参数的类型转成前面的类型
return DISPATCH_GLOBAL_OBJECT(dispatch_queue_main_t, _dispatch_main_q);
}
继续看_dispatch_main_q,
struct dispatch_queue_static_s _dispatch_main_q = {
// 配置queue_main的vtable
DISPATCH_GLOBAL_OBJECT_HEADER(queue_main),
#if !DISPATCH_USE_RESOLVERS
// 获取.default状态的overcommit的root队列
.do_targetq = _dispatch_get_default_queue(true),
#endif
.dq_state = DISPATCH_QUEUE_STATE_INIT_VALUE(1) |
DISPATCH_QUEUE_ROLE_BASE_ANON,
// debug信息中常出现的label
.dq_label = "com.apple.main-thread",
// DQF_WIDTH(1)代表是串行队列
.dq_atomic_flags = DQF_THREAD_BOUND | DQF_WIDTH(1),
// 序号,之前我们获取的root队列序号是从3-15,主队列序号为1
.dq_serialnum = 1,
};
从这里可以看出,主队列是序号为1,label为com.apple.main-thread,targettq为默认的过载root队列,这样的队列。它在执行任务时创建的线程,就是我们熟悉的主线程。
全局队列
全局队列是我们日常使用中频率很高的队列,我们一起来看看DispatchQueue.global()做了什么,
public class func global(qos: DispatchQoS.QoSClass = .default) -> DispatchQueue {
return __dispatch_get_global_queue(Int(qos.rawValue.rawValue), 0)
}
继续看__dispatch_get_global_queue,
dispatch_get_global_queue(intptr_t priority, uintptr_t flags)
{
dispatch_assert(countof(_dispatch_root_queues) ==
DISPATCH_ROOT_QUEUE_COUNT);
if (flags & ~(unsigned long)DISPATCH_QUEUE_OVERCOMMIT) {
return DISPATCH_BAD_INPUT;
}
dispatch_qos_t qos = _dispatch_qos_from_queue_priority(priority);
#if !HAVE_PTHREAD_WORKQUEUE_QOS
if (qos == QOS_CLASS_MAINTENANCE) {
qos = DISPATCH_QOS_BACKGROUND;
} else if (qos == QOS_CLASS_USER_INTERACTIVE) {
qos = DISPATCH_QOS_USER_INITIATED;
}
#endif
if (qos == DISPATCH_QOS_UNSPECIFIED) {
return DISPATCH_BAD_INPUT;
}
// 前面都是在配置qos的值,
// 到这里可以看到是根据qos和flags,从root队列中取出一个队列返回
return _dispatch_get_root_queue(qos, flags & DISPATCH_QUEUE_OVERCOMMIT);
}
可以看出,全局队列就是其中一个root队列。
自定义队列
异步任务创建执行这篇文章中,就是以自定义队列为基础来讲的,
let queue = DispatchQueue(label: "com.concurrent", attributes: .concurrent)
swift代码中创建的queue确实是自定义的队列,但最终执行任务时,也是root队列在执行。
root队列
说了这么久的root队列,那么root队列到底是什么呢?
struct dispatch_queue_global_s _dispatch_root_queues[] = {
#define _DISPATCH_ROOT_QUEUE_IDX(n, flags) \
((flags & DISPATCH_PRIORITY_FLAG_OVERCOMMIT) ? \
DISPATCH_ROOT_QUEUE_IDX_##n##_QOS_OVERCOMMIT : \
DISPATCH_ROOT_QUEUE_IDX_##n##_QOS)
#define _DISPATCH_ROOT_QUEUE_ENTRY(n, flags, ...) \
[_DISPATCH_ROOT_QUEUE_IDX(n, flags)] = { \
DISPATCH_GLOBAL_OBJECT_HEADER(queue_global), \
.dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \
.do_ctxt = _dispatch_root_queue_ctxt(_DISPATCH_ROOT_QUEUE_IDX(n, flags)), \
.dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \
.dq_priority = flags | ((flags & DISPATCH_PRIORITY_FLAG_FALLBACK) ? \
_dispatch_priority_make_fallback(DISPATCH_QOS_##n) : \
_dispatch_priority_make(DISPATCH_QOS_##n, 0)), \
__VA_ARGS__ \
}
_DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, 0,
.dq_label = "com.apple.root.maintenance-qos",
.dq_serialnum = 4,
),
_DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.maintenance-qos.overcommit",
.dq_serialnum = 5,
),
_DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, 0,
.dq_label = "com.apple.root.background-qos",
.dq_serialnum = 6,
),
_DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.background-qos.overcommit",
.dq_serialnum = 7,
),
_DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, 0,
.dq_label = "com.apple.root.utility-qos",
.dq_serialnum = 8,
),
_DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.utility-qos.overcommit",
.dq_serialnum = 9,
),
_DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT, DISPATCH_PRIORITY_FLAG_FALLBACK,
.dq_label = "com.apple.root.default-qos",
.dq_serialnum = 10,
),
_DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT,
DISPATCH_PRIORITY_FLAG_FALLBACK | DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.default-qos.overcommit",
.dq_serialnum = 11,
),
_DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, 0,
.dq_label = "com.apple.root.user-initiated-qos",
.dq_serialnum = 12,
),
_DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.user-initiated-qos.overcommit",
.dq_serialnum = 13,
),
_DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, 0,
.dq_label = "com.apple.root.user-interactive-qos",
.dq_serialnum = 14,
),
_DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.user-interactive-qos.overcommit",
.dq_serialnum = 15,
),
};
根据这个宏_DISPATCH_ROOT_QUEUE_ENTRY,
#define _DISPATCH_ROOT_QUEUE_ENTRY(n, flags, ...) \
[_DISPATCH_ROOT_QUEUE_IDX(n, flags)] = { \
DISPATCH_GLOBAL_OBJECT_HEADER(queue_global), \
.dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \
.do_ctxt = _dispatch_root_queue_ctxt(_DISPATCH_ROOT_QUEUE_IDX(n, flags)), \
.dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \
.dq_priority = flags | ((flags & DISPATCH_PRIORITY_FLAG_FALLBACK) ? \
_dispatch_priority_make_fallback(DISPATCH_QOS_##n) : \
_dispatch_priority_make(DISPATCH_QOS_##n, 0)), \
__VA_ARGS__ \
}
我们可以看到,所谓的root队列,就是一些带有特定参数的队列。在执行各种逻辑(sync,async,group等等)中,根据各个参数的不同,产生不同的逻辑。
结语
由于能力有限,文章中难免出现疏漏或者根本性错误,欢迎指正。
如果文章对您有帮助,可以点个赞支持一下,谢谢!