最近在閱讀 SDWebImage 的源碼,發(fā)現(xiàn)了這段有趣的代碼蔗草。
最新代碼
#ifndef dispatch_main_async_safe
#define dispatch_main_async_safe(block)\
if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\
block();\
} else {\
dispatch_async(dispatch_get_main_queue(), block);\
}
#endif
之前的代碼咒彤,而且這是網(wǎng)上流傳最多的代碼。
#define dispatch_main_async_safe(block)\
if ([NSThread isMainThread]) {\
block();\
} else {\
dispatch_async(dispatch_get_main_queue(), block);\
}
對(duì)比兩段代碼可以發(fā)現(xiàn)前者有兩個(gè)地方改變了咒精,一是多了 #ifndef
镶柱,二是判斷條件改變了。
顯然狠轻,增加 #ifndef
是為了提高代碼的嚴(yán)謹(jǐn)奸例,防止重復(fù)定義 dispatch_main_async_safe
。
關(guān)于判斷條件的改變的原因則是復(fù)雜得多了向楼,具體可以閱讀 GCD's Main Queue vs. Main Thread查吊。
原文這樣說(shuō)道:
Calling an API from a non-main queue that is executing on the main thread will lead to issues if the library (like VektorKit) relies on checking for execution on the main queue.
意思大概是如果在主線程執(zhí)行非主隊(duì)列調(diào)度的API,而這個(gè)API需要檢查是否由主隊(duì)列上調(diào)度湖蜕,那么將會(huì)出現(xiàn)問(wèn)題逻卖。
SDWebImage 就是從判斷是否在主線程執(zhí)行改為判斷是否由主隊(duì)列上調(diào)度。而由于主隊(duì)列是一個(gè)串行隊(duì)列昭抒,無(wú)論任務(wù)是異步同步都不會(huì)開(kāi)辟新線程评也,所以當(dāng)前隊(duì)列是主隊(duì)列等價(jià)于當(dāng)前在主線程上執(zhí)行∶鸱担可以這樣說(shuō)盗迟,在主隊(duì)列調(diào)度的任務(wù)肯定在主線程執(zhí)行,而在主線程執(zhí)行的任務(wù)不一定是由主隊(duì)列調(diào)度的熙含。
參考資料