iOS底层原理探索-----Runloop
简述
Runloop
是一个事件处理循环,属于线程相关基础架构的一部分。它用来安排工作,并协调接收传入的事件。
Runloop
是一个do..while
循环,和普通循环的区别,在有工作的时候让线程保持忙碌,没有工作时让线程休眠。
Runloop
作用:
-
保持程序的持续运行;
-
处理
App
中的各种事件(触摸、定时器、performSelector
); -
节省
CPU
资源,该做事就做事,该休息就休息。
Runloop
循环
Runloop
在底层的封装为CFRunloop
,代码如下:
void CFRunLoopRun(void) {
/* DOES CALLOUT */ int32_t result;
do {
// 1.0e10 : 科学计数 1*10^10
result = CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);
CHECK_FOR_FORK();
} while (kCFRunLoopRunStopped != result && kCFRunLoopRunFinished != result);
}
与线程的关系
获取Runloop
的两种方式:
// 主运行循环
CFRunLoopRef mainRunloop = CFRunLoopGetMain();
// 当前运行循环
CFRunLoopRef currentRunloop = 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;
}
- 调用
_CFRunLoopGet0
函数,通过主线程查找。
当前运行循环
进入CFRunLoopGetCurrent
函数:
CFRunLoopRef CFRunLoopGetCurrent(void) {
CHECK_FOR_FORK();
//优先TSD中查找
CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(__CFTSDKeyRunLoop);
if (rl) return rl;
//通过当前线程查找
return _CFRunLoopGet0(pthread_self());
}
-
优先
TSD
中查找; -
调用
_CFRunLoopGet0
函数,通过当前线程查找。
_CFRunLoopGet0
进入_CFRunLoopGet0
函数:
CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {
if (pthread_equal(t, kNilPthreadT)) {
//不存在,默认为主线程
t = pthread_main_thread_np();
}
__CFSpinLock(&loopsLock);
if (!__CFRunLoops) {
__CFSpinUnlock(&loopsLock);
//创建全局字典,标记为kCFAllocatorSystemDefault
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
//通过主线程 创建主运行循环
CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());
// dict : key value
//利用dict,进行key-value绑定操作,线程和Runloop是一一对应的
CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);
if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) {
CFRelease(dict);
}
CFRelease(mainLoop);
__CFSpinLock(&loopsLock);
}
//通过其他线程获取Runloop
CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
__CFSpinUnlock(&loopsLock);
if (!loop) {
//如果没有获取到,创建一个Runloop
CFRunLoopRef newLoop = __CFRunLoopCreate(t);
__CFSpinLock(&loopsLock);
loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
if (!loop) {
//与线程进行key-value绑定
CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop); loop = newLoop;
}
// don't release run loops inside the loopsLock, because CFRunLoopDeallocate may end up taking it
__CFSpinUnlock(&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
对象在第一次获取RunLoop
时创建,销毁则是在线程结束的时候; -
主线程的
RunLoop
对象由系统自动创建,而子线程的RunLoop
对象需要开发者主动创建; -
RunLoop
并不保证线程安全; -
当前线程内部不能操作其他线程的
RunLoop
对象。
结构
进入__CFRunLoopCreate
函数:
static CFRunLoopRef __CFRunLoopCreate(pthread_t t) {
CFRunLoopRef loop = NULL;
CFRunLoopModeRef rlm;
uint32_t size = sizeof(struct __CFRunLoop) - sizeof(CFRuntimeBase);
loop = (CFRunLoopRef)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault, __kCFRunLoopTypeID, size, NULL);
if (NULL == loop) {
return NULL;
}
(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;
}
- 创建
RunLoop
,返回CFRunLoopRef
类型。 找到CFRunLoopRef
的定义:
typedef struct __CFRunLoop * CFRunLoopRef;
RunLoop
也是一个对象,本质是__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;
CFTypeRef _counterpart;
};
_commonModes
和_commonModeItems
都是集合类型,表示在Runloop
中可能会对应多个。
Modes
获取Runloop
下的所有Modes
:
CFRunLoopRef lp = CFRunLoopGetCurrent();
CFArrayRef modeArray= CFRunLoopCopyAllModes(lp);
NSLog(@"modeArray == %@",modeArray);
打印输出结果:
modeArray == (
UITrackingRunLoopMode,
GSEventReceiveRunLoopMode,
kCFRunLoopDefaultMode
)
- 一个
RunLoop
对应多个Modes
。
创建一个NSTimer
,将其加入Runloop
并运行:
NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
NSLog(@"fire in home -- %@",[[NSRunLoop currentRunLoop] currentMode]);
}];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
- 添加到
RunLoop
中,必须指定Mode
,这证明Timer
的运行依赖于RunLoop
的Mode
。
然后再次获取当前Runloop
正在运行的Mode
:
CFRunLoopRef lp = CFRunLoopGetCurrent();
CFRunLoopMode mode = CFRunLoopCopyCurrentMode(lp);
NSLog(@"mode == %@",mode);
打印输出结果:
mode == kCFRunLoopDefaultMode
Mode
类型:
-
NSDefaultRunLoopMode
:默认的Mode
,正常情况下都在该Mode
下; -
NSConnectionReplyMode
:将此模式与NSConnection
对象结合使用来监视回复; -
NSModalPanelRunLoopMode
:使用这种模式来识别用于模态面板的事件; -
NSEventTrackingRunLoopMode
:使用该Mode
跟踪来自用户交互的事件,例如:UITableView
上下滑动; -
NSRunLoopCommonModes
:伪模式,该集合默认包括默认、模态和事件跟踪模式。
在官方文档中,共提及以上五种Mode
类型。而iOS
中,只公开暴露了NSDefaultRunLoopMode
和NSRunLoopCommonModes
两种。
而NSRunLoopCommonModes
是伪模式,本质是Mode
的集合,包含NSDefaultRunLoopMode
、NSModalPanelRunLoopMode
、NSEventTrackingRunLoopMode
。
Mode
主要是用于指定RunLoop
中事件优先级。
Items
除了Timer
之外,我们还可以指定其他事务指定它在CFRunLoopDefaultMode
下执行,所有一个Mode
对应多个Items
。
Source
、Timer
、Observer
统称Item
。
Runloop
可处理以下事务类型:
-
Block
应用:__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__
; 如图: -
调用
timer
:__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__
。 如代码:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gotNotification:) name:@"helloMyNotification" object:nil];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[[NSNotificationCenter defaultCenter] postNotificationName:@"helloMyNotification" object:@"cooci"];
}
- (void)gotNotification:(NSNotification *)noti{
// __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__
NSLog(@"gotNotification = %@",noti);
}
Source
Source
表示可以唤醒RunLoop
的一些事件,例如:用户点击屏幕,就会创建一个RunLoop
,主要分为Source0
和Source1
;
-
Source0
:表示非系统事件,即用户自定义的事件; -
Source1
:表示系统事件,主要负责底层的通讯,具备唤醒能力。
Timer
常用NSTimer
定时器。
Observer
Observer
主要用于监听RunLoop
的状态变化,并作出一定响应。
源码中Observer
的定义:
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
//进入
kCFRunLoopEntry = (1UL << 0),
//即将处理Timers
kCFRunLoopBeforeTimers = (1UL << 1),
//即将处理Sources
kCFRunLoopBeforeSources = (1UL << 2),
//进入休眠
kCFRunLoopBeforeWaiting = (1UL << 5),
//被唤醒
kCFRunLoopAfterWaiting = (1UL << 6),
//退出
kCFRunLoopExit = (1UL << 7),
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
Runloop
结构图
线程与RunLoop
一对一:
一个RunLoop
对应多个Modes
,一个Mode
对应多个Items
。
Source
、Timer
、Observer
统称Item
。
事务处理
Timer
示例
创建CFRunLoopTimer
,将其加入到Runloop
并执行:
- (void)cfTimerDemo {
CFRunLoopTimerContext context = {
0,
((__bridge void *)self),
NULL,
NULL,
NULL
};
CFRunLoopRef rlp = CFRunLoopGetCurrent();
/**
参数一:用于分配对象的内存
参数二:在什么是触发 (距离现在)
参数三:每隔多少时间触发一次
参数四:未来参数
参数五:CFRunLoopObserver的优先级 当在Runloop同一运行阶段中有多个CFRunLoopObserver 正常情况下使用0
参数六:回调,比如触发事件,我就会来到这里
参数七:上下文记录信息
*/
CFRunLoopTimerRef timerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, 0, 1, 0, 0, lgRunLoopTimerCallBack, &context);
CFRunLoopAddTimer(rlp, timerRef, kCFRunLoopDefaultMode);
}
void lgRunLoopTimerCallBack(CFRunLoopTimerRef timer, void *info){
NSLog(@"%@---%@",timer,info);
}
进入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);
//匹配kCFRunLoopCommonModes,伪模式,集合类型
if (modeName == kCFRunLoopCommonModes) {
//获取集合
CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault, rl->_commonModes) : NULL;
//获取RunLoop下的事务
if (NULL == rl->_commonModeItems) {
//为空需要重新创建
rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
}
//将传入的CFRunLoopTimer参数,加入到Items
CFSetAddValue(rl->_commonModeItems, rlt);
//集合不为空
if (NULL != set) {
CFTypeRef context[2] = {rl, rlt};
/* add new item to all common-modes */
//设置回调函数,添加到common-modes中
CFSetApplyFunction(set, (__CFRunLoopAddItemToCommonModes), (void *)context); CFRelease(set);
}
} else {
//如果是其他类型,通过名字寻址Mode
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;
}
//如果匹配,将Runloop加进去,执行依赖于runloop run
CFSetAddValue(rlt->_rlModes, rlm->_name);
__CFRunLoopTimerUnlock(rlt);
__CFRunLoopTimerFireTSRLock();
__CFRepositionTimerInMode(rlm, rlt, false);
__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);
}
在CFRunLoopAddTimer
源码中,没有找到执行事务的函数:
- 所以,真正事务的执行,依赖于
runloop run
。
__CFRunLoopRun
进入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);
}
-
通过
CFRunLoopRunSpecific
函数,得到result
结果; -
1.0e10
:科学计数法,1 * 10 ^ 10
。
进入CFRunLoopRunSpecific
函数:
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);
//如果没找到 || mode中没有注册任何事件,则就此停止,不进入循环
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);
//取上一次运行的mode
CFRunLoopModeRef previousMode = rl->_currentMode;
//如果本次mode和上次的mode一致
rl->_currentMode = currentMode;
//初始化一个result为kCFRunLoopRunFinished
int32_t result = kCFRunLoopRunFinished;
if (currentMode->_observerMask & kCFRunLoopEntry )
/// 1. 通知 Observers: RunLoop 即将进入 loop。
__CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode);
if (currentMode->_observerMask & kCFRunLoopExit )
/// 10. 通知 Observers: RunLoop 即将退出。
__CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);
__CFRunLoopModeUnlock(currentMode);
__CFRunLoopPopPerRunData(rl, previousPerRun);
rl->_currentMode = previousMode;
__CFRunLoopUnlock(rl);
return result;
}
- 在进入和退出之间,调用
__CFRunLoopRun
函数。
进入__CFRunLoopRun
函数:
- 每一种类型都有特定的处理函数调用。
__CFRunLoopDoTimer
进入__CFRunLoopDoTimers
函数:
static Boolean __CFRunLoopDoTimers(CFRunLoopRef rl, CFRunLoopModeRef rlm, uint64_t limitTSR) {
/* DOES CALLOUT */
Boolean timerHandled = false;
CFMutableArrayRef timers = NULL;
//程序中正在运行的timer可能不止一个
for (CFIndex idx = 0, cnt = rlm->_timers ? CFArrayGetCount(rlm->_timers) : 0; idx < cnt; idx++) {
//遍历timer,从Mode中获取
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);
//执行timer
Boolean did = __CFRunLoopDoTimer(rl, rlm, rlt);
timerHandled = timerHandled || did;
}
if (timers) CFRelease(timers);
return timerHandled;
}
进入__CFRunLoopDoTimer
函数:
timer
的回调。
处理流程
-
通过
CFRunLoopAddTimer
将timer
加入到指定Mode
中; -
事务的执行依赖于
runloop run
:- 调用
CFRunLoopRun
→CFRunLoopRunSpecific
函数,在Runloop
进入和离开之间,调用__CFRunLoopRun
函数。
- 调用
-
__CFRunLoopRun
中,包含对Observers
、Source0
、Source1
、Timer
的逻辑处理:-
针对
timer
的处理,调用__CFRunLoopDoTimers
,遍历当前正在运行的timer
; -
针对单个
timer
,调用__CFRunLoopDoTimer
函数,执行事务的处理。
-
Runloop
事务处理的流程图:
底层原理
CFRunLoopRunSpecific
中的核心代码:
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;
}
__CFRunLoopRun
中的核心代码:
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;
}
流程图:
转载自:https://juejin.cn/post/7008081207896309768