GCD ① Dispatch Queue

Dispatch Queue 是什么呢?

    如如其名称所示,是执行处理的等待队列。应用程序编程人员通过 dispatch async 函数等 API ,在 Block 语法中记述想执行的处理并将其追加到 Dispatch Queue 中。Dispatch Queue 按照追加的顺序(先进先出 FIFO, First-In-First-Out)执行处理。

dispatch_queue执行处理

Dispatch Queue 的特点

  • 提供了一个简单明了的编程接口。
  • 提供自动和整体的线程池管理。
  • 内存效率要高得多(因为线程堆栈不会停留在应用程序内存中)。
  • 将任务异步分派到 Dispatch Queue 不会使队列死锁。

Dispatch Queue 的种类

    另外在执行处理时存在两种 Dispatch Queue ,一种是等待现在执行中处理的串行队列(Serial Dispatch Queue),另一种是不等待现在执行中处理的并发队列(Concurrent Dispatch Queue),如表所示。

Dispatch Queue 的种类 说明
Serial Dispatch Queue 等待现在执行中处理结束
Concurrent Dispatch Queue 不等待现在执行中处理结束
Serial Dispatch Queue 和 Concurrent Dispatch Queue

     Concurrent Dispatch Queue 虽然不用等待处理结束,可以并行执行多个处理,但并行执行的处理数最取决于当前系统的状态。即 iOSOS X 基于 Dispatch Queue 中的处理数、CPU 核数以及 CPU 负荷等当前系统的状态来决定 Concurrent Dispatch Queue 中并行执行的处理数。所谓“并行执行。就是使用多个线程同时执行多个处理。

Dispatch_Queue和线程的关系

Dispatch Queue 的获取

     虽然知道了有 Serial Dispatch QueueConcurrent Dispatch Queue 这两种,但如何才能得到这些 Dispatch Queue 呢?方法有两种。

dispatch_queue_create

第一种方法是通过 GCDAPI 生成 Dispatch Queuedispatch queue create 函数可生成 Dispatch Queue


dispatch_queue_create(const char *_Nullable label,
  dispatch_queue_attr_t _Nullable attr);

      该函数的第一个参数指定 Serial Dispatch Queue 的名称。 Dispatch Queue 的名称推荐使用应用程序 ID 这种逆序全程域名 (FQDN, fully qualified domain name) 。该名称在 XcodeInstruments 的调试器中作为 Dispatch Queue 名称表示。另外,该名称也出现在应用程序崩溃时所生成的 CrashLog 中。我们命名时应遵循这样的原则:对我们编程人员来说简单易懂,对用户来说也要易憧。

     生成 Serial Dispatch Queue.像下面代码这样,将第二个参数指定为 NULL。生成 *Concurrent Dispatch Queue 时,像下面代码一样,指定为 DISPATCH_QUEUE_CONCURRENT

  • Serial Dispatch Queue

       dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create ("com.example.gcd.MySerialDispatchQueue",NULL);
    

          如前所述,Concurrent Dispatch Queue 并行执行多个追加处理,而 Serial Dispatch Queue 同时只能执行 1 个追加处理。虽然 Serial Dispatch QueueConcurrent Dispatch Queue 受到系统资源的限制,但用 dispatch queue create 函数可生成任意多个 Dispatch Queue
          当生成多个 Serial Dispatch Queue 时,各个 Serial Dispatch Queue 将并行执行。虽然在 1 个 Serial Dispatch Queue 中同时只能执行一个迫加处理,但如果将处理分别追加到 4 个 Serial Dispatch Queue 中,各个 Serial Dispatch Queue 执行 1 个,即为同时执行 4 个处理。

    多个Serial Dispatch Queue

          像之前列举的多线程编程问题一样,如果过多使用多线程,就会消耗大量内存,引起大量的上下文切换,大幅度降低系统的响应性能。


    多个Serial Dispatch Queue引发的问题
  • Concurrent Dispatch Queue

     dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("com.example.gcd.MyConcurrentDispatchQueue",DISPATCH_QUEUE_CONCURRENT);
    

