RunLoop
RunLoop是iOS、OSX开发中非常基础的一个概念,这篇文章将会从源码的角度分析RunLoop的概念已经底层实现原理。在iOS中,苹果如何利用RunLoop实现了自动释放池、延迟回调、触摸事件和屏幕刷新等功能,我们也将一一探索。
RunLoop的作用
- 保持程序的运行
- 处理APP的各种事件(触摸,定时器,
performSelector) - 节省CPU资源、提高程序的性能;该做事就做事,该休息就休息
RunLoop的应用非常广泛,iOS中多种任务的执行都依赖RunLoop,下面是一些RunLoop的call out函数
block:CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK
NSTimer:__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
SOURCE0:__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
SOURCE1:__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
GCD主队列:__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
observer源:__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
官方文档
RunLoop的官方文档在Threading Programming Guide中。

OSX/iOS系统中,提供了两个RunLoop对象NSRunLoop和CFRunLoopRef
CFRunLoopRef是在CoreFoundation框架内的,它提供了纯C函数的API,所有这些API是线程安全的
NSRunLoop是基于CFRunLoopRef的封装,提供了面向对象的API,但是这些API不是线程安全的
CFRunLoopRef的代码是开源的,可以在这里下载
源码分析
- 搜索
CFRunLoopRun
void CFRunLoopRun(void) { /* DOES CALLOUT */
int32_t result;
do {
result = CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);
CHECK_FOR_FORK();
} while (kCFRunLoopRunStopped != result && kCFRunLoopRunFinished != result);
}
这就是一个do-while循环,这里最重要的就是CFRunLoopRunSpecific方法。当RunLoopRunStopped或者RunLoopRunFinished的时候才会跳出循环
- 查看
CFRunLoopRunSpecific
SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) { /* DOES CALLOUT */
CHECK_FOR_FORK();
if (__CFRunLoopIsDeallocating(rl)) return kCFRunLoopRunFinished;
__CFRunLoopLock(rl);
CFRunLoopModeRef currentMode = __CFRunLoopFindMode(rl, modeName, false);
if (NULL == currentMode || __CFRunLoopModeIsEmpty(rl, currentMode, rl->_currentMode)) {
Boolean did = false;
if (currentMode) __CFRunLoopModeUnlock(currentMode);
__CFRunLoopUnlock(rl);
return did ? kCFRunLoopRunHandledSource : kCFRunLoopRunFinished;
}
volatile _per_run_data *previousPerRun = __CFRunLoopPushPerRunData(rl);
CFRunLoopModeRef previousMode = rl->_currentMode;
rl->_currentMode = currentMode;
int32_t result = kCFRunLoopRunFinished;
if (currentMode->_observerMask & kCFRunLoopEntry ) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);//通知Observer,runloop即将进来
result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode);//这是才是`runloop`执行任务的地方
if (currentMode->_observerMask & kCFRunLoopExit ) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);//通知Observer,runloop即将退出
__CFRunLoopModeUnlock(currentMode);
__CFRunLoopPopPerRunData(rl, previousPerRun);
rl->_currentMode = previousMode;
__CFRunLoopUnlock(rl);
return result;
}
RunLoop和线程的关系
苹果不允许直接创建RunLoop,它提供了两个获取的函数CFRunLoopGetMain()和CFRunLoopGetCurrent (),下面我们看一下这两个函数的实现。
- 搜索
CFRunLoopGetMain
CFRunLoopRef CFRunLoopGetMain(void) {
CHECK_FOR_FORK();
static CFRunLoopRef __main = NULL; // no retain needed
if (!__main) __main = _CFRunLoopGet0(pthread_main_thread_np()); // no CAS needed
return __main;
}
- 搜索
CFRunLoopGetCurrent
CFRunLoopRef CFRunLoopGetCurrent(void) {
CHECK_FOR_FORK();
CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(__CFTSDKeyRunLoop);
if (rl) return rl;
return _CFRunLoopGet0(pthread_self());
}
上面两个函数,都调用了_CFRunLoopGet0
- 查看
_CFRunLoopGet0
CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {
if (pthread_equal(t, kNilPthreadT)) {
t = pthread_main_thread_np();//线程为空,设置为主线程
}
__CFLock(&loopsLock);
if (!__CFRunLoops) {//绑定主线程
__CFUnlock(&loopsLock);
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());
// 进行绑定 dict[@"pthread_main_thread_np"] = mainLoop
CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);
if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) {
CFRelease(dict);
}
CFRelease(mainLoop);
__CFLock(&loopsLock);
}
//绑定其他线程
CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
__CFUnlock(&loopsLock);
if (!loop) {
CFRunLoopRef newLoop = __CFRunLoopCreate(t);
__CFLock(&loopsLock);
loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
if (!loop) {
CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop);
loop = newLoop;
}
// don't release run loops inside the loopsLock, because CFRunLoopDeallocate may end up taking it
__CFUnlock(&loopsLock);
CFRelease(newLoop);
}
if (pthread_equal(t, pthread_self())) {
_CFSetTSD(__CFTSDKeyRunLoop, (void *)loop, NULL);
if (0 == _CFGetTSD(__CFTSDKeyRunLoopCntr)) {
_CFSetTSD(__CFTSDKeyRunLoopCntr, (void *)(PTHREAD_DESTRUCTOR_ITERATIONS-1), (void (*)(void *))__CFFinalizeRunLoop);
}
}
return loop;
}
这个方法主要是创建runloop,并把runloop和对应的线程通过key-value的方式保存下来。
- 查看
__CFRunLoopCreate
static CFRunLoopRef __CFRunLoopCreate(pthread_t t) {
CFRunLoopRef loop = NULL;
CFRunLoopModeRef rlm;
uint32_t size = sizeof(struct __CFRunLoop) - sizeof(CFRuntimeBase);
//创建一个CFRunLoopRef
loop = (CFRunLoopRef)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault, CFRunLoopGetTypeID(), size, NULL);
if (NULL == loop) {
return NULL;
}
//下面是对`RunLoop`的赋值操作
(void)__CFRunLoopPushPerRunData(loop);
__CFRunLoopLockInit(&loop->_lock);
loop->_wakeUpPort = __CFPortAllocate();
if (CFPORT_NULL == loop->_wakeUpPort) HALT;
__CFRunLoopSetIgnoreWakeUps(loop);
loop->_commonModes = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
CFSetAddValue(loop->_commonModes, kCFRunLoopDefaultMode);
loop->_commonModeItems = NULL;
loop->_currentMode = NULL;
loop->_modes = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
loop->_blocks_head = NULL;
loop->_blocks_tail = NULL;
loop->_counterpart = NULL;
loop->_pthread = t;
#if DEPLOYMENT_TARGET_WINDOWS
loop->_winthread = GetCurrentThreadId();
#else
loop->_winthread = 0;
#endif
rlm = __CFRunLoopFindMode(loop, kCFRunLoopDefaultMode, true);
if (NULL != rlm) __CFRunLoopModeUnlock(rlm);
return loop;
}
- 搜索
__CFRunLoop {查看__CFRunLoop结构体
struct __CFRunLoop {
CFRuntimeBase _base;
pthread_mutex_t _lock; /* locked for accessing mode list */
__CFPort _wakeUpPort; // used for CFRunLoopWakeUp
Boolean _unused;
volatile _per_run_data *_perRunData; // reset for runs of the run loop
pthread_t _pthread;
uint32_t _winthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
struct _block_item *_blocks_head;
struct _block_item *_blocks_tail;
CFAbsoluteTime _runTime;
CFAbsoluteTime _sleepTime;
CFTypeRef _counterpart;
};
可以看到里面的Modes,说明runloop有多个mode切换,还有一个_currentMode表示当前mode
Mode

在断点处进行
LLDB调试
(lldb) po CFRunLoopCopyCurrentMode(mainRunLoop)
kCFRunLoopDefaultMode
(lldb) po CFRunLoopCopyAllModes(mainRunLoop)
<__NSArrayM 0x6000007a4930>(
UITrackingRunLoopMode,//追踪ScrollView的滑动状态
GSEventReceiveRunLoopMode,//处理事件
kCFRunLoopDefaultMode,
kCFRunLoopCommonModes
)
(lldb)
可以看出mainRunLoop里面有四种Mode,这也对应了上面,一个runLoop可以有多种mode,可以在各种mode之间切换
CFRunLoopMode和CFRunLoop大致源码如下:
struct __CFRunLoopMode {
...
CFStringRef _name;//mode name , 例如@"kCFRunLoopDefaultMode"
CFMutableSetRef _sources0;//sources0 set
CFMutableSetRef _sources1;//sources1 set
CFMutableArrayRef _observers;//_observers array
CFMutableArrayRef _timers;//_timers array
CFMutableDictionaryRef _portToV1SourceMap;
...
};
struct __CFRunLoop {//RunLoop里面存在modes
...
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
...
};
这里有个概念叫commonModes,一个mode可以将自己标记为“Common”属性(通过将其modeName加入到RunLoop的commonModes中)。每当RunLoop的内容发生变化时,RunLoop都会自动将_commonModeItems中的Source/Observer/Timer同步到具有“Common”标记的所有mode中。
主线程的RunLoop中有两个预置的mode: kCFRunLoopDefaultMode和UITrackingRunLoopMode,这两个都已经被标记“Common”属性。DefaultMode是APP平时所处的状态,TrackingRunLoopMode是追踪ScrollView滑动时的状态。当你创建一个timer加入到DefaultMode,正常情况下timer可以得到回调,但当你滑动ScrollView的时候,RunLoop会切换到TrackingRunLoopMode,这时的timer就不会回调,也不会影响滑动操作。
有时候你需要一个timer在两个mode中都能得到回调,一种方法是将timer分别加入这两个mode,还有一种方法就是将timer加入到顶层的commonModeItems中,被
RunLoop自动更新到具有“Common”的mode中去
面试题
NSTimer

结果是不会打印,子线的
runloop默认是不启动的,NSTimer不会执行block任务。
解决方法:

加上这一句代码,开启
runLoop即可
不知道大家有没有这样的疑问,NSTimer为什么要依赖于runLoop才可以执行呢?

在断点处打印堆栈信息,可以看到我们熟悉的
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
- 在源码中搜索
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__(CFRunLoopTimerCallBack func, CFRunLoopTimerRef timer, void *info) {
if (func) {
func(timer, info);
}
asm __volatile__(""); // thwart tail-call optimization
}
在这里执行了Timer的任务回调函数,其实执行任务要从下面的-[NSRunLoop(NSRunLoop) run]开始
-
搜索
__CFRunLoopRun找到一个很长的方法
往下看
这里是处理block和observer的
这里doTimers,处理timer 查看
__CFRunLoopDoTimers
static Boolean __CFRunLoopDoTimers(CFRunLoopRef rl, CFRunLoopModeRef rlm, uint64_t limitTSR) { /* DOES CALLOUT */
Boolean timerHandled = false;
CFMutableArrayRef timers = NULL;
for (CFIndex idx = 0, cnt = rlm->_timers ? CFArrayGetCount(rlm->_timers) : 0; idx < cnt; idx++) {
CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)CFArrayGetValueAtIndex(rlm->_timers, idx);
if (__CFIsValid(rlt) && !__CFRunLoopTimerIsFiring(rlt)) {
if (rlt->_fireTSR <= limitTSR) {
if (!timers) timers = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
CFArrayAppendValue(timers, rlt);
}
}
}
for (CFIndex idx = 0, cnt = timers ? CFArrayGetCount(timers) : 0; idx < cnt; idx++) {
CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)CFArrayGetValueAtIndex(timers, idx);
Boolean did = __CFRunLoopDoTimer(rl, rlm, rlt);
timerHandled = timerHandled || did;
}
if (timers) CFRelease(timers);
return timerHandled;
}
循环_timers里面的timer,执行__CFRunLoopDoTimer方法
- 查看
__CFRunLoopDoTimer
往下可以找到我们熟悉的__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__函数
最后我们查看一下timer在下层的结构
struct __CFRunLoopTimer {
CFRuntimeBase _base;
uint16_t _bits;
pthread_mutex_t _lock;
CFRunLoopRef _runLoop;
CFMutableSetRef _rlModes;
CFAbsoluteTime _nextFireDate;
CFTimeInterval _interval; /* immutable */
CFTimeInterval _tolerance; /* mutable */
uint64_t _fireTSR; /* TSR units */
CFIndex _order; /* immutable */
CFRunLoopTimerCallBack _callout; /* immutable */
CFRunLoopTimerContext _context; /* immutable, except invalidation */
};
NSTimer里面有_runLoop和_callout,拿到了timer对象就能准确执行
这些方法执行了Timer的任务。那又是哪个方法将Timer加到了NSRunLoop呢?
我们记得NSRunLoop有一个addTimer:forMode:的方法,在源码中搜索addTimer
-
搜索
addTimer
从这里可以看出,Source、Observer、Timer都要加入RunLoop 查看
CFRunLoopAddTimer方法
void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeName) {
CHECK_FOR_FORK();
if (__CFRunLoopIsDeallocating(rl)) return;
if (!__CFIsValid(rlt) || (NULL != rlt->_runLoop && rlt->_runLoop != rl)) return;
//屏蔽非空
__CFRunLoopLock(rl);//加锁
if (modeName == kCFRunLoopCommonModes) {//当是CommonMode
//_commonModes为空 赋一个默认值
CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault, rl->_commonModes) : NULL;
//_commonModeItems为空 赋一个默认值
if (NULL == rl->_commonModeItems) {
rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
}
CFSetAddValue(rl->_commonModeItems, rlt);//把timer加入 _commonModeItems
if (NULL != set) {//set 不为空 加到`CommonModes`中去
CFTypeRef context[2] = {rl, rlt};
/* add new item to all common-modes */
CFSetApplyFunction(set, (__CFRunLoopAddItemToCommonModes), (void *)context);
CFRelease(set);
}
}
else {
//根据name 和runloop匹配 CFRunLoopModeRef
CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, true);
if (NULL != rlm) {
if (NULL == rlm->_timers) {
CFArrayCallBacks cb = kCFTypeArrayCallBacks;
cb.equal = NULL;
rlm->_timers = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &cb);
}
}
if (NULL != rlm && !CFSetContainsValue(rlt->_rlModes, rlm->_name)) {
__CFRunLoopTimerLock(rlt);
if (NULL == rlt->_runLoop) {
rlt->_runLoop = rl;
} else if (rl != rlt->_runLoop) {
__CFRunLoopTimerUnlock(rlt);
__CFRunLoopModeUnlock(rlm);
__CFRunLoopUnlock(rl);
return;
}
CFSetAddValue(rlt->_rlModes, rlm->_name);
__CFRunLoopTimerUnlock(rlt);
__CFRunLoopTimerFireTSRLock();
__CFRepositionTimerInMode(rlm, rlt, false);//将timer添加到mode中
__CFRunLoopTimerFireTSRUnlock();
if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionLion)) {
// Normally we don't do this on behalf of clients, but for
// backwards compatibility due to the change in timer handling...
if (rl != CFRunLoopGetCurrent()) CFRunLoopWakeUp(rl);
}
}
if (NULL != rlm) {
__CFRunLoopModeUnlock(rlm);
}
}
__CFRunLoopUnlock(rl);
}
根据modeName将timer加到__CFRunLoopMode的_timers中去
- 搜索
__CFRepositionTimerInMode
static void __CFRepositionTimerInMode(CFRunLoopModeRef rlm, CFRunLoopTimerRef rlt, Boolean isInArray) {
if (!rlt) return;
CFMutableArrayRef timerArray = rlm->_timers;
if (!timerArray) return;
Boolean found = false;
// If we know in advance that the timer is not in the array (just being added now) then we can skip this search
if (isInArray) {
CFIndex idx = CFArrayGetFirstIndexOfValue(timerArray, CFRangeMake(0, CFArrayGetCount(timerArray)), rlt);
if (kCFNotFound != idx) {
CFRetain(rlt);
CFArrayRemoveValueAtIndex(timerArray, idx);
found = true;
}
}
if (!found && isInArray) return;
CFIndex newIdx = __CFRunLoopInsertionIndexInTimerArray(timerArray, rlt);
CFArrayInsertValueAtIndex(timerArray, newIdx, rlt);//将timer 加到_timers数组
__CFArmNextTimerInMode(rlm, rlt->_runLoop);
if (isInArray) CFRelease(rlt);
}
这个函数主要是添加timer
Observer
-
Observer结构体
struct __CFRunLoopObserver {
CFRuntimeBase _base;
pthread_mutex_t _lock;
CFRunLoopRef _runLoop;
CFIndex _rlCount;
CFOptionFlags _activities; /* immutable */
CFIndex _order; /* immutable */
CFRunLoopObserverCallBack _callout; /* immutable */
CFRunLoopObserverContext _context; /* immutable, except invalidation */
};
-
CFRunLoopAddObserver

