上一回從public API的角度看了如何新建一個(gè)隊(duì)列、哪些字段有關(guān)隊(duì)列優(yōu)先級(jí)吻育、以及隊(duì)列的優(yōu)先級(jí)怎么設(shè)置念秧。這一回就從源碼的角度來證實(shí)上一回的猜測(cè)。
一布疼、_dispatch_lane_create_with_target 探索
1.1 dispatch_get_main_queue()
- 轉(zhuǎn)寫成cpp文件:
xcrun -sdk iphonesimulator clang -arch x86_64 -rewrite-objc main.m
摊趾,得到以下信息:_dispatch_main_q
dispatch_queue_main_t
dispatch_get_main_queue(void)
{
return (( dispatch_queue_main_t)&(_dispatch_main_q));
}
- 在GCD源碼中找到
_dispatch_main_q
的定義
struct dispatch_queue_static_s _dispatch_main_q = {
DISPATCH_GLOBAL_OBJECT_HEADER(queue_main),
#if !DISPATCH_USE_RESOLVERS
.do_targetq = _dispatch_get_default_queue(true),
#endif
.dq_state = DISPATCH_QUEUE_STATE_INIT_VALUE(1) |
DISPATCH_QUEUE_ROLE_BASE_ANON,
.dq_label = "com.apple.main-thread",
.dq_atomic_flags = DQF_THREAD_BOUND | DQF_WIDTH(1),
.dq_serialnum = 1,
};
- 第一行:
DISPATCH_GLOBAL_OBJECT_HEADER(queue_main)
,在GCD的類型定義的文章中解釋的非常詳細(xì)了游两; - 第二行:
.do_targetq = _dispatch_get_default_queue(true)
砾层,在上一回的講解中已經(jīng)知道了,主隊(duì)列仍然依賴于一個(gè)根隊(duì)列贱案,而這里便是對(duì)targetq的設(shè)置肛炮,最后會(huì)走到_dispatch_root_queues
方法中去,這個(gè)方法放在下面做講解; - 第三行:
.dq_state = DISPATCH_QUEUE_STATE_INIT_VALUE(1) | DISPATCH_QUEUE_ROLE_BASE_ANON
铸董,上一回的日志中就看到了這個(gè)屬性祟印,從這里的賦值來看,這個(gè)屬性是一個(gè)比較大的數(shù)值粟害,具體值的大小可以在源碼中看到蕴忆,主隊(duì)列的默認(rèn)值為:0x001ffe1000000000
,而最終輸出的值不一樣悲幅,說明后面修改過該值套鹅。
dq_state初始值 - 第四行:
.dq_label = "com.apple.main-thread"
,主隊(duì)列的標(biāo)識(shí)汰具,跟輸出的結(jié)果一致卓鹿; - 第五行:
.dq_atomic_flags = DQF_THREAD_BOUND | DQF_WIDTH(1)
,可能跟線程安全相關(guān)留荔; - 第六行:
.dq_serialnum = 1
吟孙,很簡(jiǎn)單的猜測(cè)為串行隊(duì)列,任務(wù)數(shù)為1聚蝶;
1.2 dispatch_get_global_queue()
在源碼中找到dispatch_get_global_queue
的定義杰妓。代碼邏輯非常簡(jiǎn)單,確定隊(duì)列的優(yōu)先級(jí)碘勉,然后根據(jù)優(yōu)先級(jí)獲取一個(gè)根隊(duì)列巷挥。
第一行:flags & ~(unsigned long)DISPATCH_QUEUE_OVERCOMMIT
,做了一個(gè)限制验靡,保證任何非0數(shù)都返回一個(gè)NULL倍宾。(實(shí)測(cè)2是可以通過的,可能是將來預(yù)留的某種標(biāo)識(shí)胜嗓,實(shí)際中別使用高职,玩源碼的時(shí)候可以測(cè)試下)。
最后根據(jù)_dispatch_get_root_queue
辞州,返回一個(gè)根隊(duì)列初厚,函數(shù)的第二個(gè)參數(shù)很有意思,flag=0
孙技,那么這個(gè)參數(shù)就定為false,也即并行隊(duì)列排作。
dispatch_queue_global_t
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;
}
return _dispatch_get_root_queue(qos, flags & DISPATCH_QUEUE_OVERCOMMIT);
}
1.3 dispatch_queue_create()
dispatch_queue_create
方法最終走到了_dispatch_lane_create_with_target
方法牵啦。
前面兩個(gè)參數(shù):label
、attr
上一回講過了妄痪,并會(huì)透?jìng)鞯较聦臃椒ǎ?br>
后面兩個(gè)參數(shù):tq:DISPATCH_TARGET_QUEUE_DEFAULT
表示新建一個(gè)隊(duì)列的默認(rèn)targetq是默認(rèn)優(yōu)先級(jí)的哈雏,legacy:true
表示使用遺留類。具體的含義會(huì)在_dispatch_lane_create_with_target 流程
中講解。
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 流程
對(duì)源碼取出一些條件判斷土浸,取出主流程,這里忽略的legacy
參數(shù)相關(guān)邏輯彭羹,這個(gè)參數(shù)主要是控制隊(duì)列的釋放條件黄伊。剩余部分如下所示:
static dispatch_queue_t
_dispatch_lane_create_with_target(const char *label, dispatch_queue_attr_t dqa,
dispatch_queue_t tq, bool legacy)
{
// 獲取隊(duì)列屬性描述
dispatch_queue_attr_info_t dqai = _dispatch_queue_attr_to_info(dqa);
// 步驟 1:通用參數(shù)設(shè)置
// 關(guān)于 qos 的一些判斷條件省略,直接取重點(diǎn)流程
dispatch_qos_t qos = dqai.dqai_qos;
_dispatch_queue_attr_overcommit_t overcommit = dqai.dqai_overcommit;
// 串行隊(duì)列默認(rèn)是 overcommit
overcommit = dqai.dqai_concurrent ?
_dispatch_queue_attr_overcommit_disabled :
_dispatch_queue_attr_overcommit_enabled;
// 設(shè)置 targetq
tq = _dispatch_get_root_queue(
qos == DISPATCH_QOS_UNSPECIFIED ? DISPATCH_QOS_DEFAULT/*4*/ : qos,
overcommit == _dispatch_queue_attr_overcommit_enabled)->_as_dq;
// 步驟 2:初始化隊(duì)列
const void *vtable;
// 設(shè)置隊(duì)列標(biāo)識(shí)
dispatch_queue_flags_t dqf = legacy ? DQF_MUTABLE : 0;
// 設(shè)置是串行隊(duì)列還是并行隊(duì)列
if (dqai.dqai_concurrent) {
vtable = DISPATCH_VTABLE(queue_concurrent);
} else {
vtable = DISPATCH_VTABLE(queue_serial);
}
// 配置隊(duì)列的標(biāo)簽
if (label) {
const char *tmp = _dispatch_strdup_if_mutable(label);
label = tmp;
}
// 分配隊(duì)列內(nèi)存
dispatch_lane_t dq = _dispatch_object_alloc(vtable,
sizeof(struct dispatch_lane_s));
// 初始化隊(duì)列
_dispatch_queue_init(dq, dqf, dqai.dqai_concurrent ?
DISPATCH_QUEUE_WIDTH_MAX : 1, DISPATCH_QUEUE_ROLE_INNER |
(dqai.dqai_inactive ? DISPATCH_QUEUE_INACTIVE : 0));
// 設(shè)置隊(duì)列標(biāo)簽
dq->dq_label = label;
// 設(shè)置隊(duì)列優(yōu)先級(jí)
dq->dq_priority = _dispatch_priority_make((dispatch_qos_t)dqai.dqai_qos,
dqai.dqai_relpri);
if (overcommit == _dispatch_queue_attr_overcommit_enabled) {
dq->dq_priority |= DISPATCH_PRIORITY_FLAG_OVERCOMMIT;
}
// 設(shè)置并持有目標(biāo)隊(duì)列
_dispatch_retain(tq);
dq->do_targetq = tq;
// 返回隊(duì)列
return _dispatch_trace_queue_create(dq)._dq;
}
2.1 _dispatch_queue_attr_to_info(dqa)
dqa
就是通過dispatch_queue_create
的第二個(gè)參數(shù)透?jìng)鬟^來的值派殷。這個(gè)屬性包含的值也是相當(dāng)有限的还最,但在創(chuàng)建隊(duì)列的過程中,非常依賴由dqa
這個(gè)值生成的結(jié)果dqai
毡惜,說明GCD中的屬性之間會(huì)有比較多的關(guān)聯(lián)拓轻。例如:dqai_concurrent
可以確定overcommit
屬性,而overcommit
的值又會(huì)影響dq_priority
屬性经伙。而蘋果將它們都通過計(jì)算存在一個(gè)值里面扶叉。可以看一下它的賦值過程:
size_t idx = (size_t)(dqa - _dispatch_queue_attrs);
dqai.dqai_inactive = (idx % DISPATCH_QUEUE_ATTR_INACTIVE_COUNT);
idx /= DISPATCH_QUEUE_ATTR_INACTIVE_COUNT;
dqai.dqai_concurrent = !(idx % DISPATCH_QUEUE_ATTR_CONCURRENCY_COUNT);
idx /= DISPATCH_QUEUE_ATTR_CONCURRENCY_COUNT;
dqai.dqai_relpri = -(int)(idx % DISPATCH_QUEUE_ATTR_PRIO_COUNT);
idx /= DISPATCH_QUEUE_ATTR_PRIO_COUNT;
dqai.dqai_qos = idx % DISPATCH_QUEUE_ATTR_QOS_COUNT;
idx /= DISPATCH_QUEUE_ATTR_QOS_COUNT;
dqai.dqai_autorelease_frequency =
idx % DISPATCH_QUEUE_ATTR_AUTORELEASE_FREQUENCY_COUNT;
idx /= DISPATCH_QUEUE_ATTR_AUTORELEASE_FREQUENCY_COUNT;
dqai.dqai_overcommit = idx % DISPATCH_QUEUE_ATTR_OVERCOMMIT_COUNT;
idx /= DISPATCH_QUEUE_ATTR_OVERCOMMIT_COUNT;
有興趣的話帕膜,可以每個(gè)值都替換進(jìn)去枣氧,看一看類型的變化。
2.2 通用參數(shù)設(shè)置
這一步主要設(shè)置以下三個(gè)屬性:
qos = dqai.dqai_qos
- 外部傳進(jìn)來的 attr泳叠;
- 將 attr 中的優(yōu)先級(jí)保存進(jìn)
info 中 qos
字段作瞄; - 取 info 中的 qos;
overcommit = dqai.dqai_concurrent ? _dispatch_queue_attr_overcommit_disabled : _dispatch_queue_attr_overcommit_enabled
- 外部傳進(jìn)來的 attr危纫;
- 將 attr 中串行/并行屬性保存進(jìn)
info 中 dqai_concurrent
字段宗挥; - 根據(jù)
info 中 dqai_concurrent
決定 overcommit 字段。并行隊(duì)列:disabled种蝶,串行隊(duì)列:enabled
tq = _dispatch_get_root_queue( qos == DISPATCH_QOS_UNSPECIFIED ? DISPATCH_QOS_DEFAULT/*4*/ : qos, overcommit == _dispatch_queue_attr_overcommit_enabled)->_as_dq;
- 根據(jù)上面得到的
qos
和overcommit
來獲取 target契耿; - 走到
_dispatch_get_root_queue
流程;
2.3 初始化隊(duì)列
- 分配內(nèi)存螃征。這個(gè)方法最終會(huì)調(diào)到:
malloc_zone_calloc(_dispatch_ccache_zone, (n), (s))
dispatch_lane_t dq = _dispatch_object_alloc(vtable,
sizeof(struct dispatch_lane_s));
- 初始化隊(duì)列搪桂。內(nèi)部會(huì)根據(jù)幾個(gè)參數(shù)對(duì)隊(duì)列的屬性進(jìn)行初始化。
_dispatch_queue_init(dq, dqf, dqai.dqai_concurrent ?
DISPATCH_QUEUE_WIDTH_MAX : 1, DISPATCH_QUEUE_ROLE_INNER |
(dqai.dqai_inactive ? DISPATCH_QUEUE_INACTIVE : 0));
- 持有tq盯滚。targetq引用計(jì)數(shù)+1踢械,targetq指針指向tq。
// 設(shè)置并持有目標(biāo)隊(duì)列
_dispatch_retain(tq);
dq->do_targetq = tq;
三魄藕、dispatch_queue_attr_info_t 詳解
typedef struct dispatch_queue_attr_info_s {
dispatch_qos_t dqai_qos : 8;
int dqai_relpri : 8;
uint16_t dqai_overcommit:2;
uint16_t dqai_autorelease_frequency:2;
uint16_t dqai_concurrent:1;
uint16_t dqai_inactive:1;
} dispatch_queue_attr_info_t;
- dqai_qos:queue的target的優(yōu)先級(jí)
- dqai_relpri:關(guān)聯(lián)優(yōu)先級(jí)内列。queue在target中的優(yōu)先級(jí)
- dqai_overcommit:是否可以overcommit。依賴于dqai_concurrent屬性背率,串行隊(duì)列:overcommit為true话瞧,并行隊(duì)列為false
- dqai_autorelease_frequency:自動(dòng)釋放頻率
- dqai_concurrent:是否是并行隊(duì)列
- dqai_inactive:是否激活
下面可以靜態(tài)感受一下蘋果對(duì) info 的賦值:
- 取出一個(gè)相對(duì)下標(biāo)嫩与;
- 然后對(duì)每個(gè)段輾轉(zhuǎn)取余;
- 取完某個(gè)段的值之后便將其移除交排;
size_t idx = (size_t)(dqa - _dispatch_queue_attrs);
dqai.dqai_inactive = (idx % DISPATCH_QUEUE_ATTR_INACTIVE_COUNT);
idx /= DISPATCH_QUEUE_ATTR_INACTIVE_COUNT;
dqai.dqai_concurrent = !(idx % DISPATCH_QUEUE_ATTR_CONCURRENCY_COUNT);
idx /= DISPATCH_QUEUE_ATTR_CONCURRENCY_COUNT;
dqai.dqai_relpri = -(int)(idx % DISPATCH_QUEUE_ATTR_PRIO_COUNT);
idx /= DISPATCH_QUEUE_ATTR_PRIO_COUNT;
dqai.dqai_qos = idx % DISPATCH_QUEUE_ATTR_QOS_COUNT;
idx /= DISPATCH_QUEUE_ATTR_QOS_COUNT;
dqai.dqai_autorelease_frequency =
idx % DISPATCH_QUEUE_ATTR_AUTORELEASE_FREQUENCY_COUNT;
idx /= DISPATCH_QUEUE_ATTR_AUTORELEASE_FREQUENCY_COUNT;
dqai.dqai_overcommit = idx % DISPATCH_QUEUE_ATTR_OVERCOMMIT_COUNT;
idx /= DISPATCH_QUEUE_ATTR_OVERCOMMIT_COUNT;
上面的宏定義:
#define DISPATCH_QUEUE_ATTR_OVERCOMMIT_COUNT 3
#define DISPATCH_QUEUE_ATTR_AUTORELEASE_FREQUENCY_COUNT 3
#define DISPATCH_QUEUE_ATTR_QOS_COUNT (DISPATCH_QOS_MAX + 1)
#define DISPATCH_QUEUE_ATTR_PRIO_COUNT (1 - QOS_MIN_RELATIVE_PRIORITY)
#define DISPATCH_QUEUE_ATTR_CONCURRENCY_COUNT 2
#define DISPATCH_QUEUE_ATTR_INACTIVE_COUNT 2
#define DISPATCH_QUEUE_ATTR_COUNT ( \
DISPATCH_QUEUE_ATTR_OVERCOMMIT_COUNT * \
DISPATCH_QUEUE_ATTR_AUTORELEASE_FREQUENCY_COUNT * \
DISPATCH_QUEUE_ATTR_QOS_COUNT * \
DISPATCH_QUEUE_ATTR_PRIO_COUNT * \
DISPATCH_QUEUE_ATTR_CONCURRENCY_COUNT * \
DISPATCH_QUEUE_ATTR_INACTIVE_COUNT )
#define DISPATCH_QOS_UNSPECIFIED ((dispatch_qos_t)0)
#define DISPATCH_QOS_MAINTENANCE ((dispatch_qos_t)1)
#define DISPATCH_QOS_BACKGROUND ((dispatch_qos_t)2)
#define DISPATCH_QOS_UTILITY ((dispatch_qos_t)3)
#define DISPATCH_QOS_DEFAULT ((dispatch_qos_t)4)
#define DISPATCH_QOS_USER_INITIATED ((dispatch_qos_t)5)
#define DISPATCH_QOS_USER_INTERACTIVE ((dispatch_qos_t)6)
#define DISPATCH_QOS_MIN DISPATCH_QOS_MAINTENANCE
#define DISPATCH_QOS_MAX DISPATCH_QOS_USER_INTERACTIVE
#define DISPATCH_QOS_SATURATED ((dispatch_qos_t)15)
typedef unsigned long pthread_priority_t;
#define QOS_MIN_RELATIVE_PRIORITY (-15)
#define _PTHREAD_PRIORITY_FLAGS_MASK (~0xffffff)
#define _PTHREAD_PRIORITY_QOS_CLASS_MASK 0x00ffff00
#define _PTHREAD_PRIORITY_QOS_CLASS_SHIFT (8ull)
#define _PTHREAD_PRIORITY_PRIORITY_MASK 0x000000ff
#define _PTHREAD_PRIORITY_OVERCOMMIT_FLAG 0x80000000
#define _PTHREAD_PRIORITY_SCHED_PRI_FLAG 0x20000000
#define _PTHREAD_PRIORITY_FALLBACK_FLAG 0x04000000
#define _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG 0x02000000
#define _PTHREAD_PRIORITY_NEEDS_UNBIND_FLAG 0x01000000
#define _PTHREAD_PRIORITY_ENFORCE_FLAG 0x10000000
除了GCD內(nèi)部調(diào)用的方法是這樣划滋,上一回講到的dispatch_queue_attr_make_with_qos_class
方法中也是用的類似的方法給屬性賦值,包括另外兩個(gè)未展開講解的方法也是一樣:
dispatch_queue_attr_make_initially_inactive
dispatch_queue_attr_make_with_autorelease_frequency
下面附上這三個(gè)方法的源碼:
dispatch_queue_attr_t
dispatch_queue_attr_make_with_qos_class(dispatch_queue_attr_t dqa,
dispatch_qos_class_t qos_class, int relpri)
{
if (!_dispatch_qos_class_valid(qos_class, relpri)) {
return (dispatch_queue_attr_t)dqa;
}
dispatch_queue_attr_info_t dqai = _dispatch_queue_attr_to_info(dqa);
dqai.dqai_qos = _dispatch_qos_from_qos_class(qos_class);
dqai.dqai_relpri = relpri;
return _dispatch_queue_attr_from_info(dqai);
}
dispatch_queue_attr_t
dispatch_queue_attr_make_initially_inactive(dispatch_queue_attr_t dqa)
{
dispatch_queue_attr_info_t dqai = _dispatch_queue_attr_to_info(dqa);
dqai.dqai_inactive = true;
return _dispatch_queue_attr_from_info(dqai);
}
dispatch_queue_attr_t
dispatch_queue_attr_make_with_autorelease_frequency(dispatch_queue_attr_t dqa,
dispatch_autorelease_frequency_t frequency)
{
switch (frequency) {
case DISPATCH_AUTORELEASE_FREQUENCY_INHERIT:
case DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM:
case DISPATCH_AUTORELEASE_FREQUENCY_NEVER:
break;
}
dispatch_queue_attr_info_t dqai = _dispatch_queue_attr_to_info(dqa);
dqai.dqai_autorelease_frequency = (uint16_t)frequency;
return _dispatch_queue_attr_from_info(dqai);
}
到這里埃篓,隊(duì)列中的屬性就是非常明了了处坪。
【補(bǔ)充】dispatch_autorelease_frequency
關(guān)于create流程中l(wèi)egacy參數(shù)確定的取值
DISPATCH_ENUM(dispatch_autorelease_frequency, unsigned long,
DISPATCH_AUTORELEASE_FREQUENCY_INHERIT DISPATCH_ENUM_API_AVAILABLE(
macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) = 0,
DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM DISPATCH_ENUM_API_AVAILABLE(
macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) = 1,
DISPATCH_AUTORELEASE_FREQUENCY_NEVER DISPATCH_ENUM_API_AVAILABLE(
macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) = 2,
);
- DISPATCH_AUTORELEASE_FREQUENCY_INHERIT
繼承目標(biāo)隊(duì)列的釋放頻率
與目標(biāo)隊(duì)列的釋放頻率保持一致 - DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM
在每個(gè)block被異步添加到隊(duì)列中的時(shí)候push
在每個(gè)block執(zhí)行完成之后pop - DISPATCH_AUTORELEASE_FREQUENCY_NEVER
這種類型只針對(duì)全局隊(duì)列
并且不支持自定義的自動(dòng)釋放池的push和pop
四、_dispatch_root_queues 詳解
_dispatch_root_queues
源碼如下:
-
_DISPATCH_ROOT_QUEUE_IDX
宏定義是獲取根隊(duì)列的最終類型都许; -
_DISPATCH_ROOT_QUEUE_ENTRY
宏定義是給這個(gè)根隊(duì)列中的屬性進(jìn)行賦值稻薇; - 從第三個(gè)代碼塊到最后一個(gè)代碼塊,一起12個(gè)代碼塊胶征。
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,
),
};
- 這里的是12條系統(tǒng)維護(hù)的根隊(duì)列
- 每一種優(yōu)先級(jí)的隊(duì)列都有串行和并行兩種
- 也就是有6種塞椎,這六種優(yōu)先從上到下遞減
__QOS_ENUM(qos_class, unsigned int, QOS_CLASS_USER_INTERACTIVE __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x21, QOS_CLASS_USER_INITIATED __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x19, QOS_CLASS_DEFAULT __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x15, QOS_CLASS_UTILITY __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x11, QOS_CLASS_BACKGROUND __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x09, QOS_CLASS_UNSPECIFIED __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x00, );
- dispatch_get_main_queue
com.apple.root.default-qos.overcommit QOS_CLASS_DEFAULT
- dispatch_get_global_queue
com.apple.root.default-qos QOS_CLASS_DEFAULT