GCD底层分析(一)

·  阅读 9911

lldb bt 堆栈信息 image.png GCD源码存在于dyld

GCD底层关键数据结构

几种类型的队列

首先测试打印几种常用的queue

- (void)queueTestPrint {
    dispatch_queue_t serial = dispatch_queue_create("ifl_queue_serial",
        DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t conque = dispatch_queue_create("ifl_queue_concurrent", 
        DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_queue_t globQueue = dispatch_get_global_queue(0, 0);
    NSLog(@"\n%@\n%@\n%@\n%@",serial,conque,mainQueue,globQueue);
}

测试结果

<OS_dispatch_queue_serial: ifl_queue_serial>
<OS_dispatch_queue_concurrent: ifl_queue_concurrent>
<OS_dispatch_queue_main: com.apple.main-thread>
<OS_dispatch_queue_global: com.apple.root.default-qos>

乍一看,貌似可以分为4种, 且看 - 暂且不表

串行队列  - ifl_queue_serial
并行队列  - ifl_queue_concurrent
主队列   -  com.apple.main-thread
全局队列  - com.apple.root.default-qos

主队列 - com.apple.main-thread

  • 主队列溯源 - dispatch_get_main_queue()

    1. dispatch_queue_main_t dispatch_get_main_queue(void) 
       {
           return DISPATCH_GLOBAL_OBJECT(dispatch_queue_main_t, _dispatch_main_q);
       }
      
    2. DISPATCH_GLOBAL_OBJECT(dispatch_queue_main_t, _dispatch_main_q)
      #define DISPATCH_GLOBAL_OBJECT(type, object) ((type)&(object))
      
    3. 解析宏 DISPATCH_GLOBAL_OBJECT,重点放在_dispatch_main_q上
      
    4. 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,
       };
      
    5. #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
      
    6. #define DISPATCH_VTABLE(name) DISPATCH_OBJC_CLASS(name)
      
    7. #define DISPATCH_OBJC_CLASS(name) (&DISPATCH_CLASS_SYMBOL(name))
      
    8. #define DISPATCH_CLASS_SYMBOL(name) _dispatch_##name##_vtable
       解析宏 DISPATCH_CLASS_SYMBOL 
       为 前缀部分(_dispatch_) + name部分(queue_main) + 后缀部分(vtable)
       
      

      根据层层宏嵌套,解析出 _dispatch_main_q 结构

    9. struct dispatch_queue_static_s _dispatch_main_q = {
           .do_vtable = _dispatch_queue_main_vtable, 
           .do_ref_cnt = INT_MAX, 
           .do_xref_cnt = INT_MAX
           #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_queue_static_s

    10. typedef struct dispatch_queue_static_s *dispatch_queue_main_t
      
      10_1
      struct dispatch_queue_static_s {
          struct dispatch_lane_s _as_dl[0]; 
          DISPATCH_LANE_CLASS_HEADER(lane);
      } DISPATCH_CACHELINE_ALIGN;
      
      10_2
      #define DISPATCH_LANE_CLASS_HEADER(x) \
          struct dispatch_queue_s _as_dq[0]; \
          DISPATCH_QUEUE_CLASS_HEADER(x, \
          struct dispatch_object_s *volatile dq_items_tail); \
          dispatch_unfair_lock_s dq_sidelock; \
          struct dispatch_object_s *volatile dq_items_head; \
          uint32_t dq_side_suspend_cnt
        
      10_3
      struct dispatch_queue_s {
          DISPATCH_QUEUE_CLASS_HEADER(queue, void *__dq_opaque1);
          /* 32bit hole on LP64 */
      } DISPATCH_ATOMIC64_ALIGN;
      
      10_4
      #define DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__) \
          _DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__); \
          /* LP64 global queue cacheline boundary */ \
          unsigned long dq_serialnum; \
          const char *dq_label; \
          DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \
              const uint16_t dq_width, \
              const uint16_t __dq_opaque2 \
          ); \
          dispatch_priority_t dq_priority; \
          union { \
              struct dispatch_queue_specific_head_s *dq_specific_head; \
              struct dispatch_source_refs_s *ds_refs; \
              struct dispatch_timer_source_refs_s *ds_timer_refs; \
              struct dispatch_mach_recv_refs_s *dm_recv_refs; \
              struct dispatch_channel_callbacks_s const *dch_callbacks; \
          }; \
          int volatile dq_sref_cnt
        
      10_5
      #define _DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__) \
          DISPATCH_OBJECT_HEADER(x); \
          __pointer_sized_field__; \
          DISPATCH_UNION_LE(uint64_t volatile dq_state, \
          dispatch_lock dq_state_lock, \
          uint32_t dq_state_bits \
          )
       
      10_6
      #define DISPATCH_OBJECT_HEADER(x) \
          struct dispatch_object_s _as_do[0]; \
          _DISPATCH_OBJECT_HEADER(x)
       
      10_7
      #define _DISPATCH_OBJECT_HEADER(x) \
          struct _os_object_s _as_os_obj[0]; \
          OS_OBJECT_STRUCT_HEADER(dispatch_##x); \
          struct dispatch_##x##_s *volatile do_next; \
          struct dispatch_queue_s *do_targetq; \
          void *do_ctxt; \
          union { \
              dispatch_function_t DISPATCH_FUNCTION_POINTER do_finalizer; \
              void *do_introspection_ctxt; \
          }
          
      typedef void (*dispatch_function_t)(void * _Nullable);
      
      #if __has_feature(ptrauth_calls) //判断编译器是否支持指针身份验证功能
      [使用Apple A12或更高版本A系列处理器的设备(如iPhone XS、iPhone XS Max和
      iPhone XR或更新的设备)支持arm64e架构]
          #define DISPATCH_FUNCTION_POINTER \
          __ptrauth(ptrauth_key_process_dependent_code, true, \
          ptrauth_string_discriminator("dispatch.handler"))
      #else
          #define DISPATCH_FUNCTION_POINTER (空的宏定义 - 也就是占位为空)
      
       
      10_8
      #define OS_OBJECT_STRUCT_HEADER(x) \
          _OS_OBJECT_HEADER(\
          const struct x##_vtable_s *__ptrauth_objc_isa_pointer do_vtable, \
          do_ref_cnt, \
          do_xref_cnt)
          
      
      10_9
      #define _OS_OBJECT_HEADER(isa, ref_cnt, xref_cnt) \
          isa; /* must be pointer-sized and use __ptrauth_objc_isa_pointer */ \
          int volatile ref_cnt; \
          int volatile xref_cnt
          
      
    11. from 10 描述的源码宏逻辑层层拆解
      
      根据10_8 and 10_9 拆解得到
      
      11_1
      #define OS_OBJECT_STRUCT_HEADER(x) \
          const struct x##_vtable_s *__ptrauth_objc_isa_pointer do_vtable; \
          int volatile do_ref_cnt; \
          int volatile do_xref_cnt)
          
      从10_8 向上追踪 宏参数 x,发现 
      
          10_1-> dispatch_queue_static_s
          DISPATCH_LANE_CLASS_HEADER(dispatch_lane)  x ------- lane
          
          10_3-> DISPATCH_QUEUE_CLASS_HEADER(dispatch_queue, void *__dq_opaque1)
              x ------- queue
      
      11_2 - 分析 
          继续11_1 得到
      
      11_3
      #define OS_OBJECT_STRUCT_HEADER(dispatch_lane) \
          const struct dispatch_lane_vtable_s \
              *__ptrauth_objc_isa_pointer do_vtable; \
          int volatile do_ref_cnt; \
          int volatile do_xref_cnt)
          
      #define OS_OBJECT_STRUCT_HEADER(dispatch_queue) \
          const struct dispatch_queue_vtable_s \
              *__ptrauth_objc_isa_pointer do_vtable; \
          int volatile do_ref_cnt; \
          int volatile do_xref_cnt)
          
      11_4
          拆解10_7
              //#define _DISPATCH_OBJECT_HEADER(x) \  x: lane / queue
      #define _DISPATCH_OBJECT_HEADER(lane) \  
          struct _os_object_s _as_os_obj[0]; \
          const struct dispatch_lane_vtable_s \
              *__ptrauth_objc_isa_pointer do_vtable; \
          int volatile do_ref_cnt; \
          int volatile do_xref_cnt) \
          struct dispatch_lane_s *volatile do_next; \
          struct dispatch_queue_s *do_targetq; \
          void *do_ctxt; \
          union { \
              void *do_finalizer; \
              void *do_introspection_ctxt; \
          }
          
      11_5
          拆解10_6
       #define DISPATCH_OBJECT_HEADER(x) \   x: lane / queue
          struct dispatch_object_s _as_do[0]; \
          struct _os_object_s _as_os_obj[0]; \
          const struct dispatch_lane_vtable_s \
              *__ptrauth_objc_isa_pointer do_vtable; \
          int volatile do_ref_cnt; \
          int volatile do_xref_cnt) \
          struct dispatch_lane_s *volatile do_next; \
          struct dispatch_queue_s *do_targetq; \
          void *do_ctxt; \
          union { \
              void *do_finalizer; \
              void *do_introspection_ctxt; \
          }
          
      11_6
          拆解10_5    x: lane / queue
      #define _DISPATCH_QUEUE_CLASS_HEADER(x,__pointer_sized_field__)\
          struct dispatch_object_s _as_do[0]; \
          struct _os_object_s _as_os_obj[0]; \
          const struct dispatch_lane_vtable_s \
              *__ptrauth_objc_isa_pointer do_vtable; \
          int volatile do_ref_cnt; \
          int volatile do_xref_cnt) \
          struct dispatch_lane_s *volatile do_next; \
          struct dispatch_queue_s *do_targetq; \
          void *do_ctxt; \
          union { \
              void *do_finalizer; \
              void *do_introspection_ctxt; \
          } \
          __pointer_sized_field__; \ 
          DISPATCH_UNION_LE(uint64_t volatile dq_state, \ 
          dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \ )
          
      11_7
          拆解10_4    x: lane / queue
      #define DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__) \
          struct dispatch_object_s _as_do[0]; \
          struct _os_object_s _as_os_obj[0]; \
          const struct dispatch_lane_vtable_s \
              *__ptrauth_objc_isa_pointer do_vtable; \
          int volatile do_ref_cnt; \
          int volatile do_xref_cnt) \
          struct dispatch_lane_s *volatile do_next; \
          struct dispatch_queue_s *do_targetq; \
          void *do_ctxt; \
          union { \
              void *do_finalizer; \
              void *do_introspection_ctxt; \
          } \
          __pointer_sized_field__; \ 
          DISPATCH_UNION_LE(uint64_t volatile dq_state, \ 
          dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \
          )
          /* LP64 global queue cacheline boundary */ \
          unsigned long dq_serialnum; \
          const char *dq_label; \
          DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \
              const uint16_t dq_width, \
              const uint16_t __dq_opaque2 \
          ); \
          dispatch_priority_t dq_priority; \
          union { \
              struct dispatch_queue_specific_head_s *dq_specific_head; \
              struct dispatch_source_refs_s *ds_refs; \
              struct dispatch_timer_source_refs_s *ds_timer_refs; \
              struct dispatch_mach_recv_refs_s *dm_recv_refs; \
              struct dispatch_channel_callbacks_s const *dch_callbacks; \
          }; \
          int volatile dq_sref_cnt
      
      11_8
         拆解10_3
        
       struct dispatch_queue_s { 
          struct dispatch_object_s _as_do[0]; \
          struct _os_object_s _as_os_obj[0]; \
          const struct dispatch_queue_vtable_s \
              *__ptrauth_objc_isa_pointer do_vtable; \
          int volatile do_ref_cnt; \
          int volatile do_xref_cnt) \
          struct dispatch_queue_s *volatile do_next; \
          struct dispatch_queue_s *do_targetq; \
          void *do_ctxt; \
          union { \
              void *do_finalizer; \
              void *do_introspection_ctxt; \
          } \
          void *__dq_opaque1; \ 
          DISPATCH_UNION_LE(uint64_t volatile dq_state, \ 
          dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \
          )
          /* LP64 global queue cacheline boundary */ \
          unsigned long dq_serialnum; \
          const char *dq_label; \
          DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \
              const uint16_t dq_width, \
              const uint16_t __dq_opaque2 \
          ); \
          dispatch_priority_t dq_priority; \
          union { \
              struct dispatch_queue_specific_head_s *dq_specific_head; \
              struct dispatch_source_refs_s *ds_refs; \
              struct dispatch_timer_source_refs_s *ds_timer_refs; \
              struct dispatch_mach_recv_refs_s *dm_recv_refs; \
              struct dispatch_channel_callbacks_s const *dch_callbacks; \
          }; \
          int volatile dq_sref_cnt;
       } DISPATCH_ATOMIC64_ALIGN;   
          
      11_9
          拆解 10_2  10_1
      struct dispatch_queue_static_s { 
          struct dispatch_lane_s _as_dl[0]; \
          struct dispatch_queue_s _as_dq[0]; \ 
          struct dispatch_object_s _as_do[0]; \
          struct _os_object_s _as_os_obj[0]; \
          const struct dispatch_lane_vtable_s \
              *__ptrauth_objc_isa_pointer do_vtable; \
          int volatile do_ref_cnt; \
          int volatile do_xref_cnt) \
          struct dispatch_lane_s *volatile do_next; \
          struct dispatch_queue_s *do_targetq; \
          void *do_ctxt; \
          union { \
              void *do_finalizer; \
              void *do_introspection_ctxt; \
          } \
          struct dispatch_object_s *volatile dq_items_tail; \ 
          DISPATCH_UNION_LE(uint64_t volatile dq_state, \ 
          dispatch_lock dq_state_lock, \ uint32_t dq_state_bits \
          )
          /* LP64 global queue cacheline boundary */ \
          unsigned long dq_serialnum; \
          const char *dq_label; \
          DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \
              const uint16_t dq_width, \
              const uint16_t __dq_opaque2 \
          ); \
          dispatch_priority_t dq_priority; \
          union { \
              struct dispatch_queue_specific_head_s *dq_specific_head; \
              struct dispatch_source_refs_s *ds_refs; \
              struct dispatch_timer_source_refs_s *ds_timer_refs; \
              struct dispatch_mach_recv_refs_s *dm_recv_refs; \
              struct dispatch_channel_callbacks_s const *dch_callbacks; \
          }; \
          int volatile dq_sref_cnt;
          dispatch_unfair_lock_s dq_sidelock; \ 
          struct dispatch_object_s *volatile dq_items_head; \ 
          uint32_t dq_side_suspend_cnt; 
      } DISPATCH_CACHELINE_ALIGN;
      

    最终通过解析宏 得到 dispatch_queue_static_s 完整类型结构

  • DQF_WIDTH

    #define DQF_WIDTH(n)          ((dispatch_queue_flags_t)(uint16_t)(n))

    DQF_WIDTH(1) - 0x00000001(32位 16进制形式)

  • DQF_THREAD_BOUND

    对于 _dispatch_main_q 结构中出现的 DQF_THREAD_BOUND甚是耿耿于怀

    源码中查找,出现在 DISPATCH_OPTIONS(dispatch_queue_flags, uint32_t, ....) 结构里

      #define DISPATCH_OPTIONS(name, type, ...) \
      typedef enum : type { __VA_ARGS__ } __DISPATCH_OPTIONS_ATTR \
          __DISPATCH_ENUM_ATTR name##_t
    

    VA_ARGS 表示可变参数的宏,用来替换 ...代表的可变参数

    解析 DISPATCH_OPTIONS(name, type, ...) 得到

      typedef uint32_t dispatch_queue_flags_t
      enum : dispatch_queue_flags_t {
          DQF_NONE                = 0x00000000,
          DQF_AUTORELEASE_ALWAYS  = 0x00010000,
          DQF_AUTORELEASE_NEVER   = 0x00020000,
          DQF_THREAD_BOUND        = 0x00040000, // queue is bound to a thread
          DQF_BARRIER_BIT         = 0x00080000, // queue is a barrier on its target
          DQF_TARGETED            = 0x00100000, // queue is targeted by another object
          DQF_LABEL_NEEDS_FREE    = 0x00200000, // queue label was strdup()ed
          DQF_MUTABLE             = 0x00400000,
          DQF_RELEASED            = 0x00800000, // xref_cnt == -1
          DSF_STRICT              = 0x04000000,
          DSF_WLH_CHANGED         = 0x08000000,
          DSF_CANCELED            = 0x10000000,
          DSF_CANCEL_WAITER       = 0x20000000,
          DSF_NEEDS_EVENT         = 0x40000000,
          DSF_DELETED             = 0x80000000,
      }
    

    DQF_THREAD_BOUND - 标识为 0x00040000,表示队列绑定到一个线程

      DQF_THREAD_BOUND | DQF_WIDTH(1) 就是
      0x00040000 | 0x00000001 = 0x00040001
      
    

    _dispatch_main_q.dq_atomic_flags = 0x00040001, 高16位标识flag, 低16位标识 DQF_WIDTH, 至于 DQF_WIDTH什么含义,且往继续看分析过程,暂不表

  • dispatch_queue_flags_t

    dispatch_queue_flags_t 通过拆解宏得到,分析源码过程中,经常会碰到令人厌烦的宏, 不做到耐心有细,分析思路就此中断,文章到此也就结束了

    如果搞不清楚一个研究对象的基本数据类型,后面 堆积起来的所有理解就不踏实,分析思路是离散化的,面对抽象的底层代码,终不得其正解

    • DQF_NONE = 0x00000000

    • DQF_AUTORELEASE_ALWAYS = 0x00010000

    • DQF_AUTORELEASE_NEVER = 0x00020000

        32位16进制结构, 16~17 两位表示  (第一位从0开始)
        autorelease标识(0-none, 1-always autorelease, 2-never autorelease) 
        dispatch_queue_flags_t & _DQF_AUTORELEASE_MASK(0x00030000) 得到标识
        
      
    • DQF_THREAD_BOUND = 0x00040000 队列绑定到一个线程

    • DQF_BARRIER_BIT       第19位, // queue is a barrier on its target

    • DQF_TARGETED          第20位, // queue is targeted by another object

    • DQF_LABEL_NEEDS_FREE  第21位, // queue label was strdup()ed

        DQF_BARRIER_BIT DQF_TARGETED DQF_LABEL_NEEDS_FREE 具体含义暂不表
        
      
    • DSF_STRICT // 第26位

        一旦设定,严格遵守语义,handlers(处理程序)不能随便更改已激活的状态机状态
      
    • DSF_WLH_CHANGED // 第27位

        只能作为调试分析标识用
      
    • DSF_CANCELED // 第28位

        要求取消,发出请求
      
    • DSF_CANCEL_WAITER // 第29位

        至少有一个 dispatch_source_cancel_and_wait() 等待取消完成,此之前一定
        已经设置了标识 DSF_CANCELED
      
    • DSF_NEEDS_EVENT // 第30位

        状态机需要特定的事件才能唤醒,此标识可以防止一些乱七八糟的虚假wakeups
        可能解除状态机阻塞的事件传递 DISPATCH_WAKEUP_EVENT, 消除
        DSF_NEEDS_EVENT 影响
      
    • DSF_DELETED // 第31位

        标识不再允许注册新的unote,之前已经注册的unotes失活,但是之前已经注册过的
        unotes可能还处在正交付最后一个事件的过程中, 直到结束
        
      