Main Dispatch Queue/Global Dispatch Queue

     除了 dispatch_queue_create 创建,还可以获取系统标准提供的 Dispatch Queue 。实际上不用特意生成 Dispatch Queue 。系统也会给我们提供几个。那就是 Main Dispatch QueueGlobal Dispalch Queue

  • Main Dispatch Queue

        Main Dispatch Queue 正如其名称中含有的 Main 一样,是在主线程中执行的 Dispatch Queue。因为主线程只冇 1 个,所以 Main Dispatch Queue 自然就是 Serial Dispatch Queue
          追加到 Main Dispatch Queue 的处理在主线程的 RunLoop 中执行。由于在主线程中执行,因此要将用户界面的更新等一些必须在主线程中执行的处理追加到 Main Dispatch Queue 使用。 这正好与 NSObject 类的 performSelectorOnMainThread 实例方法这一执行方法相同。

    Main Dispatch Queue

    
    /**
      Main Dispatch Queue 的获取方法
    */
    dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
    
    
  • Global Dispatch Queue
        另一个 Global Dispatch Queue 是所有应用程序都能够使用的 Concurrent Dispatch Queue 。虽然 Global Dispatch Queue 使用起来较为方便,但是在应用程序开发中,使用 dispatch_queue_create 创建维护 Dispatch_Queue 是有必要的。

    /**
    Global Dispatch Queue (默认优先级)的获取方法
    */
    dispatch_queue_t globalDispatchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAUL,0);
    
  • 优先级
        另外,Global Dispatch Queue 有 4 个执行优先级,分别是高优先级( High Priority ),默认优先级( Default Priority )、低优先级( Low Priority )和后台优先级( Background Priority )。通过 XNU 内核管理的用于 Global Dispatch Queue 的线程,将各自使用的 Global Dispatch Queue 的执行优先级作为线程的执行优先级使用。在向 Global Dispatch Queue 追加处理时,应选择与处理内容对应的执行优先级的 Global Dispatch Queue

    名称 Dispatch Queue 的种类 说明
    Main Dispatch Queue Serial Dispatch Queue 主线程执行
    Global Dispatch Queue ( High Priority ) Concurrent Dispatch queue 执行优先級:高(最高优先)
    Global Dispatch Queue ( Default Priority ) Concurrent Dispatch queue 执行优先級:默认
    Global Dispatch Queue ( Low Priority ) Concurrent Dispatch queue 执行优先级:低
    Global Dispatch Queue ( Background Priority ) Concurrent Dispatch queue 执行优先级:后台

dispatch_get_main_queue 实现

dispatch_get_main_queue 源码

打开 libdispatch 工程后搜索 dispatch_get_main_queue(void),找到源码如下:

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

DISPATCH_GLOBAL_OBJECT

DISPATCH_GLOBAL_OBJECT 是一个宏,因此等于 __bridge dispatch_queue_main_t &_dispatch_main_q;

#define OS_OBJECT_BRIDGE __bridge
#define DISPATCH_GLOBAL_OBJECT(type, object) ((OS_OBJECT_BRIDGE type)&(object))

_dispatch_main_q

搜索 _dispatch_main_qdispatch_queue_static_s 结构体,可以看到主队列在定义时就赋值,源码如下:

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_introspection_init

    在工程中搜索 _dispatch_main_q,可以看到 dispatch_introspection_init 函数中调用 _dispatch_trace_queue_create(&_dispatch_main_q);; 而 dispatch_introspection_initlibdispatch_init 就被调用。因此,主队列的创建是在 libdispatch.dylib 初始化时。

