附录-OC源码-GCD:GCD 函数源码 `GET` 与 `Create`

使用版本:
libdispatch-1173.40.5.tar
涉及到的数据结构在我的另一篇 其他:数据结构源码解析
本篇还是我对函数源码的逐步探究, 核心内容在正文中: 正文: 以 GCD 的接口为引, 看源码实现

dispatch_get_main_queue

里面返回一个宏, 关键的地方在 _dispatch_main_q

dispatch_queue_main_t dispatch_get_main_queue(void){  
  return DISPATCH_GLOBAL_OBJECT(dispatch_queue_main_t, _dispatch_main_q);  
}  

可以看到, _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_get_global_queue

init.c
入参: long priority & unsigned long flags
核心代码: 返回一个 root_queue

return _dispatch_get_root_queue(qos, flags & DISPATCH_QUEUE_OVERCOMMIT);  

从头往下看: 忽略断言部分
~是按位取反
下面的代码是判断 flags 为某个值(我没算出来),时直接返回结束,

DISPATCH_QUEUE_OVERCOMMIT = 0x2ull  
if (flags & ~(unsigned long)DISPATCH_QUEUE_OVERCOMMIT)  

dispatch_qos_t 的本质是整型, 这里做的操作是, 把入参的priority, 通过一个转换函数转换为另一个整型qos
内部函数可以理解为是在实现两个 enum 的转换, 将外部定义的优先级,转为内部的执行优先级
qos(quality-of-service) 官方文档有提到:Apple Developer Documentation,其实就是线程中优先级的意思

typedef uint32_t dispatch_qos_t;  
dispatch_qos_t qos = _dispatch_qos_from_queue_priority(priority);  

这些判断结束后, 就是返回_dispatch_get_root_queue
完整代码如下:

dispatch_queue_t dispatch_get_global_queue(long priority, unsigned long 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);  
}  

_dispatch_get_root_queue & _dispatch_root_queues

这个函数直接看源码, 内部是返回一个变量, 这个变量在开始就已生成 _dispatch_root_queues

static inline dispatch_queue_global_t _dispatch_get_root_queue(dispatch_qos_t qos, bool overcommit)  
{  
  if (unlikely(qos < DISPATCH_QOS_MIN || qos > DISPATCH_QOS_MAX)) {  
    DISPATCH_CLIENT_CRASH(qos, "Corrupted priority");  
  }  
  return &_dispatch_root_queues[2 * (qos - 1) + overcommit];  
}  

其中两个宏被我放到了 其他: 数据结构使用的宏 中解析要注意的是
每个优先级,都会有另一个这个 优先级名字+overcommit 的下一级优先级

在一些参考文章中看到(有overcommit标记的队列会在任务提交时新创建一个线程), 暂时不知道怎么求证
整体优先级如下:

enum {  
  DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS = 0,  
  DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT,  
  DISPATCH_ROOT_QUEUE_IDX_BACKGROUND_QOS,  
  DISPATCH_ROOT_QUEUE_IDX_BACKGROUND_QOS_OVERCOMMIT,  
  DISPATCH_ROOT_QUEUE_IDX_UTILITY_QOS,  
  DISPATCH_ROOT_QUEUE_IDX_UTILITY_QOS_OVERCOMMIT,  
  DISPATCH_ROOT_QUEUE_IDX_DEFAULT_QOS,  
  DISPATCH_ROOT_QUEUE_IDX_DEFAULT_QOS_OVERCOMMIT,  
  DISPATCH_ROOT_QUEUE_IDX_USER_INITIATED_QOS,  
  DISPATCH_ROOT_QUEUE_IDX_USER_INITIATED_QOS_OVERCOMMIT,  
  DISPATCH_ROOT_QUEUE_IDX_USER_INTERACTIVE_QOS,  
  DISPATCH_ROOT_QUEUE_IDX_USER_INTERACTIVE_QOS_OVERCOMMIT,  
  _DISPATCH_ROOT_QUEUE_IDX_COUNT,  
};  