全局队列 - com.apple.root.default-qos

  • 全局队列溯源 - dispatch_get_global_queue(intptr_t identifier, uintptr_t flags)
  1. 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);
     }
     
    
  2. 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];
     }
    
  3. 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,
         ),
    };
    
  4. _dispatch_root_queues结构中又出现了宏
     _DISPATCH_ROOT_QUEUE_IDX 
     _DISPATCH_ROOT_QUEUE_ENTRY
     DISPATCH_GLOBAL_OBJECT_HEADER ....
     
    
  5. #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
           
    #define DISPATCH_VTABLE(name) DISPATCH_OBJC_CLASS(name)
    
    #define DISPATCH_OBJC_CLASS(name) (&DISPATCH_CLASS_SYMBOL(name))
    
    #define DISPATCH_CLASS_SYMBOL(name) _dispatch_##name##_vtable
         解析宏 DISPATCH_CLASS_SYMBOL 
         为 前缀部分(_dispatch_) + name部分(queue_global) + 后缀部分(vtable)
         
    解析其中一个 _DISPATCH_ROOT_QUEUE_ENTRY 结构
        _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, 
             DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
             .dq_label = "com.apple.root.maintenance-qos.overcommit",
             .dq_serialnum = 5,
         ),
         
            
    #define _DISPATCH_ROOT_QUEUE_IDX(MAINTENANCE, 
        DISPATCH_PRIORITY_FLAG_OVERCOMMIT) \
         ((DISPATCH_PRIORITY_FLAG_OVERCOMMIT & 
             DISPATCH_PRIORITY_FLAG_OVERCOMMIT) ? \
         DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT : \
         DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS)
         
    #define _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, 
        DISPATCH_PRIORITY_FLAG_OVERCOMMIT, ...) \
         [_DISPATCH_ROOT_QUEUE_IDX(MAINTENANCE, 
             DISPATCH_PRIORITY_FLAG_OVERCOMMIT)] = { \
             .do_vtable = _dispatch_queue_global_vtable, 
             .do_ref_cnt = INT_MAX, 
             .do_xref_cnt = INT_MAX
             .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \
             .do_ctxt = 
                 _dispatch_root_queue_ctxt(_DISPATCH_ROOT_QUEUE_IDX(
                     MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT)), \
             .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \
             .dq_priority = DISPATCH_PRIORITY_FLAG_OVERCOMMIT | ((
                     DISPATCH_PRIORITY_FLAG_OVERCOMMIT 
                     & DISPATCH_PRIORITY_FLAG_FALLBACK) ? \
             _dispatch_priority_make_fallback(DISPATCH_QOS_MAINTENANCE) : \
             _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 0)), \
             .dq_label = "com.apple.root.maintenance-qos.overcommit", \
             .dq_serialnum = 5, \
         }
         
      解析 _DISPATCH_ROOT_QUEUE_IDX(MAINTENANCE, 
          DISPATCH_PRIORITY_FLAG_OVERCOMMIT) 得到一个entry结构
      
    [DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT] = { \
             .do_vtable = _dispatch_queue_global_vtable, 
             .do_ref_cnt = INT_MAX, 
             .do_xref_cnt = INT_MAX
             .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \
             .do_ctxt = 
                 _dispatch_root_queue_ctxt(
                     DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT), \
             .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \
             .dq_priority = DISPATCH_PRIORITY_FLAG_OVERCOMMIT 
                | (_dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 0), \
             .dq_label = "com.apple.root.maintenance-qos.overcommit", \
             .dq_serialnum = 5, \
         }  
      
    #define _dispatch_priority_make(qos, relpri) \
     (qos ? ((((qos) << DISPATCH_PRIORITY_QOS_SHIFT) & 
         DISPATCH_PRIORITY_QOS_MASK) | \
     ((dispatch_priority_t)(relpri - 1) 
         & DISPATCH_PRIORITY_RELPRI_MASK)) : 0)
         
    #define _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 
        0) \
     (DISPATCH_QOS_MAINTENANCE ? 
         ((((DISPATCH_QOS_MAINTENANCE) << DISPATCH_PRIORITY_QOS_SHIFT) & 
         DISPATCH_PRIORITY_QOS_MASK) | \
     ((dispatch_priority_t)(0 - 1) 
         & DISPATCH_PRIORITY_RELPRI_MASK)) : 0)
        
    #define _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 
        0) \
     (DISPATCH_QOS_MAINTENANCE ? 
         (((1 << 8) & 0x00000f00) | \
     ((dispatch_priority_t)(0 - 1) 
         & DISPATCH_PRIORITY_RELPRI_MASK)) : 0)
         
    #define _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 
        0) \
     (DISPATCH_QOS_MAINTENANCE ? 
         (0x00000100 | \
     ((dispatch_priority_t)(0 - 1) 
         & 0x000000ff)) : 0)
         
    #define _dispatch_priority_make(DISPATCH_QOS_MAINTENANCE, 0) \
     (DISPATCH_QOS_MAINTENANCE ? 
         0x000001ff : 0)
         
    _dispatch_priority_make  解出结果 ---  0x000001ff
    
    [DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT] = { \
             .do_vtable = _dispatch_queue_global_vtable, 
             .do_ref_cnt = INT_MAX, 
             .do_xref_cnt = INT_MAX
             .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \
             .do_ctxt = 
                 _dispatch_root_queue_ctxt(
                     DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT), \
             .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \
             .dq_priority = DISPATCH_PRIORITY_FLAG_OVERCOMMIT | 0x000001ff, \
             .dq_label = "com.apple.root.maintenance-qos.overcommit", \
             .dq_serialnum = 5, \
         } 
         
    [DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT] = { \
             .do_vtable = _dispatch_queue_global_vtable, 
             .do_ref_cnt = INT_MAX, 
             .do_xref_cnt = INT_MAX
             .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \
             .do_ctxt = 
                 _dispatch_root_queue_ctxt(
                     DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT), \
             .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \
             .dq_priority = 0x800001ff, \
             .dq_label = "com.apple.root.maintenance-qos.overcommit", \
             .dq_serialnum = 5, \
         } 
         
    