void
_dispatch_introspection_init(void)
{
 _dispatch_introspection.debug_queue_inversions =
   _dispatch_getenv_bool("LIBDISPATCH_DEBUG_QUEUE_INVERSIONS", false);

 // Hack to determine queue TSD offset from start of pthread structure
 uintptr_t thread = _dispatch_thread_self();
 thread_identifier_info_data_t tiid;
 mach_msg_type_number_t cnt = THREAD_IDENTIFIER_INFO_COUNT;
 kern_return_t kr = thread_info(pthread_mach_thread_np((void*)thread),
   THREAD_IDENTIFIER_INFO, (thread_info_t)&tiid, &cnt);
 if (!dispatch_assume_zero(kr)) {
  _dispatch_introspection.thread_queue_offset =
    (void*)(uintptr_t)tiid.dispatch_qaddr - (void*)thread;
 }
 _dispatch_thread_key_create(&dispatch_introspection_key,
   _dispatch_introspection_thread_remove);
 _dispatch_introspection_thread_add(); // add main thread

 for (size_t i = 0; i < DISPATCH_ROOT_QUEUE_COUNT; i++) {
  _dispatch_trace_queue_create(&_dispatch_root_queues[i]);
 }
#if DISPATCH_USE_MGR_THREAD && DISPATCH_USE_PTHREAD_ROOT_QUEUES
 _dispatch_trace_queue_create(_dispatch_mgr_q.do_targetq);
#endif
 _dispatch_trace_queue_create(&_dispatch_main_q);
 _dispatch_trace_queue_create(&_dispatch_mgr_q);
}

dispatch_queue_create 实现

    打开 libdispatch 工程后搜索 dispatch_queue_create(const char *label, dispatch_queue_attr_t attr) 关键字,源码如下:

#define DISPATCH_TARGET_QUEUE_DEFAULT NULL
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_queue_create 函数内部实现可以得知,调用 _dispatch_lane_create_with_target 私有函数,并传递标签 label 与类型 attr参数。 其中 DISPATCH_TARGET_QUEUE_DEFAULT 是宏定义 NULL

dispatch_queue_attr_t attr 是什么

    dispatch_queue_attr_t 类型是 dispatch queues 的属性,一般地,在调用 dispatch_queue_create函数时,会赋值 DISPATCH_QUEUE_SERIALDISPATCH_QUEUE_CONCURRENT,其宏定义源码如下:

#define DISPATCH_QUEUE_SERIAL NULL
#define DISPATCH_QUEUE_CONCURRENT \
  DISPATCH_GLOBAL_OBJECT(dispatch_queue_attr_t, \
  _dispatch_queue_attr_concurrent)

DISPATCH_QUEUE_CONCURRENT

    可以看到 DISPATCH_QUEUE_CONCURRENT 其实是 _dispatch_queue_attr_concurrent

#define DISPATCH_GLOBAL_OBJECT(type, object) ((OS_OBJECT_BRIDGE type)&(object))
struct dispatch_queue_attr_s _dispatch_queue_attr_concurrent = {
 DISPATCH_GLOBAL_OBJECT_HEADER(queue_attr),
};

DISPATCH_GLOBAL_OBJECT_HEADER

    DISPATCH_GLOBAL_OBJECT_HEADER 是一个宏代码执行,源码如下:

#define DISPATCH_GLOBAL_OBJECT_HEADER(name) \
.do_vtable = DISPATCH_VTABLE(name), \
.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT, \
.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT
#endif

DISPATCH_VTABLE

    通过 DISPATCH_VTABLE 拼接队列类型,赋值 vtable 变量 ,其中 DISPATCH_VTABLE() 是宏定义,最终实现是 OS_dispatch_##name##_class

#define DISPATCH_VTABLE(name) DISPATCH_OBJC_CLASS(name)
#define DISPATCH_OBJC_CLASS(name) (&DISPATCH_CLASS_SYMBOL(name))
#define DISPATCH_CLASS_SYMBOL(name) OS_dispatch_##name##_class