-
__CFRunLoopDoObservers
与Timer的原理基本一致。
__CFRunLoopRun详解
CFRunLoopRun
void CFRunLoopRun(void) { /* DOES CALLOUT */
int32_t result;
do {
result = CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);// 科学计数1.0e10
CHECK_FOR_FORK();
} while (kCFRunLoopRunStopped != result && kCFRunLoopRunFinished != result);
}
每次runloop循环,传入了一个循环时间
-
__CFRunLoopRun
在这里面也有一个计时器用来记录时间,由于NSTimer是依赖于RunLoop的,在这里显然不适用。这里使用的是dispatch_source_t
dispatch_source_t timeout_timer = NULL;
struct __timeout_context *timeout_context = (struct __timeout_context *)malloc(sizeof(*timeout_context));
if (seconds <= 0.0) { // instant timeout
seconds = 0.0;
timeout_context->termTSR = 0ULL;
} else if (seconds <= TIMER_INTERVAL_LIMIT) {
dispatch_queue_t queue = pthread_main_np() ? __CFDispatchQueueGetGenericMatchingMain() : __CFDispatchQueueGetGenericBackground();
timeout_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_retain(timeout_timer);
timeout_context->ds = timeout_timer;
timeout_context->rl = (CFRunLoopRef)CFRetain(rl);
timeout_context->termTSR = startTSR + __CFTimeIntervalToTSR(seconds);
dispatch_set_context(timeout_timer, timeout_context); // source gets ownership of context
dispatch_source_set_event_handler_f(timeout_timer, __CFRunLoopTimeout);
dispatch_source_set_cancel_handler_f(timeout_timer, __CFRunLoopTimeoutCancel);
uint64_t ns_at = (uint64_t)((__CFTSRToTimeInterval(startTSR) + seconds) * 1000000000ULL);
dispatch_source_set_timer(timeout_timer, dispatch_time(1, ns_at), DISPATCH_TIME_FOREVER, 1000ULL);
dispatch_resume(timeout_timer);
} else { //超时
seconds = 9999999999.0;
timeout_context->termTSR = UINT64_MAX;
}
- 将代码折叠起来查看整体结构
do-while循环才是我们研究的重点,
下面是runloop方法的流程图和主要代码。
SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) { /* DOES CALLOUT */
CHECK_FOR_FORK();
if (__CFRunLoopIsDeallocating(rl)) return kCFRunLoopRunFinished;
__CFRunLoopLock(rl);
/// 首先根据modeName找到对应mode
CFRunLoopModeRef currentMode = __CFRunLoopFindMode(rl, modeName, false);
/// 通知 Observers: RunLoop 即将进入 loop。
__CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
/// 内部函数,进入loop
result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode);
/// 通知 Observers: RunLoop 即将退出。
__CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);
return result;
}
/// 核心函数
static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) {
int32_t retVal = 0;
do { // itmes do
/// 通知 Observers: 即将处理timer事件
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
/// 通知 Observers: 即将处理Source事件
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources)
/// 处理Blocks
__CFRunLoopDoBlocks(rl, rlm);
/// 处理sources0
Boolean sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm, stopAfterHandle);
/// 处理sources0返回为YES
if (sourceHandledThisLoop) {
/// 处理Blocks
__CFRunLoopDoBlocks(rl, rlm);
}
/// 判断有无端口消息(Source1)
if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0, &voucherState, NULL)) {
/// 处理消息
goto handle_msg;
}
/// 通知 Observers: 即将进入休眠
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
__CFRunLoopSetSleeping(rl);
/// 等待被唤醒
__CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy);
// user callouts now OK again
__CFRunLoopUnsetSleeping(rl);
/// 通知 Observers: 被唤醒,结束休眠
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
handle_msg:
if (被Timer唤醒) {
/// 处理Timers
__CFRunLoopDoTimers(rl, rlm, mach_absolute_time());
} else if (被GCD唤醒) {
/// 处理gcd
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);
} else if (被Source1唤醒) {
/// 被Source1唤醒,处理Source1
__CFRunLoopDoSource1(rl, rlm, rls, msg, msg->msgh_size, &reply)
}
/// 处理block
__CFRunLoopDoBlocks(rl, rlm);
if (sourceHandledThisLoop && stopAfterHandle) {
retVal = kCFRunLoopRunHandledSource;
} else if (timeout_context->termTSR < mach_absolute_time()) {
retVal = kCFRunLoopRunTimedOut;
} else if (__CFRunLoopIsStopped(rl)) {
__CFRunLoopUnsetStopped(rl);
retVal = kCFRunLoopRunStopped;
} else if (rlm->_stopped) {
rlm->_stopped = false;
retVal = kCFRunLoopRunStopped;
} else if (__CFRunLoopModeIsEmpty(rl, rlm, previousMode)) {
retVal = kCFRunLoopRunFinished;
}
} while (0 == retVal);
return retVal;
}
// main dispatch queue
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
// __CFRunLoopDoObservers
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
// __CFRunLoopDoBlocks
__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__
// __CFRunLoopDoSources0
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
// __CFRunLoopDoSource1
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
// __CFRunLoopDoTimers
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__