串行队列

  • 队列溯源 - ifl_queue_serial -
  1. 根据源码中的宏解析   dispatch_lane_t   
     
    typedef struct dispatch_lane_s *dispatch_queue_serial_t;
    typedef struct dispatch_lane_s *dispatch_queue_concurrent_t;
    
    typedef struct dispatch_lane_s {
         struct dispatch_queue_s _as_dq[0]; \
         struct dispatch_object_s _as_do[0]; \ 
         struct _os_object_s _as_os_obj[0]; \ 
         const struct dispatch_lane_vtable_s \ 
             *__ptrauth_objc_isa_pointer do_vtable; \ 
         int volatile do_ref_cnt; \ 
         int volatile do_xref_cnt) \ 
         struct dispatch_lane_s *volatile do_next; \ 
         struct dispatch_queue_s *do_targetq; \ 
         void *do_ctxt; \ 
         union { \ 
             void *do_finalizer; \ 
             void *do_introspection_ctxt; \ 
         } \ 
         struct dispatch_object_s *volatile dq_items_tail; \ 
         DISPATCH_UNION_LE(uint64_t volatile dq_state, \ 
         dispatch_lock dq_state_lock, \ 
         uint32_t dq_state_bits \ 
         ) /* LP64 global queue cacheline boundary */ \ 
         unsigned long dq_serialnum; \ 
         const char *dq_label; \ 
         DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \ 
             const uint16_t dq_width, \ 
             const uint16_t __dq_opaque2 \ 
         ); \ 
         dispatch_priority_t dq_priority; \ 
         union { \ 
             struct dispatch_queue_specific_head_s *dq_specific_head; \ 
             struct dispatch_source_refs_s *ds_refs; \ 
             struct dispatch_timer_source_refs_s *ds_timer_refs; \ 
             struct dispatch_mach_recv_refs_s *dm_recv_refs; \ 
             struct dispatch_channel_callbacks_s const *dch_callbacks; \ 
         }; \ 
         int volatile dq_sref_cnt;
         dispatch_unfair_lock_s dq_sidelock; \
         struct dispatch_object_s *volatile dq_items_head; \
         uint32_t dq_side_suspend_cnt
     } DISPATCH_ATOMIC64_ALIGN *dispatch_lane_t;
     
     
     typedef struct dispatch_queue_s *dispatch_queue_t;
     
     struct dispatch_queue_s { 
         struct dispatch_object_s _as_do[0]; \ 
         struct _os_object_s _as_os_obj[0]; \ 
         const struct dispatch_queue_vtable_s \ 
         *__ptrauth_objc_isa_pointer do_vtable; \ 
         int volatile do_ref_cnt; \ 
         int volatile do_xref_cnt) \ 
         struct dispatch_queue_s *volatile do_next; \ 
         struct dispatch_queue_s *do_targetq; \ 
         void *do_ctxt; \ 
         union { \ 
             void *do_finalizer; \ 
             void *do_introspection_ctxt; \ 
         } \ 
         void *__dq_opaque1; \ 
         DISPATCH_UNION_LE(uint64_t volatile dq_state, \ 
             dispatch_lock dq_state_lock, \ 
             uint32_t dq_state_bits \ 
         ) /* LP64 global queue cacheline boundary */ \ 
         unsigned long dq_serialnum; \ 
         const char *dq_label; \ 
         DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags, \ 
             const uint16_t dq_width, \ 
             const uint16_t __dq_opaque2 \ 
         ); \ 
         dispatch_priority_t dq_priority; \ 
         union { \ 
             struct dispatch_queue_specific_head_s *dq_specific_head; \ 
             struct dispatch_source_refs_s *ds_refs; \ 
             struct dispatch_timer_source_refs_s *ds_timer_refs; \ 
             struct dispatch_mach_recv_refs_s *dm_recv_refs; \ 
             struct dispatch_channel_callbacks_s const *dch_callbacks; \ 
         }; \ 
         int volatile dq_sref_cnt; 
     } DISPATCH_ATOMIC64_ALIGN;
     
     
     typedef union {
         struct _os_object_s *_os_obj;
         struct dispatch_object_s *_do;
         struct dispatch_queue_s *_dq;
         struct dispatch_queue_attr_s *_dqa;
         struct dispatch_group_s *_dg;
         struct dispatch_source_s *_ds;
         struct dispatch_channel_s *_dch;
         struct dispatch_mach_s *_dm;
         struct dispatch_mach_msg_s *_dmsg;
         struct dispatch_semaphore_s *_dsema;
         struct dispatch_data_s *_ddata;
         struct dispatch_io_s *_dchannel;
     } dispatch_object_t DISPATCH_TRANSPARENT_UNION;
     
     
     typedef struct dispatch_continuation_s {
         DISPATCH_CONTINUATION_HEADER(continuation);
     } *dispatch_continuation_t;
     
     typedef struct dispatch_continuation_s {
         union { \
             const void *__ptrauth_objc_isa_pointer do_vtable; \
             uintptr_t dc_flags; \
         }; \
         union { \
             pthread_priority_t dc_priority; \
             int dc_cache_cnt; \
             uintptr_t dc_pad; \
         }; \
         struct voucher_s *dc_voucher; \
         struct dispatch_continuation_s *volatile do_next; \
         dispatch_function_t dc_func; \
         void *dc_ctxt; \
         void *dc_data; \
         void *dc_other
     } *dispatch_continuation_t;
    
  2. dispatch_queue_t 
    dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)
     
     _dispatch_lane_create_with_target(label, attr, 
     DISPATCH_TARGET_QUEUE_DEFAULT, true)
     
     static dispatch_queue_t
     _dispatch_lane_create_with_target(const char *label, 
         dispatch_queue_attr_t dqa, dispatch_queue_t tq, bool legacy)
     {
         /*
             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 dqai = 
                             _dispatch_queue_attr_to_info(dqa);
         \
         //
         // Step 1: Normalize arguments (qos, overcommit, tq)
         //
         \
         // dqai_qos -- typedef uint32_t dispatch_qos_t
         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 (overcommit != _dispatch_queue_attr_overcommit_unspecified && tq) {
             if (tq->do_targetq) {
                 DISPATCH_CLIENT_CRASH(tq, "Cannot specify both overcommit and "
                 "a non-global target queue");
             }
         }
         \
         if (tq && dx_type(tq) == DISPATCH_QUEUE_GLOBAL_ROOT_TYPE) {
             // Handle discrepancies between attr and target queue, attributes win
             if (overcommit == _dispatch_queue_attr_overcommit_unspecified) {
                 if (tq->dq_priority & DISPATCH_PRIORITY_FLAG_OVERCOMMIT) {
                     overcommit = _dispatch_queue_attr_overcommit_enabled;
                 } else {
                     overcommit = _dispatch_queue_attr_overcommit_disabled;
                 }
             }
             if (qos == DISPATCH_QOS_UNSPECIFIED) {
                 qos = _dispatch_priority_qos(tq->dq_priority);
             }
             tq = NULL;
         } else if (tq && !tq->do_targetq) {
             // target is a pthread or runloop root queue, setting QoS or overcommit
             // is disallowed
             if (overcommit != _dispatch_queue_attr_overcommit_unspecified) {
                 DISPATCH_CLIENT_CRASH(tq, "Cannot specify an overcommit attribute "
                 "and use this kind of target queue");
             }
         } else {
             if (overcommit == _dispatch_queue_attr_overcommit_unspecified) {
                 // Serial queues default to overcommit!
                 overcommit = dqai.dqai_concurrent ? 
                     _dispatch_queue_attr_overcommit_disabled : 
                         _dispatch_queue_attr_overcommit_enabled;
             }
         }
         if (!tq) {
             tq = _dispatch_get_root_queue(
                 qos == DISPATCH_QOS_UNSPECIFIED ? DISPATCH_QOS_DEFAULT : qos, 
                 overcommit == _dispatch_queue_attr_overcommit_enabled)->_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) {
             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;
     }
     
    

并发队列

分类:
iOS
标签:
分类:
iOS
标签:
收藏成功!
已添加到「」, 点击更改