这整个 数组变量_dispatch_root_queues[], 内部通过MAINTENANCE 这类第一个参数, 生成dispatch_queue_global_s变量
然后通过MAINTENANCE, 0第一个第二个参数组合, 计算出在数组中的序号

struct dispatch_queue_global_s _dispatch_root_queues[] = {  
  _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_queue_create & dispatch_queue_create_with_target

这两函数, 实际都是在调用 _dispatch_lane_create_with_target

_dispatch_lane_create_with_target(  
	const char *label,   
	dispatch_queue_attr_t dqa,  
	dispatch_queue_t tq,   
	bool legacy  
)  

不同在于 dispatch_queue_create 入参为

_dispatch_lane_create_with_target(label, attr, DISPATCH_TARGET_QUEUE_DEFAULT, true);  

dispatch_queue_create_with_target 入参为

_dispatch_lane_create_with_target(label, dqa, tq, false);  

看完函数后会结合数据结构 dispatch_queue_attr_s : 会发现第三个参的dispatch_queue_t tq 就是最后创建的 queue 中的dq->do_targetq = tq;
在创建过程中, tq 一旦是空的, 最终创建的 queue, do_targetq 都会变成根据 qos 在 _dispatch_get_root_queue中查找

//dispatch_queue_create 时就是空的  
#define DISPATCH_TARGET_QUEUE_DEFAULT NULL  
  
if (!tq) {  
    tq = _dispatch_get_root_queue(  
        qos == DISPATCH_QOS_UNSPECIFIED ? DISPATCH_QOS_DEFAULT : qos,  
        overcommit == _dispatch_queue_attr_overcommit_enabled)->_as_dq;  

可以理解为创建的队列在默认情况下, 最终都是在一个队列里执行的(某个 root queue)
自定义的队列在最终都会被归为 root 中某个队列中执行

最后看代码(省略了大部分判断过程)

static dispatch_queue_t _dispatch_lane_create_with_target(const char *label, dispatch_queue_attr_t dqa,  
    dispatch_queue_t tq, bool legacy) {  
  dispatch_queue_attr_info_t dqai = _dispatch_queue_attr_to_info(dqa);  
	//...qos 计算  
	// tq 判校验,判空处理等  
	// 一旦上面将 tq 设为空,或者传入的是空, 都是从 root_queue 取东西  
  if (!tq) {  
    tq = _dispatch_get_root_queue(  
        qos == DISPATCH_QOS_UNSPECIFIED ? DISPATCH_QOS_DEFAULT : qos,  
        overcommit == _dispatch_queue_attr_overcommit_enabled)->_as_dq;  
  }  
	// 根据 并行/串行 初始化虚函数表  
  const void *vtable;  
  dispatch_queue_flags_t dqf = legacy ? DQF_MUTABLE : 0;  
  if (dqai.dqai_concurrent) {  
    vtable = DISPATCH_VTABLE(queue_concurrent);  
  } else {  
    vtable = DISPATCH_VTABLE(queue_serial);  
  }  
	// 开始初始化, 申请空间  
  dispatch_lane_t dq = _dispatch_object_alloc(vtable,  
      sizeof(struct dispatch_lane_s));  
	// 初始化值  
  _dispatch_queue_init(dq, dqf, dqai.dqai_concurrent ?  
      DISPATCH_QUEUE_WIDTH_MAX : 1, DISPATCH_QUEUE_ROLE_INNER |  
      (dqai.dqai_inactive ? DISPATCH_QUEUE_INACTIVE : 0));  
	// 设置入参  
  dq->dq_label = label;  
  dq->dq_priority = _dispatch_priority_make((dispatch_qos_t)dqai.dqai_qos,  
      dqai.dqai_relpri);  
	// 后面涉及两个函数,暂时没研究透,先省略  
  _dispatch_retain(tq);  
  dq->do_targetq = tq;  
  _dispatch_object_debug(dq, "%s", __func__);  
  return _dispatch_trace_queue_create(dq)._dq;  
}