数据结构中使用的宏
一些宏, 逻辑上没啥可说的, 就是单纯代码拼接.
但要注意的, _OS_OBJECT_HEADER, OS_OBJECT_STRUCT_HEADER, _DISPATCH_OBJECT_HEADER
整体链条如下:
DISPATCH_OBJECT_HEADER -> _DISPATCH_OBJECT_HEADER -> OS_OBJECT_STRUCT_HEADER -> _OS_OBJECT_HEADER
这三个宏中的字段, 在大部分的基础结构体中都有, 可以理解为 GCD 的基础结构有这样下面的特性
- 准备作为链表节点使用, 都拥有
do_next指向下一个节点的指针 - 都需要包含当前执行的队列
do_targetq - 包含
do_ctxt作为上下文,do_finalizer作为析构函数 - 都拥有一个 isa 指针, 这个 isa 类型是
结构体名字_vtable_s, 字段名为do_vtable - 都拥有一个内部引用计数和一个外部引用计数
_as_os_obj暂时不知道干嘛的_DISPATCH_OBJECT_HEADER#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; \ void *do_finalizer
OS_OBJECT_STRUCT_HEADER
#define OS_OBJECT_STRUCT_HEADER(x) \
_OS_OBJECT_HEADER(\
const struct x##_vtable_s *do_vtable, \
do_ref_cnt, \
do_xref_cnt)
#endif
_OS_OBJECT_HEADER
#define _OS_OBJECT_HEADER(isa, ref_cnt, xref_cnt) \
isa; /* must be pointer-sized */ \
int volatile ref_cnt; \
int volatile xref_cnt
DISPATCH_GLOBAL_OBJECT_HEADER 在 global, main queue 初始化时常见
其实是对上面提到的字段的初始化
其中do_vtable, 层层宏解开后是 OS_dispatch_##name##_class
两个引用计数, 最终使用的是INT_MAX
#define _OS_OBJECT_GLOBAL_REFCNT INT_MAX
#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
#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_ROOT_QUEUE_IDX
主要是将传入的名字 n, 通过 flags 决定拼接成 QOS_OverCommit 还是 qos
这个生成的内容将会是初始化生成的全局队列的数组序号, 这个序号同时也会被宏转为优先级的 enum
#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)
_DISPATCH_ROOT_QUEUE_ENTRY
生成一个dispatch_queue_global_s, 并且将其按计算出来的序号装入数组中
#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__ \
}