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

Dispatch_Queue和线程的关系

Dispatch Queue 的获取

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

dispatch_queue_create

第一种方法是通过 GCD 的 API 生成 Dispatch Queue, dispatch 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) 。该名称在 Xcode 和 Instruments 的调试器中作为 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 Queue 和 Concurrent 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 Queue 和 Global 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_q 为 dispatch_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_init 在 libdispatch_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_SERIAL 和 DISPATCH_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 等于 4096 - 2。

      ```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 最终是通过结构体模板创建的。

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容