_dispatch_lane_create_with_target 实现分析

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);

      //
      // Step 1: Normalize arguments (qos, overcommit, tq)
      //

      dispatch_qos_t qos = dqai.dqai_qos;
     #if !HAVE_PTHREAD_WORKQUEUE_QOS
      if (qos == DISPATCH_QOS_USER_INTERACTIVE) {
       dqai.dqai_qos = qos = DISPATCH_QOS_USER_INITIATED;
      }
      if (qos == DISPATCH_QOS_MAINTENANCE) {
       dqai.dqai_qos = qos = DISPATCH_QOS_BACKGROUND;
      }
     #endif // !HAVE_PTHREAD_WORKQUEUE_QOS

      _dispatch_queue_attr_overcommit_t overcommit = dqai.dqai_overcommit;
       //代码过长省略部分判断
      if (!tq) {
       uintptr_t flags = (overcommit == _dispatch_queue_attr_overcommit_enabled) ? DISPATCH_QUEUE_OVERCOMMIT : 0;
       //tq初始化
       tq = _dispatch_get_root_queue(
         qos == DISPATCH_QOS_UNSPECIFIED ? DISPATCH_QOS_DEFAULT : qos,
          flags)->_as_dq;
       if (unlikely(!tq)) {
        DISPATCH_CLIENT_CRASH(qos, "Invalid queue attribute");
       }
      }

      //
      // Step 2: Initialize the queue
      //

      if (legacy) {
       // if any of these attributes is specified, use non legacy classes
       if (dqai.dqai_inactive || dqai.dqai_autorelease_frequency) {
        legacy = false;
       }
      }

      const void *vtable;
      dispatch_queue_flags_t dqf = legacy ? DQF_MUTABLE : 0;
      if (dqai.dqai_concurrent) {
         OS_dispatch_name
       vtable = DISPATCH_VTABLE(queue_concurrent);
      } else {
       vtable = DISPATCH_VTABLE(queue_serial);
      }
      switch (dqai.dqai_autorelease_frequency) {
      case DISPATCH_AUTORELEASE_FREQUENCY_NEVER:
       dqf |= DQF_AUTORELEASE_NEVER;
       break;
      case DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM:
       dqf |= DQF_AUTORELEASE_ALWAYS;
       break;
      }
      if (label) {
       const char *tmp = _dispatch_strdup_if_mutable(label);
       if (tmp != label) {
        dqf |= DQF_LABEL_NEEDS_FREE;
        label = tmp;
       }
      }

      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);
      if (overcommit == _dispatch_queue_attr_overcommit_enabled) {
       dq->dq_priority |= DISPATCH_PRIORITY_FLAG_OVERCOMMIT;
      }
      if (!dqai.dqai_inactive) {
       _dispatch_queue_priority_inherit_from_target(dq, tq);
       _dispatch_lane_inherit_wlh_from_target(dq, tq);
      }
      _dispatch_retain(tq);
      dq->do_targetq = tq;
      _dispatch_object_debug(dq, "%s", __func__);
      return _dispatch_trace_queue_create(dq)._dq;
  }

