数据结构
__CFRunLoopMode
- struct __CFRunLoopMode {
- CFRuntimeBase _base;
- pthread_mutex_t _lock; /* must have the run loop locked before locking
- this */
- //mode名
- CFStringRef _name;
- Boolean _stopped;
- char _padding[3];
- //source0 源
- CFMutableSetRef _sources0;
- //source1 源
- CFMutableSetRef _sources1;
- //observer 源
- CFMutableArrayRef _observers;
- //timer 源
- CFMutableArrayRef _timers;
-
- //mach port 到 mode的映射,为了在runloop主逻辑中过滤runloop自己的port消息。
- CFMutableDictionaryRef _portToV1SourceMap;
-
- //记录了所有当前mode中需要监听的port,作为调用监听消息函数的参数。
- __CFPortSet _portSet;
- CFIndex _observerMask;
- #if USE_DISPATCH_SOURCE_FOR_TIMERS
- dispatch_source_t _timerSource;
- dispatch_queue_t _queue;
- Boolean _timerFired; // set to true by the source when a timer has fired
- Boolean _dispatchTimerArmed;
- #endif
- #if USE_MK_TIMER_TOO
- //使用 mk timer, 用到的mach port,和source1类似,都依赖于mach port
- mach_port_t _timerPort;
- Boolean _mkTimerArmed;
- #endif
- //timer触发的理想时间
- uint64_t _timerSoftDeadline; /* TSR */
- //timer触发的实际时间,理想时间加上tolerance(偏差)
- uint64_t _timerHardDeadline; /* TSR */
- };
- 复制代码
__CFRunLoop
- struct __CFRunLoop {
- CFRuntimeBase _base;
- pthread_mutex_t _lock; /* locked for accessing mode list */
-
- //用于手动将当前runloop线程唤醒,通过调用CFRunLoopWakeUp完成,
- //CFRunLoopWakeUp会向_wakeUpPort发送一条消息
- __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;
- //记录了当前runloop中所有的mode名
- CFMutableSetRef _commonModes;
- //记录了当前runloop中所有注册到commonMode中的源
- CFMutableSetRef _commonModeItems;
- CFRunLoopModeRef _currentMode;
- CFMutableSetRef _modes;
- //记录了添加到runloop中的block,它也可以像其他源一样被runloop处理,
- //通过CFRunLoopPerformBlock可向runloop中添加block任务。
- struct _block_item *_blocks_head;
- struct _block_item *_blocks_tail;
- CFTypeRef _counterpart;
- };
- 复制代码
__CFRunLoops
- //全局字典,保存线程和对应runloop之间的关系
- static CFMutableDictionaryRef __CFRunLoops = NULL;
- 复制代码
函数:
__CFRunLoopRun
- static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm,
- CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef
- previousMode) {
- //获取系统启动之后cpu嘀嗒数
- uint64_t startTSR = mach_absolute_time();
- if (__CFRunLoopIsStopped(rl)) {
- __CFRunLoopUnsetStopped(rl);
- return kCFRunLoopRunStopped;
- } else if (rlm->_stopped) {
- rlm->_stopped = false;
- return kCFRunLoopRunStopped;
- }
-
- //mach 端口, 线程之间通信的对象
- mach_port_name_t dispatchPort = MACH_PORT_NULL;
- //这里主要是为了判断当前线程是否为主线程
- Boolean libdispatchQSafe = pthread_main_np() && ((
- HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && NULL == previousMode) || (!
- HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && 0 == _CFGetTSD(
- __CFTSDKeyIsInGCDMainQ)));
- if (libdispatchQSafe && (CFRunLoopGetMain() == rl) && CFSetContainsValue(rl
- ->_commonModes, rlm->_name)) dispatchPort =
- _dispatch_get_main_queue_port_4CF();
-
- //使用GCD实现runloop超时功能
- dispatch_source_t timeout_timer = NULL;
- struct __timeout_context *timeout_context = (struct __timeout_context *)
- malloc(sizeof(*timeout_context));
- //seconds是设置的runloop超时时间
- if (seconds <= 0.0) { // instant timeout
- seconds = 0.0;
- timeout_context->termTSR = 0ULL;
- } else if (seconds <= TIMER_INTERVAL_LIMIT) {
- dispatch_queue_t queue = dispatch_get_global_queue(
- DISPATCH_QUEUE_PRIORITY_HIGH, DISPATCH_QUEUE_OVERCOMMIT);
- 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 { // infinite timeout
- seconds = 9999999999.0;
- timeout_context->termTSR = UINT64_MAX;
- }
- Boolean didDispatchPortLastTime = true;
- int32_t retVal = 0;
- do {
- uint8_t msg_buffer[3 * 1024];
- mach_msg_header_t *msg = NULL;
- mach_port_t livePort = MACH_PORT_NULL;
- __CFPortSet waitSet = rlm->_portSet;
- __CFRunLoopUnsetIgnoreWakeUps(rl);
- //rl->_perRunData->ignoreWakeUps = 0x0;
- if (rlm->_observerMask & kCFRunLoopBeforeTimers) __CFRunLoopDoObservers
- (rl, rlm, kCFRunLoopBeforeTimers);
- if (rlm->_observerMask & kCFRunLoopBeforeSources)
- __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
- //Perform blocks queued by CFRunLoopPerformBlock;
- __CFRunLoopDoBlocks(rl, rlm);
- Boolean sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm,
- stopAfterHandle);
- //如果rl中有source0消息
- if (sourceHandledThisLoop) {
- //处理block Perform blocks newly queued by CFRunLoopPerformBlock;
- __CFRunLoopDoBlocks(rl, rlm);
- }
- //poll标志着有没有处理source0的消息,如果没有则为false,反之为true
- Boolean poll = sourceHandledThisLoop || (0ULL == timeout_context->
- termTSR);
- //第一次进来不走这个逻辑,didDispatchPortLastTime是true
- if (MACH_PORT_NULL != dispatchPort && !didDispatchPortLastTime) {
- msg = (mach_msg_header_t *)msg_buffer;
- //__CFRunLoopServiceMachPort用于接受指定端口(一个也可以是多个)
- //的消息,最后一个参数代表当端口无消息的时候是否休眠,0是立刻返回不休眠,
- //TIMEOUT_INFINITY代表休眠
- //处理通过GCD派发到主线程的任务,这些任务优先级最高会被最先处理
- if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(
- msg_buffer), &livePort, 0)) {
- goto handle_msg;
- }
- }
- didDispatchPortLastTime = false;
- //根据之前有没有处理过source0消息,来判断如果也没有source1消息的时候是否让线程进入睡眠,这里处
- //理observer源,如果睡眠则通知Observer进入睡眠。
- if (!poll && (rlm->_observerMask & kCFRunLoopBeforeWaiting))
- __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
- __CFRunLoopSetSleeping(rl);
- // do not do any user callouts after this point (after notifying of
- //sleeping)
- // Must push the local-to-this-activation ports in on every loop
- // iteration, as this mode could be run re-entrantly and we don't
- // want these ports to get serviced.
- __CFPortSetInsert(dispatchPort, waitSet);
-
- __CFRunLoopModeUnlock(rlm);
- __CFRunLoopUnlock(rl);
- if (kCFUseCollectableAllocator) {
- objc_clear_stack(0);
- memset(msg_buffer, 0, sizeof(msg_buffer));
- }
- msg = (mach_msg_header_t *)msg_buffer;
- //如果poll为null,且waitset中无port有消息,线程进入休眠
- __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort,
- poll ? 0 : TIMEOUT_INFINITY);
-
- __CFRunLoopLock(rl);
- __CFRunLoopModeLock(rlm);
- // Must remove the local-to-this-activation ports in on every loop
- // iteration, as this mode could be run re-entrantly and we don't
- // want these ports to get serviced. Also, we don't want them left
- // in there if this function returns.
- __CFPortSetRemove(dispatchPort, waitSet);
-
- __CFRunLoopSetIgnoreWakeUps(rl);
- // user callouts now OK again
- __CFRunLoopUnsetSleeping(rl);
- //处理observer源,线程醒来
- if (!poll && (rlm->_observerMask & kCFRunLoopAfterWaiting))
- __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
- handle_msg:;
- __CFRunLoopSetIgnoreWakeUps(rl);
- if (MACH_PORT_NULL == livePort) {
- CFRUNLOOP_WAKEUP_FOR_NOTHING();
- // handle nothing
- //通过CFRunloopWake将当前线程唤醒
- } else if (livePort == rl->_wakeUpPort) {
- CFRUNLOOP_WAKEUP_FOR_WAKEUP();
- // do nothing on Mac OS
- }
- //处理timer源
- else if (rlm->_timerPort != MACH_PORT_NULL && livePort == rlm->
- _timerPort) {
- CFRUNLOOP_WAKEUP_FOR_TIMER();
- if (!__CFRunLoopDoTimers(rl, rlm, mach_absolute_time())) {
- // Re-arm the next timer
- __CFArmNextTimerInMode(rlm, rl);
- }
- }
- //通过GCD派发给主线程的任务
- else if (livePort == dispatchPort) {
- CFRUNLOOP_WAKEUP_FOR_DISPATCH();
- __CFRunLoopModeUnlock(rlm);
- __CFRunLoopUnlock(rl);
- _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)6, NULL);
- __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);
- _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)0, NULL);
- __CFRunLoopLock(rl);
- __CFRunLoopModeLock(rlm);
- sourceHandledThisLoop = true;
- didDispatchPortLastTime = true;
- } else {
- //通过macPort给当前线程派发消息,处理source1
- CFRUNLOOP_WAKEUP_FOR_SOURCE();
- // Despite the name, this works for windows handles as well
- //过滤macPort消息,有一些消息不一定是runloop中注册的,这里只处理runloop中注册的
- //消息,在rlm->_portToV1SourceMap通过macPort找有没有对应的runloopMode
- CFRunLoopSourceRef rls = __CFRunLoopModeFindSourceForMachPort(rl,
- rlm, livePort);
- if (rls) {
- mach_msg_header_t *reply = NULL;
- sourceHandledThisLoop = __CFRunLoopDoSource1(rl, rlm, rls, msg,
- msg->msgh_size, &reply) || sourceHandledThisLoop;
- if (NULL != reply) {
- //当前线程处理完source1,给发消息的线程反馈消息,
- //MACH_SEND_MSG表示给replay端口发送消息
- (void)mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0,
- MACH_PORT_NULL, 0, MACH_PORT_NULL);
- CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply);
- }
- }
- }
- if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg);
-
- __CFRunLoopDoBlocks(rl, rlm);
- if (sourceHandledThisLoop && stopAfterHandle) {
- retVal = kCFRunLoopRunHandledSource;
- } else if (timeout_context->termTSR < mach_absolute_time()) {
- //runloop超时时间到
- 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);
- if (timeout_timer) {
- dispatch_source_cancel(timeout_timer);
- dispatch_release(timeout_timer);
- } else {
- free(timeout_context);
- }
- return retVal;
- }
- 复制代码
CFRunLoopAddSource
- void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef rls,
- CFStringRef modeName) { /* DOES CALLOUT */
- CHECK_FOR_FORK();
- if (__CFRunLoopIsDeallocating(rl)) return;
- if (!__CFIsValid(rls)) return;
- Boolean doVer0Callout = false;
- __CFRunLoopLock(rl);
- if (modeName == kCFRunLoopCommonModes) {
- //par1 : 处理commonModeItmes的逻辑
- /*rl->_commonModes的作用是记录了当前runloop中标记为commonMode的mode,rl->_commonModeI
- tems记录了当前runloop中注册到commonMode中的源
- 两者用来处理跟commonMode相关的逻辑,比如当一个mode被标记为commonMode的时候,会将rl->_common
- ModeItems中的源添加到新的mode当中去,在当前mode下这些源的消息就会被
- 监听并处理。例如一个timer被注册到commonMode中,那么在所有被标记为commonMode的mode中都会处理该timer的消息。
- */
- CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault
- , rl->_commonModes) : NULL;
- if (NULL == rl->_commonModeItems) {
- rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
- }
- CFSetAddValue(rl->_commonModeItems, rls);
- if (NULL != set) {
- CFTypeRef context[2] = {rl, rls};
- /* add new item to all common-modes */
- //对每一个mode,调用part2的逻辑
- CFSetApplyFunction(set, (__CFRunLoopAddItemToCommonModes), (void *)context);
- CFRelease(set);
- }
- } else {
- //part2 : 处理某个具体的mode中addSource的逻辑
- CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, true);
- if (NULL != rlm && NULL == rlm->_sources0) {
- rlm->_sources0 = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &
- kCFTypeSetCallBacks);
- rlm->_sources1 = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &
- kCFTypeSetCallBacks);
- rlm->_portToV1SourceMap = CFDictionaryCreateMutable(
- kCFAllocatorSystemDefault, 0, NULL, NULL);
- }
- if (NULL != rlm && !CFSetContainsValue(rlm->_sources0, rls) && !
- CFSetContainsValue(rlm->_sources1, rls)) {
- if (0 == rls->_context.version0.version) {
- CFSetAddValue(rlm->_sources0, rls);
- } else if (1 == rls->_context.version0.version) {
- CFSetAddValue(rlm->_sources1, rls);
- __CFPort src_port = rls->_context.version1.getPort(rls->_context.
- version1.info);
- if (CFPORT_NULL != src_port) {
- //rlm->_portToV1SourceMap是port到source1的映射,
- //为了在runloop主逻辑中过滤runloop自己的port消息。
- CFDictionarySetValue(rlm->_portToV1SourceMap, (const void *)(
- uintptr_t)src_port, rls);
- //rml->_portSet记录了所有当前mode中需要监听的port,作为调用监听消息函数的参数。
- __CFPortSetInsert(src_port, rlm->_portSet);
- }
- }
- __CFRunLoopSourceLock(rls);
- if (NULL == rls->_runLoops) {
- rls->_runLoops = CFBagCreateMutable(kCFAllocatorSystemDefault, 0, &
- kCFTypeBagCallBacks); // sources retain run loops!
- }
- CFBagAddValue(rls->_runLoops, rl);
- __CFRunLoopSourceUnlock(rls);
- if (0 == rls->_context.version0.version) {
- if (NULL != rls->_context.version0.schedule) {
- doVer0Callout = true;
- }
- }
- }
- if (NULL != rlm) {
- __CFRunLoopModeUnlock(rlm);
- }
- }
- __CFRunLoopUnlock(rl);
- if (doVer0Callout) {
- // although it looses some protection for the source, we have no
- //choice but
- // to do this after unlocking the run loop and mode locks, to avoid
- //deadlocks
- // where the source wants to take a lock which is already held in
- //another
- // thread which is itself waiting for a run loop/mode lock
- rls->_context.version0.schedule(rls->_context.version0.info, rl, modeName); /* CALLOUT */
- }
- }
- 复制代码
CFRunLoopRemoveSource
- void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef rls,
- CFStringRef modeName) { /* DOES CALLOUT */
- CHECK_FOR_FORK();
- Boolean doVer0Callout = false, doRLSRelease = false;
- __CFRunLoopLock(rl);
- if (modeName == kCFRunLoopCommonModes) {
- if (NULL != rl->_commonModeItems && CFSetContainsValue(rl->
- _commonModeItems, rls)) {
- CFSetRef set = rl->_commonModes ? CFSetCreateCopy(
- kCFAllocatorSystemDefault, rl->_commonModes) : NULL;
- CFSetRemoveValue(rl->_commonModeItems, rls);
- if (NULL != set) {
- CFTypeRef context[2] = {rl, rls};
- /* remove new item from all common-modes */
- CFSetApplyFunction(set, (__CFRunLoopRemoveItemFromCommonModes), (
- void *)context);
- CFRelease(set);
- }
- }
- } else {
- CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, false);
- if (NULL != rlm && ((NULL != rlm->_sources0 && CFSetContainsValue(rlm->
- _sources0, rls)) || (NULL != rlm->_sources1 && CFSetContainsValue(rlm->
- _sources1, rls)))) {
- //source0或者source1中的一种
- CFRetain(rls);
- if (1 == rls->_context.version0.version) {
- __CFPort src_port = rls->_context.version1.getPort(rls->_context.
- version1.info);
- if (CFPORT_NULL != src_port) {
- CFDictionaryRemoveValue(rlm->_portToV1SourceMap, (const void *)(
- uintptr_t)src_port);
- __CFPortSetRemove(src_port, rlm->_portSet);
- }
- }
- CFSetRemoveValue(rlm->_sources0, rls);
- CFSetRemoveValue(rlm->_sources1, rls);
- __CFRunLoopSourceLock(rls);
- if (NULL != rls->_runLoops) {
- CFBagRemoveValue(rls->_runLoops, rl);
- }
- __CFRunLoopSourceUnlock(rls);
- if (0 == rls->_context.version0.version) {
- if (NULL != rls->_context.version0.cancel) {
- doVer0Callout = true;
- }
- }
- doRLSRelease = true;
- }
- if (NULL != rlm) {
- __CFRunLoopModeUnlock(rlm);
- }
- }
- __CFRunLoopUnlock(rl);
- if (doVer0Callout) {
- // although it looses some protection for the source, we have no choice but
- // to do this after unlocking the run loop and mode locks, to avoid deadlocks
- // where the source wants to take a lock which is already held in another
- // thread which is itself waiting for a run loop/mode lock
- rls->_context.version0.cancel(rls->_context.version0.info, rl, modeName); /* CALLOUT */
- }
- if (doRLSRelease) CFRelease(rls);
- }
- 复制代码
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) {
- CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault
- , rl->_commonModes) : NULL;
- if (NULL == rl->_commonModeItems) {
- rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0,
- &kCFTypeSetCallBacks);
- }
- CFSetAddValue(rl->_commonModeItems, rlt);
- if (NULL != set) {
- CFTypeRef context[2] = {rl, rlt};
- /* add new item to all common-modes */
- CFSetApplyFunction(set, (__CFRunLoopAddItemToCommonModes), (void *)
- context);
- CFRelease(set);
- }
- } else {
- 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是添加或者删除timer,
- //这里是往rlm->_timers添加timer
- __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);
- }
- 复制代码
__CFRunLoopFindMode
- static CFRunLoopModeRef __CFRunLoopFindMode(CFRunLoopRef rl, CFStringRef
- modeName, Boolean create) {
- CHECK_FOR_FORK();
- CFRunLoopModeRef rlm;
- struct __CFRunLoopMode srlm;
- memset(&srlm, 0, sizeof(srlm));
- _CFRuntimeSetInstanceTypeIDAndIsa(&srlm, __kCFRunLoopModeTypeID);
- srlm._name = modeName;
- rlm = (CFRunLoopModeRef)CFSetGetValue(rl->_modes, &srlm);
- if (NULL != rlm) {
- __CFRunLoopModeLock(rlm);
- return rlm;
- }
- if (!create) {
- return NULL;
- }
- rlm = (CFRunLoopModeRef)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault,
- __kCFRunLoopModeTypeID, sizeof(struct __CFRunLoopMode) - sizeof(
- CFRuntimeBase), NULL);
- if (NULL == rlm) {
- return NULL;
- }
- __CFRunLoopLockInit(&rlm->_lock);
- rlm->_name = CFStringCreateCopy(kCFAllocatorSystemDefault, modeName);
- rlm->_stopped = false;
- rlm->_portToV1SourceMap = NULL;
- rlm->_sources0 = NULL;
- rlm->_sources1 = NULL;
- rlm->_observers = NULL;
- rlm->_timers = NULL;
- rlm->_observerMask = 0;
- rlm->_portSet = __CFPortSetAllocate();
- rlm->_timerSoftDeadline = UINT64_MAX;
- rlm->_timerHardDeadline = UINT64_MAX;
-
- kern_return_t ret = KERN_SUCCESS;
- //1
- #if USE_DISPATCH_SOURCE_FOR_TIMERS
- rlm->_timerFired = false;
- rlm->_queue = _dispatch_runloop_root_queue_create_4CF("Run Loop Mode Queue"
- , 0);
- mach_port_t queuePort = _dispatch_runloop_root_queue_get_port_4CF(rlm->
- _queue);
- if (queuePort == MACH_PORT_NULL) CRASH("*** Unable to create run loop mode
- queue port. (%d) ***", -1);
- rlm->_timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0
- , rlm->_queue);
-
- __block Boolean *timerFiredPointer = &(rlm->_timerFired);
- dispatch_source_set_event_handler(rlm->_timerSource, ^{
- *timerFiredPointer = true;
- });
-
- // Set timer to far out there. The unique leeway makes this timer easy to spot in debug output.
- _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource,
- DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 321);
- dispatch_resume(rlm->_timerSource);
-
- ret = __CFPortSetInsert(queuePort, rlm->_portSet);
- if (KERN_SUCCESS != ret) CRASH("*** Unable to insert timer port into port
- set. (%d) ***", ret);
-
- #endif
- //1
- #if USE_MK_TIMER_TOO
- rlm->_timerPort = mk_timer_create();
- ret = __CFPortSetInsert(rlm->_timerPort, rlm->_portSet);
- if (KERN_SUCCESS != ret) CRASH("*** Unable to insert timer port into port
- set. (%d) ***", ret);
- #endif
-
- ret = __CFPortSetInsert(rl->_wakeUpPort, rlm->_portSet);
- if (KERN_SUCCESS != ret) CRASH("*** Unable to insert wake up port into
- port set. (%d) ***", ret);
-
- CFSetAddValue(rl->_modes, rlm);
- CFRelease(rlm);
- __CFRunLoopModeLock(rlm); /* return mode locked */
- return rlm;
- } ``return` `rlm;``}`
- 复制代码
__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);
- //timer开始计时
- CFArrayInsertValueAtIndex(timerArray, newIdx, rlt);
- __CFArmNextTimerInMode(rlm, rlt->_runLoop);
- if (isInArray) CFRelease(rlt);
- }
- 复制代码
__CFArmNextTimerInMode
- static void __CFArmNextTimerInMode(CFRunLoopModeRef rlm, CFRunLoopRef rl) {
- uint64_t nextHardDeadline = UINT64_MAX;
- uint64_t nextSoftDeadline = UINT64_MAX;
- if (rlm->_timers) {
- // Look at the list of timers. We will calculate two TSR values; the
- //next soft and next hard deadline.
- // The next soft deadline is the first time we can fire any timer.
- //This is the fire date of the first timer in our sorted list of timers.
- // The next hard deadline is the last time at which we can fire the
- //timer before we've moved out of the allowable tolerance of the timers in our list.
- for (CFIndex idx = 0, cnt = CFArrayGetCount(rlm->_timers); idx < cnt;
- idx++) {
- CFRunLoopTimerRef t = (CFRunLoopTimerRef)CFArrayGetValueAtIndex(rlm
- ->_timers , idx);
- // discount timers currently firing
- if (__CFRunLoopTimerIsFiring(t)) continue;
-
- int32_t err = CHECKINT_NO_ERROR;
- uint64_t oneTimerSoftDeadline = t->_fireTSR;
- uint64_t oneTimerHardDeadline = check_uint64_add(t->_fireTSR,
- __CFTimeIntervalToTSR(t->_tolerance), &err);
- if (err != CHECKINT_NO_ERROR) oneTimerHardDeadline = UINT64_MAX;
-
- // We can stop searching if the soft deadline for this timer exceeds the current hard deadline. Otherwise, later timers with lower tolerance could still have earlier hard deadlines.
- if (oneTimerSoftDeadline > nextHardDeadline) {
- break;
- }
-
- if (oneTimerSoftDeadline < nextSoftDeadline) {
- nextSoftDeadline = oneTimerSoftDeadline;
- }
-
- if (oneTimerHardDeadline < nextHardDeadline) {
- nextHardDeadline = oneTimerHardDeadline;
- }
- }
-
- if (nextSoftDeadline < UINT64_MAX && (nextHardDeadline != rlm->
- _timerHardDeadline || nextSoftDeadline != rlm->_timerSoftDeadline)) {
- if (CFRUNLOOP_NEXT_TIMER_ARMED_ENABLED()) {
- CFRUNLOOP_NEXT_TIMER_ARMED((unsigned long)(nextSoftDeadline -
- mach_absolute_time()));
- }
- #if USE_DISPATCH_SOURCE_FOR_TIMERS
- // We're going to hand off the range of allowable timer fire date
- //to dispatch and let it fire when appropriate for the system.
- uint64_t leeway = __CFTSRToNanoseconds(nextHardDeadline -
- nextSoftDeadline);
- dispatch_time_t deadline = __CFTSRToDispatchTime(nextSoftDeadline);
- #if USE_MK_TIMER_TOO
- //leeway表示timer的偏差,如果_tolerance(>=0)为0,则leeway等于0
- if (leeway > 0) {
- //GCD timer
- // Only use the dispatch timer if we have any leeway
- // <rdar://problem/14447675>
-
- // Cancel the mk timer
- if (rlm->_mkTimerArmed && rlm->_timerPort) {
- AbsoluteTime dummy;
- mk_timer_cancel(rlm->_timerPort, &dummy);
- rlm->_mkTimerArmed = false;
- }
-
- // Arm the dispatch timer
- _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource,
- deadline, DISPATCH_TIME_FOREVER, leeway);
- rlm->_dispatchTimerArmed = true;
- } else {
- //mk timer,实际中是这种情况
- // Cancel the dispatch timer
- if (rlm->_dispatchTimerArmed) {
- // Cancel the dispatch timer
- _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource,
- DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 888);
- rlm->_dispatchTimerArmed = false;
- }
-
- // Arm the mk timer
- if (rlm->_timerPort) {
- //timer开始运行
- mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(
- nextSoftDeadline));
- rlm->_mkTimerArmed = true;
- }
- }
- #else
- _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, deadline,
- DISPATCH_TIME_FOREVER, leeway);
- #endif
- #else
- if (rlm->_timerPort) {
- mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(
- nextSoftDeadline));
- }
- #endif
- } else if (nextSoftDeadline == UINT64_MAX) {
- // Disarm the timers - there is no timer scheduled
-
- if (rlm->_mkTimerArmed && rlm->_timerPort) {
- AbsoluteTime dummy;
- mk_timer_cancel(rlm->_timerPort, &dummy);
- rlm->_mkTimerArmed = false;
- }
-
- #if USE_DISPATCH_SOURCE_FOR_TIMERS
- if (rlm->_dispatchTimerArmed) {
- _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource,
- DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 333);
- rlm->_dispatchTimerArmed = false;
- }
- #endif
- }
- }
- rlm->_timerHardDeadline = nextHardDeadline;
- rlm->_timerSoftDeadline = nextSoftDeadline;
- }
- 复制代码
_CFRunLoopGet0
- CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {
- //判断t是否是传的空,如果是当成主线程处理
- if (pthread_equal(t, kNilPthreadT)) {
- t = pthread_main_thread_np();
- }
- __CFSpinLock(&loopsLock);
- //__CFRunLoops是全局存储线程和runloop关系的字典
- if (!__CFRunLoops) {
- //__CFRunLoop第一次初始化
- __CFSpinUnlock(&loopsLock);
- //初始化__CFRunLoop
- CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
- kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
- //生成主线程对应runloop
- CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());
- //存储到__CFRunLoop字典中
- CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);
- if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&
- __CFRunLoops)) {
- CFRelease(dict);
- }
- CFRelease(mainLoop);
- __CFSpinLock(&loopsLock);
- }
- //找到线程t对应的runloop
- CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops,
- pthreadPointer(t));
- __CFSpinUnlock(&loopsLock);
- if (!loop) {
- //没有找到,创建一个
- CFRunLoopRef newLoop = __CFRunLoopCreate(t);
- __CFSpinLock(&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 --> -->
- __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;
- }
- 复制代码