寫(xiě)在前面谦炬,GCD確實(shí)是非常抽象的一個(gè)庫(kù),很容易讓人產(chǎn)生放棄的情緒辛藻,但“誰(shuí)無(wú)暴風(fēng)勁雨時(shí)捌省,守得云開(kāi)見(jiàn)月明”苫纤。首先需要找到GCD的源碼:libdispatch-1271.120.2 ,拿到源碼之后就可以開(kāi)心的解剖了纲缓。然而卷拘,GCD源碼中的類(lèi)型實(shí)在是太抽象了,不像objc源碼中的規(guī)規(guī)整整的結(jié)構(gòu)體祝高,而是宏定義栗弟,非常龐大的宏定義。另外工闺,GCD中的方法調(diào)用嵌套也是非常深乍赫,十幾層那是家常便飯÷襟。《庖丁解爬壮В》中指出,除了要有鋒利的刀叠殷,還需要知道這頭牛內(nèi)部結(jié)構(gòu)是啥樣的改鲫,哪里有硬骨頭,哪里好下刀。所以第一步應(yīng)該是先將這些類(lèi)型結(jié)構(gòu)展開(kāi)成我們熟悉的結(jié)構(gòu)體樣式钩杰。
一纫塌、結(jié)構(gòu)體的繼承
1.1 _os_object_s——os系統(tǒng)類(lèi)
系統(tǒng)的對(duì)象類(lèi),GCD中不直接使用這種類(lèi)型讲弄,類(lèi)型定義為:
typedef struct _os_object_s {
_OS_OBJECT_HEADER(
const _os_object_vtable_s *__ptrauth_objc_isa_pointer os_obj_isa,
os_obj_ref_cnt,
os_obj_xref_cnt);
} _os_object_s;
將_OS_OBJECT_HEADER展開(kāi)來(lái)看:
#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
-
volatile
提示編譯器變量隨時(shí)有可能改變,總與編譯器優(yōu)化有關(guān)依痊; - 返回一個(gè)
_os_object_s
對(duì)象 - 常用作GCD類(lèi)中的構(gòu)造方法
1.2 dispatch_object_t——isa描述類(lèi)
聯(lián)合體類(lèi)型避除,繼承于_os_object_s
(結(jié)構(gòu)體中,一般第一個(gè)屬性表示繼承的父類(lèi)
)胸嘁,本身沒(méi)有成員變量瓶摆,包含GCD中所有類(lèi)型的指針,可以被理解為GCD中的isa
的類(lèi)型描述性宏,定義為:
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;
- GCD中的基類(lèi)群井,用來(lái)表示GCD中的各種類(lèi)型
1.3 dispatch_object_s——GCD基類(lèi)
繼承于_os_object_s
,結(jié)構(gòu)體的繼承:通常情況下毫胜,將結(jié)構(gòu)體的第一個(gè)屬性稱(chēng)為父類(lèi)书斜,只是邏輯上的繼承,沒(méi)有OC中明顯的繼承符號(hào)酵使。在后面的分析中荐吉,可以發(fā)現(xiàn)這個(gè)類(lèi)結(jié)構(gòu)是GCD中絕大部分類(lèi)的基類(lèi)。
在GCD中口渔,通過(guò)宏的方式样屠,將父類(lèi)的屬性在子類(lèi)中重寫(xiě),定義如下:
struct dispatch_object_s {
_DISPATCH_OBJECT_HEADER(object);
};
dispatch_object_s
類(lèi)型中只有一個(gè)宏定義:_DISPATCH_OBJECT_HEADER(object);
缺脉,完全看不出內(nèi)部結(jié)構(gòu)是啥樣子的痪欲,為了能探索下去,只能將宏展開(kāi):_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; \
union { \
dispatch_function_t DISPATCH_FUNCTION_POINTER do_finalizer; \
void *do_introspection_ctxt; \
}
展開(kāi)之后攻礼,發(fā)現(xiàn)內(nèi)部還有一個(gè)宏:OS_OBJECT_STRUCT_HEADER(dispatch_##x)
业踢,所以只能繼續(xù)展開(kāi):
#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)
#endif
展開(kāi)的結(jié)構(gòu)中仍然還包裹著一層宏:_OS_OBJECT_HEADER
,但回顧_os_object_s
結(jié)構(gòu)時(shí)秘蛔,可以發(fā)現(xiàn)陨亡,宏定義已經(jīng)到頭了,可以認(rèn)為dispatch_object_s
是繼承_os_object_s
對(duì)象的:
#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
我們逐層將宏定義展開(kāi)深员,并將參數(shù)
帶進(jìn)來(lái)進(jìn)行替換负蠕,最終的數(shù)據(jù)結(jié)構(gòu)是:
struct _os_object_s _as_os_obj[0];
const struct dispatch_object_vtable_s *do_vtable;// 重寫(xiě)isa指針do_ref_cnt;//重寫(xiě)內(nèi)部引用計(jì)數(shù)
do_xref_cnt;//重寫(xiě)外部引用計(jì)數(shù)struct dispatch_queue_s *do_targetq;//指定的隊(duì)列void *do_ctxt;//union {
dispatch_function_t do_finalizer; void *do_introspection_ctxt;}
這種格式的結(jié)構(gòu)體比最開(kāi)始的宏定義的結(jié)構(gòu)體要清晰多了。在GCD的分析中倦畅,首先應(yīng)該將宏定義逐層展開(kāi)遮糖,還原結(jié)構(gòu)體本身的模樣。
二叠赐、宏定義結(jié)構(gòu)
這里猜測(cè)下蘋(píng)果為什么要用和么復(fù)雜的宏定義欲账?可能是因?yàn)閿?shù)據(jù)結(jié)構(gòu)有非常多的屬性屡江,而對(duì)于這些數(shù)據(jù)結(jié)構(gòu)中又有大量的相同屬性,少量的差異屬性赛不,使用宏定義可以減少大量的類(lèi)型定義的代碼惩嘉,使類(lèi)型的封裝性更高。
通過(guò)分析更多的GCD數(shù)據(jù)結(jié)構(gòu)踢故,可以看出大部分宏定義內(nèi)部最終都會(huì)指向那幾個(gè)基礎(chǔ)的宏定義文黎,本節(jié)將對(duì)宏定義進(jìn)行展開(kāi)說(shuō)明。
2.1 _OS_OBJECT_HEADER—— _os_object_s
在GCD中殿较,所有的宏定義解析耸峭,最終都會(huì)指向這個(gè)宏定義,對(duì)應(yīng)的類(lèi)型是_os_object_s
淋纲。如果把它理解為基類(lèi)劳闹,描述了一個(gè)GCD對(duì)象中應(yīng)該有的基礎(chǔ)屬性:
- isa:等同于objc對(duì)象中的isa指針;
- ref_cnt:引用計(jì)數(shù)洽瞬,用作GCD內(nèi)部本涕;
- xref_cnt:引用計(jì)數(shù),用作GCD外部片任;
_OS_OBJECT_HEADER(isa, ref_cnt, xref_cnt)
isa;
int volatile ref_cnt;
int volatile xref_cnt;
OS_OBJECT_STRUCT_HEADER
宏是對(duì)上面宏的一個(gè)包裝偏友,多了一個(gè)參數(shù)x
,通過(guò)注釋可以看出GCD對(duì)象中isa的最終類(lèi)型會(huì)被轉(zhuǎn)換成:const struct x_vtable_s *
对供,這個(gè)x
就是從外面?zhèn)鬟^(guò)來(lái)的類(lèi)型位他,宏定義的替換發(fā)生在預(yù)編譯階段,所以代碼只有編譯起來(lái)之后才能看到GCD的類(lèi)型产场。
OS_OBJECT_STRUCT_HEADER(x)
isa; // const struct x_vtable_s *
int volatile ref_cnt;
int volatile xref_cnt;
2.2 _DISPATCH_OBJECT_HEADER—— dispatch_object_s
從這個(gè)宏的名字定義來(lái)看鹅髓,表示的是GCD中的對(duì)象定義。將這個(gè)宏定義展開(kāi)之后的結(jié)構(gòu)如下京景,其中isa
的注釋耐人尋味:const struct dispatch_x_vtable_s *
窿冯,前面拼接了一個(gè)dispatch_
的前綴,明確的表示的是GCD中的類(lèi)确徙。
_DISPATCH_OBJECT_HEADER(x)
struct _os_object_s _as_os_obj[0];
isa; // const struct dispatch_x_vtable_s *
int volatile ref_cnt;
int volatile xref_cnt;
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;
}
DISPATCH_OBJECT_HEADER
是對(duì)上面宏的包裝醒串,多了一個(gè)struct dispatch_x_s _as_do[0];
屬性。
DISPATCH_OBJECT_HEADER(x)
struct dispatch_x_s _as_do[0];
// _DISPATCH_OBJECT_HEADER(x)
struct _os_object_s _as_os_obj[0];
isa; // const struct dispatch_x_vtable_s *
int volatile ref_cnt;
int volatile xref_cnt;
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;
}
可以通過(guò)一個(gè)實(shí)例對(duì)象類(lèi)型來(lái)展開(kāi)宏看看鄙皇。在dispatch_object_s
結(jié)構(gòu)體中芜赌,傳遞的是object
,這個(gè)參數(shù)解析出來(lái)的類(lèi)型就是:dispatch_ object_vtable_s
伴逸、dispatch_ object_s
缠沈。
struct dispatch_object_s {
_DISPATCH_OBJECT_HEADER(object);
};
2.3 _DISPATCH_QUEUE_CLASS_HEADER——dispatch_queue_s
先來(lái)看看dispatch_queue_s
的類(lèi)型定義,內(nèi)部宏:DISPATCH_QUEUE_CLASS_HEADER
,傳遞參數(shù):queue
和void *
指針。
struct dispatch_queue_s {
DISPATCH_QUEUE_CLASS_HEADER(queue, void *__dq_opaque1);
/* 32bit hole on LP64 */
} DISPATCH_ATOMIC64_ALIGN;
_DISPATCH_QUEUE_CLASS_HEADER
宏表示隊(duì)列類(lèi)的基礎(chǔ)屬性、父類(lèi)屬性
_DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__)
// DISPATCH_OBJECT_HEADER(x)
struct dispatch_x_s _as_do[0];
struct _os_object_s _as_os_obj[0];
isa; // const struct dispatch_x_vtable_s *
int volatile ref_cnt;
int volatile xref_cnt;
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;
}
__pointer_sized_field__;
DISPATCH_UNION_LE(uint64_t volatile dq_state,
dispatch_lock dq_state_lock,
uint32_t dq_state_bits
)
dispatch_queue_s
類(lèi)型最終展開(kāi)的結(jié)構(gòu)體類(lèi)型如下所示彻犁,有非常多的屬性。
- 基類(lèi)的屬性:
isa
亡问、ref_cnt
、xref_cnt
- 隊(duì)列的并發(fā)數(shù):
dq_serialnum
肛宋,可以控制串行還是并行 - 隊(duì)列的標(biāo)簽:
dq_label
玛界,我們?cè)趧?chuàng)建隊(duì)列時(shí)填的 - 隊(duì)列的優(yōu)先級(jí):
dq_priority
,可以通過(guò)API設(shè)定隊(duì)列優(yōu)先級(jí)
-隊(duì)列的任務(wù)數(shù):dq_sref_cnt
悼吱,同步、異步添加的任務(wù)
其他的Union類(lèi)型一般都是針對(duì)某個(gè)屬性的描述良狈,本身并不具有真實(shí)值后添。分析到這里,隊(duì)列的數(shù)據(jù)結(jié)構(gòu)就非常明了了薪丁。結(jié)合到我們平時(shí)通過(guò)GCD的一些API的調(diào)用可以看出遇西,最終都是為了修改其中的某個(gè)屬性。
DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__)
// _DISPATCH_QUEUE_CLASS_HEADER(x, __pointer_sized_field__)
struct dispatch_x_s _as_do[0];
struct _os_object_s _as_os_obj[0];
isa; // const struct dispatch_x_vtable_s *
int volatile ref_cnt;
int volatile xref_cnt;
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;
}
__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
2.4 DISPATCH_SOURCE_CLASS_HEADER—— dispatch_source_s
先來(lái)看看dispatch_source_s
結(jié)構(gòu)體的定義严嗜,同樣也只有一個(gè)宏定義:DISPATCH_SOURCE_CLASS_HEADER
粱檀,接受參數(shù):source
。同樣的配方漫玄,我們將這個(gè)宏定義展開(kāi)看看茄蚯。
struct dispatch_source_s {
DISPATCH_SOURCE_CLASS_HEADER(source);
} DISPATCH_ATOMIC64_ALIGN;
在DISPATCH_SOURCE_CLASS_HEADER
的內(nèi)部依賴(lài)一個(gè)新的宏:DISPATCH_LANE_CLASS_HEADER
,結(jié)構(gòu)如下睦优∩#可以看出來(lái),宏:DISPATCH_LANE_CLASS_HEADER
內(nèi)部任然依賴(lài)宏:DISPATCH_QUEUE_CLASS_HEADER
汗盘,這個(gè)宏就是上面的
dispatch_queue_s
對(duì)象皱碘,由此可見(jiàn)dispatch_source_s
與dispatch_queue_s
有非常大關(guān)聯(lián)。在上一篇博客11--多線程探索03--GCD應(yīng)用中介紹了dispatch_source_t
作為定時(shí)器的使用案例隐孽。dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
創(chuàng)建方法第四個(gè)參數(shù)就接受一個(gè)隊(duì)列癌椿,由此可見(jiàn),這個(gè)隊(duì)列的使用就在這里菱阵。文章的最后還介紹的dispatch_source_t
作為定時(shí)器的暫停和恢復(fù)踢俄,宏DISPATCH_LANE_CLASS_HEADER
的最后一個(gè)屬性dq_side_suspend_cnt
,從字面義上可以看出這個(gè)跟dispatch_source_t
的暫停相關(guān)送粱。
DISPATCH_LANE_CLASS_HEADER(x)
struct dispatch_queue_s _as_dq[0];
// DISPATCH_QUEUE_CLASS_HEADER
struct dispatch_x_s _as_do[0];
struct _os_object_s _as_os_obj[0];
isa; // const struct dispatch_x_vtable_s *
int volatile ref_cnt;
int volatile xref_cnt;
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;
}
__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
// DISPATCH_QUEUE_CLASS_HEADER
dispatch_unfair_lock_s dq_sidelock;
struct dispatch_object_s *volatile dq_items_head;
uint32_t dq_side_suspend_cnt
dispatch_source_s類(lèi)型最終展開(kāi)的結(jié)構(gòu)體類(lèi)型如下所示褪贵,相對(duì)于上面的類(lèi)型中多了兩個(gè)聯(lián)合體。同樣的,聯(lián)合體往往都會(huì)被看出是對(duì)某個(gè)字段的解釋脆丁。從注釋中也可以清晰的看出世舰,下面的的位域在鎖的作用下表示不同的含義,具體釋義可以在后面的分析中嘗試分析槽卫。
DISPATCH_SOURCE_CLASS_HEADER(x)
struct dispatch_queue_s _as_dq[0];
struct dispatch_source_s _as_do[0];
struct _os_object_s _as_os_obj[0];
isa; // const struct dispatch_source_vtable_s *
int volatile ref_cnt;
int volatile xref_cnt;
struct dispatch_source_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;
}
__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
dispatch_unfair_lock_s dq_sidelock;
struct dispatch_object_s *volatile dq_items_head;
uint32_t dq_side_suspend_cnt
uint16_t
/* set under the drain lock */
ds_is_installed:1,
ds_latched:1,
dm_connect_handler_called:1,
dm_cancel_handler_called:1,
dm_is_xpc:1,
dm_arm_no_senders:1,
dm_made_sendrights:1,
dm_strict_reply:1,
__ds_flags_pad : 8;
uint16_t __dq_flags_separation[0];
uint16_t
/* set under the send queue lock */
dm_needs_mgr:1,
dm_disconnected:1,
__dm_flags_pad : 14
2.5 DISPATCH_OBJECT_HEADER——dispatch_semaphore_s
最后一種我們熟知的GCD類(lèi)型——信號(hào)量跟压,dispatch_semaphore_s
。在11--多線程探索03--GCD應(yīng)用中也介紹了dispatch_semaphore_s
的強(qiáng)大之處歼培,但它的結(jié)構(gòu)非常簡(jiǎn)單震蒋,至少比上面幾種類(lèi)型的結(jié)構(gòu)要簡(jiǎn)單得多。
struct dispatch_semaphore_s {
DISPATCH_OBJECT_HEADER(semaphore);
intptr_t volatile dsema_value;
intptr_t dsema_orig;
_dispatch_sema4_t dsema_sema;
};
直接繼承了dispatch_object_s
對(duì)象躲庄,全部展開(kāi)如下所示:
-
dsema_value
:當(dāng)前的信號(hào)量大小 -
dsema_orig
:原始信號(hào)量大小 -
dsema_sema
:用來(lái)和內(nèi)核通信的信號(hào)量數(shù)值
struct dispatch_semaphore_s {
struct dispatch_ semaphore_s _as_do[0];
// _DISPATCH_OBJECT_HEADER(x)
struct _os_object_s _as_os_obj[0];
isa; // const struct dispatch_ semaphore_vtable_s *
int volatile ref_cnt;
int volatile xref_cnt;
struct dispatch_ semaphore_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;
}
intptr_t volatile dsema_value;
intptr_t dsema_orig;
_dispatch_sema4_t dsema_sema;
};
到這里查剖,我們對(duì)常見(jiàn)的幾種GCD類(lèi)型的數(shù)據(jù)結(jié)構(gòu)就有個(gè)非常清晰的了解了≡刖剑回到面向?qū)ο笞钤镜囊?guī)則——萬(wàn)物皆對(duì)象笋庄,所有的GCD類(lèi)型也都能視為對(duì)象,所以我們后面就從面向?qū)ο蟮乃季S來(lái)分析它們的變化倔监。
三直砂、GCD繼承關(guān)系圖
下面的結(jié)構(gòu)圖中只展開(kāi)了常見(jiàn)的
寫(xiě)在后面,接近半個(gè)月對(duì)libdispatch-1271.120.2分析的過(guò)程不那么順利浩习,異常復(fù)雜的嵌套静暂,類(lèi)型嵌套和調(diào)用嵌套都非常深,總會(huì)讓人迷失在嵌套的地獄中谱秽,往往看到后面就不知道是當(dāng)前類(lèi)型是啥了洽蛀,只有將所有的宏定義展開(kāi)才知道。所以這里找了一套早期的源碼弯院,OS X 10.9.5
中的libdispatch-339.92.1
辱士。
GCD數(shù)據(jù)結(jié)構(gòu)
Dispatch 中常用的宏定義及基礎(chǔ)知識(shí)
DISPATCH_DECL
#define DISPATCH_DECL(name) typedef struct name##_s *name##_t
GCD中的變量大多使用了這個(gè)宏,比如DISPATCH_DECL(dispatch_queue)
展開(kāi)后是
typedef struct dispatch_queue_s *dispatch_queue_t听绳;
它的意思是定義一個(gè)dispatch_queue_t
類(lèi)型的指針颂碘,指向了一個(gè)dispatch_queue_s
類(lèi)型的結(jié)構(gòu)體。
fastpath vs slowpath
#define fastpath(x) ((typeof(x))__builtin_expect((long)(x), ~0l))
#define slowpath(x) ((typeof(x))__builtin_expect((long)(x), 0l))
__builtin_expect
是編譯器優(yōu)化匯編代碼的椅挣,fastpath(x) 依然返回 x头岔,只是告訴編譯器 x 的值一般不為 0,從而編譯器可以進(jìn)行優(yōu)化鼠证。同理峡竣,slowpath(x)
表示 x 的值很可能為 0,希望編譯器進(jìn)行優(yōu)化量九。
TSD:Thread Specific Data
Thread Specific Data(TSD)
是指線程私有數(shù)據(jù)适掰。在多線程中颂碧,會(huì)用全局變量來(lái)實(shí)現(xiàn)多個(gè)函數(shù)間的數(shù)據(jù)共享,局部變量來(lái)實(shí)現(xiàn)內(nèi)部的單獨(dú)訪問(wèn)类浪。TSD則是能夠在同一個(gè)線程的不同函數(shù)中被訪問(wèn)载城,在不同線程時(shí),相同的鍵值獲取的數(shù)據(jù)隨線程不同而不同费就。可以通過(guò)pthread的相關(guān)api來(lái)實(shí)現(xiàn)TSD:
//創(chuàng)建key
int pthread_key_create(pthread_key_t *, void (* _Nullable)(void *));
//get方法
void* _Nullable pthread_getspecific(pthread_key_t);
//set方法
int pthread_setspecific(pthread_key_t , const void * _Nullable);
原子操作
#define dispatch_atomic_xchg(p, n) __sync_lock_test_and_set((p), (n))
#define dispatch_atomic_cmpxchg(p, o, n) __sync_bool_compare_and_swap((p), (o), (n))
#define dispatch_atomic_inc(p) __sync_add_and_fetch((p), 1)
#define dispatch_atomic_dec(p) __sync_sub_and_fetch((p), 1)
#define dispatch_atomic_add(p, v) __sync_add_and_fetch((p), (v))
#define dispatch_atomic_sub(p, v) __sync_sub_and_fetch((p), (v))
#define dispatch_atomic_or(p, v) __sync_fetch_and_or((p), (v))
#define dispatch_atomic_and(p, v) __sync_fetch_and_and((p), (v))
- _sync_lock_test_and_set((p), (n)) 將p設(shè)為value并返回p操作之前的值诉瓦。
- __sync_bool_compare_and_swap((p), (o), (n)) 這兩個(gè)函數(shù)提供原子的比較和交換:如果p == o,就將n寫(xiě)入p(p代表地址,o代表oldValue力细,n代表newValue)
- __sync_add_and_fetch((p), 1) 先自加1睬澡,再返回
- __sync_sub_and_fetch((p), 1) 先自減1,再返回
- __sync_add_and_fetch((p), (v)) 先自加v眠蚂,再返回
- __sync_sub_and_fetch((p), (v)) 先自減v煞聪,再返回
- __sync_fetch_and_or((p), (v)) 先返回,再進(jìn)行或運(yùn)算
- __sync_fetch_and_and((p), (v)) 先返回逝慧,再進(jìn)行與運(yùn)算
Dispatch 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)
源碼中數(shù)據(jù)結(jié)構(gòu)的命名一般是以_s和_t結(jié)尾米绕,其中_t是_s的指針類(lèi)型,_s是結(jié)構(gòu)體馋艺。比如dispatch_queue_t和dispatch_queue_s。
dispatch_object_s
dispatch_object_s
是GCD最基礎(chǔ)的結(jié)構(gòu)體迈套,相當(dāng)于基類(lèi)捐祠,類(lèi)似OC中的id類(lèi)型。定義如下:
struct dispatch_object_s {
DISPATCH_STRUCT_HEADER(object);
};
//os object頭部宏定義
#define _OS_OBJECT_HEADER(isa, ref_cnt, xref_cnt) \
isa; /* must be pointer-sized */ \ //isa
int volatile ref_cnt; \ //引用計(jì)數(shù)
int volatile xref_cnt //外部引用計(jì)數(shù)桑李,兩者都為0釋放
//dispatch 結(jié)構(gòu)體頭部
#define DISPATCH_STRUCT_HEADER(x) \
_OS_OBJECT_HEADER( \
const struct dispatch_##x##_vtable_s *do_vtable, \ //vtable 結(jié)構(gòu)體
do_ref_cnt, \
do_xref_cnt); \
struct dispatch_##x##_s *volatile do_next; \ //下一個(gè)do 鏈表next
struct dispatch_queue_s *do_targetq; \ //目標(biāo)隊(duì)列
void *do_ctxt; \ //上下文
void *do_finalizer; \ //銷(xiāo)毀時(shí)調(diào)用函數(shù)
unsigned int do_suspend_cnt; //suspend計(jì)數(shù)踱蛀, 用作暫停標(biāo)志
dispatch_object_t
dispatch_object_t
是個(gè)union的聯(lián)合體,可以用dispatch_object_t代表這個(gè)聯(lián)合體里的所有數(shù)據(jù)結(jié)構(gòu)贵白。
union與結(jié)構(gòu)體有本質(zhì)的不同率拒,結(jié)構(gòu)體中各成員有各自的內(nèi)存空間,聯(lián)合體中的各成員共享一段內(nèi)存空間禁荒,一個(gè)聯(lián)合變量的長(zhǎng)度等于各成員最長(zhǎng)的長(zhǎng)度猬膨。用于節(jié)省內(nèi)存。
typedef union {
struct _os_object_s *_os_obj;
struct dispatch_object_s *_do;
struct dispatch_continuation_s *_dc;
struct dispatch_queue_s *_dq;
struct dispatch_queue_attr_s *_dqa;
struct dispatch_group_s *_dg;
struct dispatch_source_s *_ds;
struct dispatch_mach_s *_dm;
struct dispatch_mach_msg_s *_dmsg;
struct dispatch_timer_aggregate_s *_dta;
struct dispatch_source_attr_s *_dsa;
struct dispatch_semaphore_s *_dsema;
struct dispatch_data_s *_ddata;
struct dispatch_io_s *_dchannel;
struct dispatch_operation_s *_doperation;
struct dispatch_disk_s *_ddisk;
} dispatch_object_t __attribute__((__transparent_union__));
dispatch_xxx_vtable
DISPATCH_VTABLE_HEADER(x)
vtable結(jié)構(gòu)體定義呛伴,包含了這個(gè)dispatch_object_s
的操作函數(shù)
#define DISPATCH_VTABLE_HEADER(x) \
unsigned long do_type; \ //dispatch_object_s類(lèi)型
const char *do_kind; \ //do 的說(shuō)明
size_t (*do_debug)(struct dispatch_##x##_s *, char *, size_t); \ //debug方法
void (*do_invoke)(struct dispatch_##x##_s *); \ //任務(wù)出隊(duì)時(shí)會(huì)觸發(fā)invoke函數(shù)
unsigned long (*do_probe)(struct dispatch_##x##_s *); \ //用戶(hù)隊(duì)列創(chuàng)建的這個(gè)方法是空的勃痴,但rootqueue內(nèi)的這個(gè)有一個(gè) `_dispatch_queue_wakeup_global`函數(shù)。一般是喚醒隊(duì)列的方法
void (*do_dispose)(struct dispatch_##x##_s *); //銷(xiāo)毀隊(duì)列的方法,內(nèi)部通常調(diào)用do_finalizer 函數(shù)热康。
//dx_xxx 開(kāi)頭的宏定義沛申,本質(zhì)是調(diào)用vtable中定義的函數(shù)
#define dx_type(x) (x)->do_vtable->do_type
#define dx_metatype(x) ((x)->do_vtable->do_type & _DISPATCH_META_TYPE_MASK)
#define dx_kind(x) (x)->do_vtable->do_kind
#define dx_debug(x, y, z) (x)->do_vtable->do_debug((x), (y), (z))
#define dx_dispose(x) (x)->do_vtable->do_dispose(x)
#define dx_invoke(x) (x)->do_vtable->do_invoke(x)
#define dx_probe(x) (x)->do_vtable->do_probe(x)
dispatch_continuation_s
dispatch_continuation_s
結(jié)構(gòu)體主要封裝block和function,被傳入的block會(huì)變成這個(gè)結(jié)構(gòu)體對(duì)象傳入隊(duì)列。定義如下
#define DISPATCH_CONTINUATION_HEADER(x) \
_OS_OBJECT_HEADER( \
const void *do_vtable, \
do_ref_cnt, \
do_xref_cnt); \ //os_object_header
struct dispatch_##x##_s *volatile do_next; \ //下一個(gè)任務(wù) 鏈表next
dispatch_function_t dc_func; \ // 如 _dispatch_call_block_and_release 方法姐军,結(jié)構(gòu)體實(shí)際執(zhí)行的方法
void *dc_ctxt; \ // 調(diào)用dispatch_async 傳入的block 即待執(zhí)行的內(nèi)容,會(huì)作為參數(shù)傳入dc_func
void *dc_data; \ //相關(guān)數(shù)據(jù)
void *dc_other; //其他
struct dispatch_continuation_s {
DISPATCH_CONTINUATION_HEADER(continuation);
};
dispatch_queue_s
dispatch_queue_s
是隊(duì)列的結(jié)構(gòu)體铁材,是我們接觸最多的結(jié)構(gòu)體尖淘。
struct dispatch_queue_s {
DISPATCH_STRUCT_HEADER(queue);
DISPATCH_QUEUE_HEADER;
DISPATCH_QUEUE_CACHELINE_PADDING; // for static queues only
};
#define DISPATCH_QUEUE_HEADER \
uint32_t volatile dq_running; \ //隊(duì)列運(yùn)行的任務(wù)數(shù)量
struct dispatch_object_s *volatile dq_items_head; \ //頭節(jié)點(diǎn)
/* LP64 global queue cacheline boundary */ \
struct dispatch_object_s *volatile dq_items_tail; \ //尾節(jié)點(diǎn)
dispatch_queue_t dq_specific_q; \ //specifix隊(duì)列
uint32_t dq_width; \ //隊(duì)列并發(fā)數(shù)
unsigned int dq_is_thread_bound:1; \ //是否線程綁定
unsigned long dq_serialnum; \ //隊(duì)列序號(hào)
const char *dq_label; \ //隊(duì)列名
DISPATCH_INTROSPECTION_QUEUE_LIST;