查看_dispatch_lane_create_with_target函数实现,执行流程如下:

  1. _dispatch_queue_attr_to_info函数 创建 dispatch_queue_attr_info_t 类型的 dqai,其作用就是保存 Dispatch Queue 的属性信息:dqai_concurrent 等等,源码如下:

      ```cpp
    
      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;
    
      dispatch_queue_attr_info_t 
      _dispatch_queue_attr_to_info(dispatch_queue_attr_t dqa)
      {
          dispatch_queue_attr_info_t dqai = { };
    
          if (!dqa) return dqai;
    
               #if DISPATCH_VARIANT_STATIC
                if (dqa == &_dispatch_queue_attr_concurrent) {
                 dqai.dqai_concurrent = true;
                 return dqai;
          }
         #endif
    
          if (dqa < _dispatch_queue_attrs ||
            dqa >= &_dispatch_queue_attrs[DISPATCH_QUEUE_ATTR_COUNT]) {
                #ifndef __APPLE__
                 if (memcmp(dqa, &_dispatch_queue_attrs[0],
                   sizeof(struct dispatch_queue_attr_s)) == 0) {
                  dqa = (dispatch_queue_attr_t)&_dispatch_queue_attrs[0];
                 } else
                 #endif // __APPLE__
                 DISPATCH_CLIENT_CRASH(dqa->do_vtable, "Invalid queue attribute");
          }
    
          size_t idx = (size_t)(dqa - _dispatch_queue_attrs);
          //...代码过长省略
          return dqai;
      }
    
      ```
    
  2. 规范化参数,例如 qos, overcommit, tq

        由于在 dispatch_queue_create 函数中调用 _dispatch_lane_create_with_target时,tq 参数 为DISPATCH_TARGET_QUEUE_DEFAULT,在源码中找到代码 #define DISPATCH_TARGET_QUEUE_DEFAULT NULL,故 tq 不存在,经过 _dispatch_get_root_queue 初始化后获取 _dispatch_root_queues 中的队列。

    static inline dispatch_queue_global_t
    _dispatch_get_root_queue(dispatch_qos_t qos, uintptr_t flags)
    {
      if (unlikely(qos < DISPATCH_QOS_MIN || qos > DISPATCH_QOS_MAX)) {
      DISPATCH_CLIENT_CRASH(qos, "Corrupted priority");
      }
      unsigned int add_on = 0;
      if (flags & DISPATCH_QUEUE_OVERCOMMIT) {
      add_on = DISPATCH_ROOT_QUEUE_IDX_OFFSET_OVERCOMMIT;
      } else if (flags & DISPATCH_QUEUE_COOPERATIVE) {
      add_on = DISPATCH_ROOT_QUEUE_IDX_OFFSET_COOPERATIVE;
      }
      return &_dispatch_root_queues[3 * (qos - 1) + add_on];
    }
    
  3. 根据 dqai_concurrent,通过 DISPATCH_VTABLE 生成 vtable,串行队列:OS_dispatch_queue_serial,并发队列: OS_dispatch_queue_concurrent;

  4. 通过 _dispatch_object_alloc 创建 dq_os_object_alloc_realized 根据 vtable 的值 与 size 创建 _os_obj,设置了 isa 指向, 可知 dq对象

        void *
        _dispatch_object_alloc(const void *vtable, size_t size)
        {
           #if OS_OBJECT_HAVE_OBJC1
            const struct dispatch_object_vtable_s *_vtable = vtable;
            dispatch_object_t dou;
            dou._os_obj = _os_object_alloc_realized(_vtable->_os_obj_objc_isa, size);
            dou._do->do_vtable = vtable;
            return dou._do;
           #else
            return _os_object_alloc_realized(vtable, size);
           #endif
        }
       inline _os_object_t
       _os_object_alloc_realized(const void *cls, size_t size)
       {
        _os_object_t obj;
        dispatch_assert(size >= sizeof(struct _os_object_s));
        while (unlikely(!(obj = calloc(1u, size)))) {
         _dispatch_temporary_resource_shortage();
        }
        obj->os_obj_isa = cls;
        return obj;
       }
    
  5. 通过 _dispatch_queue_init 初始化 dq ,根据 Dispatch Queue 类型是否并发,生成的width不同,也就是可执行任务数量不同,串行等于 1 ,并发等于 DISPATCH_QUEUE_WIDTH_MAX 也就是 (DISPATCH_QUEUE_WIDTH_FULL - 2)DISPATCH_QUEUE_WIDTH_FULL 值等于 0x1000ull, 最终DISPATCH_QUEUE_WIDTH_MAX 等于 。

      ```cpp
      static inline dispatch_queue_class_t
      _dispatch_queue_init(dispatch_queue_class_t dqu, dispatch_queue_flags_t dqf,
        uint16_t width, uint64_t initial_state_bits)
      {
          uint64_t dq_state = DISPATCH_QUEUE_STATE_INIT_VALUE(width);
          dispatch_queue_t dq = dqu._dq;
    
          dispatch_assert((initial_state_bits & ~(DISPATCH_QUEUE_ROLE_MASK |
            DISPATCH_QUEUE_INACTIVE)) == 0);
    
          if (initial_state_bits & DISPATCH_QUEUE_INACTIVE) {
           dq->do_ref_cnt += 2; // rdar://8181908 see _dispatch_lane_resume
           if (dx_metatype(dq) == _DISPATCH_SOURCE_TYPE) {
            dq->do_ref_cnt++; // released when DSF_DELETED is set
           }
          }
    
          dq_state |= initial_state_bits;
          dq->do_next = DISPATCH_OBJECT_LISTLESS;
          dqf |= DQF_WIDTH(width);
          os_atomic_store2o(dq, dq_atomic_flags, dqf, relaxed);
          dq->dq_state = dq_state;
          dq->dq_serialnum =
            os_atomic_inc_orig(&_dispatch_queue_serial_numbers, relaxed);
          return dqu;
      }
       
      ```
    
  6. 通过 _dispatch_trace_queue_create 对创建的队列进行处理,其中 _dispatch_trace_queue_create_dispatch_introspection_queue_create 封装的宏定义,最后会返回处理过的 _dq

  #define _dispatch_trace_queue_create _dispatch_introspection_queue_create

_dispatch_introspection_queue_create 实现

_dispatch_introspection_queue_create(dispatch_queue_t dq)
{
 dispatch_queue_introspection_context_t dqic;
 size_t sz = sizeof(struct dispatch_queue_introspection_context_s);

 if (!_dispatch_introspection.debug_queue_inversions) {
  sz = offsetof(struct dispatch_queue_introspection_context_s,
    __dqic_no_queue_inversion);
 }
 dqic = _dispatch_calloc(1, sz);
 dqic->dqic_queue._dq = dq;
 if (_dispatch_introspection.debug_queue_inversions) {
  LIST_INIT(&dqic->dqic_order_top_head);
  LIST_INIT(&dqic->dqic_order_bottom_head);
 }
 dq->do_introspection_ctxt = dqic;

 _dispatch_unfair_lock_lock(&_dispatch_introspection.queues_lock);
 LIST_INSERT_HEAD(&_dispatch_introspection.queues, dqic, dqic_list);
 _dispatch_unfair_lock_unlock(&_dispatch_introspection.queues_lock);

 DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK_CALLOUT(queue_create, dq);
 if (DISPATCH_INTROSPECTION_HOOK_ENABLED(queue_create)) {
  _dispatch_introspection_queue_create_hook(dq);
 }
 return upcast(dq)._dqu;
}

_dispatch_introspection_queue_create 函数执行流程如下:

  1. 创建 dispatch_queue_introspection_context_t 类型的 dqic 并与 dq 进行关联

  2. 调用 _dispatch_introspection_queue_create_hook 函数

    static void
      _dispatch_introspection_queue_create_hook(dispatch_queue_t dq)
      {
        dispatch_introspection_queue_s diq;
        diq = dispatch_introspection_queue_get_info(dq);
        dispatch_introspection_hook_callout_queue_create(&diq);
      }
    
  3. 调用 dispatch_introspection_queue_get_info

    dispatch_introspection_queue_s
    dispatch_introspection_queue_get_info(dispatch_queue_t dq)
    {
     if (dx_metatype(dq) == _DISPATCH_WORKLOOP_TYPE) {
      return _dispatch_introspection_workloop_get_info(upcast(dq)._dwl);
     }
     return _dispatch_introspection_lane_get_info(upcast(dq)._dl);
    }
    
  4. 调用 _dispatch_introspection_lane_get_info

      static inline dispatch_introspection_queue_s
      _dispatch_introspection_lane_get_info(dispatch_lane_class_t dqu)
      {
       dispatch_lane_t dq = dqu._dl;
       bool global = _dispatch_object_is_global(dq);
       uint64_t dq_state = os_atomic_load2o(dq, dq_state, relaxed);
    
       dispatch_introspection_queue_s diq = {
        .queue = dq->_as_dq,
        .target_queue = dq->do_targetq,
        .label = dq->dq_label,
        .serialnum = dq->dq_serialnum,
        .width = dq->dq_width,
        .suspend_count = _dq_state_suspend_cnt(dq_state) + dq->dq_side_suspend_cnt,
        .enqueued = _dq_state_is_enqueued(dq_state) && !global,
        .barrier = _dq_state_is_in_barrier(dq_state) && !global,
        .draining = (dq->dq_items_head == (void*)~0ul) ||
          (!dq->dq_items_head && dq->dq_items_tail),
        .global = global,
        .main = dx_type(dq) == DISPATCH_QUEUE_MAIN_TYPE,
       };
       return diq;
      }
    
    

总结

通过上面的函数调用流程,可知 Dispatch Queue 最终是通过结构体模板创建的。

你可能感兴趣的:(GCD ① Dispatch Queue)