queue 结构

默认生成的 dispatch_queue_t 有 1 个 main_queue, 8个全局的 global_queue

define

点击显示源代码

typedef struct dispatch_queue_s *dispatch_queue_t;

1个 main_queue

main_queueserial queue, 是否是串行队列, 通过 dq_width标识, serial queuedq_width1concurrency queuedq_widthUINT32_MAX

define

点击显示源代码

DISPATCH_CACHELINE_ALIGN
struct dispatch_queue_s _dispatch_main_q = {
	.do_vtable = &_dispatch_queue_vtable, /// queue type vtable
	.do_targetq = &_dispatch_root_queues[
			DISPATCH_ROOT_QUEUE_IDX_DEFAULT_OVERCOMMIT_PRIORITY],
	.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT, /// 内部引用 
	.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT, /// 外部引用
	.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK,
	.dq_label = "com.apple.main-thread",
	.dq_running = 1,
	.dq_width = 1, // 派发队列宽度
	.dq_serialnum = 1, // 序列化值 (标识此结构题)
};

8个 global_queue

8 个 global queueconcurrency queue, 有8个的原因是,全局队列的类型由 priorityovercommit 选项组成

priorityovercommit

priority 有四个枚举 HIGH, DEFAULT, LOW, BACKGROUND

点击显示源代码

#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台

overcommittrue 或者 false, 代表 在执行任务的时候,是否强制创建线程。

我们平时使用的时候,惯用 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); 是使用 overcommit = false 的 4个全局队列, 其实还支持dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 2); ,来获取 overcommit = true 的全局队列。

执行输出

点击显示源代码

    NSLog(@"%@", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
    NSLog(@"%@", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 2));
    NSLog(@"%@", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 1));
2018-05-01 01:33:59.929598+0800 libdispatch-demo[53906:8498406] <OS_dispatch_queue_root: com.apple.root.background-qos>
2018-05-01 01:33:59.929790+0800 libdispatch-demo[53906:8498406] <OS_dispatch_queue_root: com.apple.root.background-qos.overcommit>
2018-05-01 01:33:59.929908+0800 libdispatch-demo[53906:8498406] (null)

原因见实现

点击显示源代码

dispatch_queue_t
dispatch_get_global_queue(long priority, unsigned long flags)
{
	/**
	 * DISPATCH_QUEUE_OVERCOMMIT = 0x2ull
	 * 即 flags 不等于 0 或者 2时 会返回null
     * 因为会无视目前的计算机状况,后续会创建一个新的线程来关联一个新的queue进行处理任务。
	 */
	if (flags & ~DISPATCH_QUEUE_OVERCOMMIT) {
		return NULL;
	}
	/**
	 * 当flags 为 2时, 会启用 overcommit
     * 当flags 为 0时, 不会启用 overcommit
	 */
	return _dispatch_get_root_queue(priority,
			flags & DISPATCH_QUEUE_OVERCOMMIT);
}

define

点击显示源代码

DISPATCH_CACHELINE_ALIGN
struct dispatch_queue_s _dispatch_root_queues[] = {
	[DISPATCH_ROOT_QUEUE_IDX_LOW_PRIORITY] = {
		.do_vtable = &_dispatch_queue_root_vtable, /// 初始化根队列 verb table
		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT, /// 初始化内部引用 ~0u unsigned int max
		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT, /// 初始化外部引用 ~0u unsigned int max
		.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK, /// 初始化 挂起计数 1u
		.do_ctxt = &_dispatch_root_queue_contexts[      /// 设置上下文 启用pthread_wrokqueue 情况下 {pthread_workqueue_t : dgq_workqueue,(工作队列) uint32_t : dgq_pending (挂起)}
				DISPATCH_ROOT_QUEUE_IDX_LOW_PRIORITY],   

		.dq_label = "com.apple.root.low-priority", /// 标签
		.dq_running = 2, /// dq 正在运行 optional (0, 1, 2) 0 : 未运行
		.dq_width = UINT32_MAX, /// 并行宽度
		.dq_serialnum = 4, /// 序列化标记
	},
	// ...省略剩余7个
};

do_vtabledo_ctxt 以及 dq_items_headdq_items_taildc

main queue 和 global queue 的数据结构中 另外比较大的不同就是 do_vtable (动作表) 和 do_ctxt (上下文)

do_vtable 中有queue的生命周期函数信息

do_ctxt 中有 线程实现信息

dq_items_head, dq_items_tail 是用于存储任务的链表,enqueue 和 dequeue 都是调用原子性函数实现,gcd能够多线程安全的原因

dc是存储任务内容的数据结构

后续介绍道 队列唤醒任务调度派发 再详细介绍

信息说明

libdispatch 版本号: 187.10

相关内容

libdispatch (GCD源代码解析) 【queue 结构】1

libdispatch (GCD源代码解析) 【任务入队,队列唤起】2

libdispatch (GCD源代码解析) 【任务调度】3

libdispatch (GCD源代码解析) 【同步】4

可执行的libdispatch源代码

https://github.com/AwayQu/libxdispatch