1. 程式人生 > >Objective-C Runloop深入理解

Objective-C Runloop深入理解

darwin ole turn run set 技術分享 span 一個 cocoa

通常情況下,一個線程執行完一個任務,就會退出並銷毀。等到需要處理下一個任務時,又得重新創建一個線程。但是很多時候,這並不是我們想要的結果。例如,

1、當任務小而多時,頻繁地創建和銷毀線程,會帶來不小的代價。

2、iOS/OSX應用的主線程要是退出了,整個應用就掛了。

因此,需要一種能讓線程不退出的機制。這種機制就是event loop,event loop在很多語言中都有。Runloop就是它在Objective-C中的實現。

Runloop其實就是個do while循環。它能讓線程在沒有任務時休眠等待,以避免占用CPU,而有任務需要處理時,又可以及時喚醒。這是怎麽做到的呢?需要從Runloop的實現中一探究竟。

Runloop提供了兩種API,一種是CoreFoundation中純C實現的CFRunloopRef;另一種是Foundation中的Objective-C實現的NSRunloop,NSRunloop是對CFRunloopRef的封裝。秘密就隱藏在CFRunloopRef的源碼中。

void CFRunLoopRun() {
CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false); }

SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) {    
    __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry); 
// 1、通知Observer,進入Runloop __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode); __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit); // 10、通知Observer,結束Runloop }

static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) {
    int32_t retVal 
= 0; do { // Runloop的一次叠代 __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers); // 2、通知Observer,即將處理timer __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources); // 3、通知Observer,即將處理source __CFRunLoopDoBlocks(rl, rlm); // 執行block __CFRunLoopDoSources0(rl, rlm, stopAfterHandle); // 處理source0 __CFRunLoopDoBlocks(rl, rlm); // 執行block __CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0)); // 處理source1 __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting); // 6、通知Observer,即將休眠等待 __CFRunLoopSetSleeping(rl); // 7、休眠等待 __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting); // 8、通知Observer,即將被喚醒 __CFRunLoopDoTimers(rl, rlm, mach_absolute_time()) // 處理timer __CFRunLoopDoSource1(rl, rlm, rls, msg, msg->msgh_size, &reply); // 處理source1 __CFRunLoopDoBlocks(rl, rlm); // 執行block } while (0 == retVal); return retVal; }

技術分享圖片

參考鏈接:

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW23

http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_msg.html

==========================================

mach_msg

MACH_SEND_MSG

MACH_RCV_MSG

Objective-C Runloop深入理解