Skip to content

Instantly share code, notes, and snippets.

@kikohz
Created November 9, 2021 08:32
Show Gist options
  • Save kikohz/eebe97f8e142f1c2c31e27eb16db6802 to your computer and use it in GitHub Desktop.
Save kikohz/eebe97f8e142f1c2c31e27eb16db6802 to your computer and use it in GitHub Desktop.
static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) {
//通知Observer:即将处理Timers事件
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
//通知Observer:即将处理Sources事件
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
//处理Blocks
__CFRunLoopDoBlocks(rl, rlm);
//处理Sources0 通过处理结果来判断是否需要再次执行Blocks
Boolean sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm, stopAfterHandle);
if (sourceHandledThisLoop) {
__CFRunLoopDoBlocks(rl, rlm);
}
//判断Sources1(MachPort为Sources1),如果有事件,直接跳转到handle_msg
if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), 0)) {
goto handle_msg;
}
//通知Observer:即将进入休眠
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
//开始休眠,等待其他消息唤醒
__CFRunLoopSetSleeping(rl);
__CFPortSetInsert(dispatchPort, waitSet);
__CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), poll ? 0 : TIMEOUT_INFINITY);
//醒来了
__CFPortSetRemove(dispatchPort, waitSet);
__CFRunLoopUnsetSleeping(rl);
//通知Observer:已经唤醒
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
handle_msg:; //看是谁唤醒RunLoop,进行相应的处理
mach_port_t livePort = msg ? msg->msgh_local_port : MACH_PORT_NULL;
if (MACH_PORT_NULL == livePort) {
// handle nothing
} else if (livePort == rl->_wakeUpPort) {
// do nothing on Mac OS
} else if (livePort == rlm->_timerPort) { //被Timer唤醒,处理Timers事件
__CFRunLoopDoTimers(rl, rlm, mach_absolute_time());
} else if (livePort == dispatchPort) { //GCD唤醒,处理GCD async to main async 事件
_dispatch_main_queue_callback_4CF(msg);
} else { //Source1唤醒,处理Source1事件
__CFRunLoopDoSource1(rl, rlm, rls, msg, msg->msgh_size, &reply) || sourceHandledThisLoop;
//执行Blocks
__CFRunLoopDoBlocks(rl, rlm);
//根据之前的执行结果来看是否要继续循环?
if (sourceHandledThisLoop && stopAfterHandle) {
retVal = kCFRunLoopRunHandledSource;
} else if (timeout_context->termTSR < (int64_t)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;
}
SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) { /* DOES CALLOUT */
//通知Observers:进入loop
__CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
//开始执行Run
result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode);
//通知Observers:推出Loop
__CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);
return result;
}
void CFRunLoopRun(void) { /* DOES CALLOUT */
int32_t result;
do {
result = CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);
CHECK_FOR_FORK();
} while (kCFRunLoopRunStopped != result && kCFRunLoopRunFinished != result);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment