RunLoop 源码阅读

作者: cdcyd | 来源:发表于2018-05-24 15:38 被阅读29次
    1. 获取runloop的函数
    // 获取主线程的runloop
    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;
    }
    
    // 获取子线程的runloop
    CFRunLoopRef CFRunLoopGetCurrent(void) {
        CHECK_FOR_FORK();
        CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(__CFTSDKeyRunLoop);
        if (rl) return rl;
        return _CFRunLoopGet0(pthread_self());
    }
    
    1. 创建runloop的函数
    CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {
        // 判断t所指向的线程是否为空,如果为空,就获取当前的主线程进行赋值
        if (pthread_equal(t, kNilPthreadT)) {
            t = pthread_main_thread_np();
        }
        __CFLock(&loopsLock);
    
        // 全局__CFRunLoops,它是一个字典,用来存储所有线程的runloop
        if (!__CFRunLoops) {
            __CFUnlock(&loopsLock);
            CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
            // 由于主线程默认就有runloop,所以再创建__CFRunLoops,要默认添加一个主线程的runloop
            CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());
            CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);
            if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) {
                CFRelease(dict);
            }
            CFRelease(mainLoop);
            __CFLock(&loopsLock);
        }
    
        // 从__CFRunLoops中获取对应于当前线程的RunLoop
        CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
        __CFUnlock(&loopsLock);
        if (!loop) {
            // 如果没有取到,说明是第一次,则创建一个runloop加入到全局字典中
            CFRunLoopRef newLoop = __CFRunLoopCreate(t);
            __CFLock(&loopsLock);
            loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
            if (!loop) {
                // 存储当前线程和对应的RunLoop到全局字典__CFRunLoops中
                CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop);
                loop = newLoop;
            }
            __CFUnlock(&loopsLock);
            CFRelease(newLoop);
        }
    
        // 判断是否为当前线程,如果是就注册一个回调,当线程销毁时,也销毁其对应的 RunLoop
        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;
    }
    
    1. 运行runloop的函数
    void CFRunLoopRun(void) {
        // 只有运行完成或主动退出时,才会真正的退出
        int32_t result;
        do {
            result = CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);
            CHECK_FOR_FORK();
        } while (kCFRunLoopRunStopped != result && kCFRunLoopRunFinished != result);
    }
    
    SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) {  
        CHECK_FOR_FORK();
        // 判断RunLoop是否正在被销毁,已被销毁就退出原因
        if (__CFRunLoopIsDeallocating(rl)) return kCFRunLoopRunFinished;
    
        __CFRunLoopLock(rl);
    
        // 获取当前 mode
        CFRunLoopModeRef currentMode = __CFRunLoopFindMode(rl, modeName, false);
        if (NULL == currentMode || __CFRunLoopModeIsEmpty(rl, currentMode, rl->_currentMode)) {
            // 如果当前 mode 和 runloop 的 mode 都为 nil,则退出
            Boolean did = false;
            if (currentMode) __CFRunLoopModeUnlock(currentMode);
            __CFRunLoopUnlock(rl);
            return did ? kCFRunLoopRunHandledSource : kCFRunLoopRunFinished;
        }
    
        // 保存正在运行的RunLoop,把相关数据压进栈
        volatile _per_run_data *previousPerRun = __CFRunLoopPushPerRunData(rl);
        CFRunLoopModeRef previousMode = rl->_currentMode;
        rl->_currentMode = currentMode;
        int32_t result = kCFRunLoopRunFinished;
    
        // 判断是否可以运行runloop,并通知观察者Observer,即将运行RunLoop
        if (currentMode->_observerMask & kCFRunLoopEntry ) 
            __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
    
        // 运行RunLoop
        result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode);
    
        // 判断是否要退出runloop,并通知观察者Observer,即将退出RunLoop
        if (currentMode->_observerMask & kCFRunLoopExit ) 
            __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);
    
        __CFRunLoopModeUnlock(currentMode);
        __CFRunLoopPopPerRunData(rl, previousPerRun);
        rl->_currentMode = previousMode;
        __CFRunLoopUnlock(rl);
        return result;
    }
    
    /* rl, rlm are locked on entrance and exit 
       rl: runloop 
       rlm: runloop mode 
       seconds: 超时时间
       stopAfterHandle: 完成后是否停止 runloop
       previousMode: 前一次的 mode (主要因为 runloop 可以嵌套调用)
    */
    static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) {
        // 当前内核时间
        uint64_t startTSR = mach_absolute_time();
    
        // 判断本次 runloop 或 mode 状态是否已经停止了
        if (__CFRunLoopIsStopped(rl)) {
            __CFRunLoopUnsetStopped(rl);
            return kCFRunLoopRunStopped;
        } else if (rlm->_stopped) {
            rlm->_stopped = false;
            return kCFRunLoopRunStopped;
        }
        
        // 主线程消息端口
        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)));
        // 在主线程中 && 是主线程的runloop && mode类型为common
        if (libdispatchQSafe && (CFRunLoopGetMain() == rl) && CFSetContainsValue(rl->_commonModes, rlm->_name)) 
            // 获取GCD端口(4CF 表示 for Core Foundation)
            dispatchPort = _dispatch_get_main_queue_port_4CF();
        
    // 是否使用了GCD timer
    #if USE_DISPATCH_SOURCE_FOR_TIMERS
        // GCD timer 消息端口
        mach_port_name_t modeQueuePort = MACH_PORT_NULL;
        if (rlm->_queue) {
            modeQueuePort = _dispatch_runloop_root_queue_get_port_4CF(rlm->_queue);
            if (!modeQueuePort) {
                CRASH("Unable to get port for run loop mode queue (%d)", -1);
            }
        }
    #endif
        
        // 超时定时器
        dispatch_source_t timeout_timer = NULL;
        // 超时定时器的上下文
        struct __timeout_context *timeout_context = (struct __timeout_context *)malloc(sizeof(*timeout_context));
        if (seconds <= 0.0) { 
            // 如果超时时间<=0.0,立即就超时了,此时不需要定时器了
            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);
            // 设置GCD的计时器上下文为当前超时计时器的上下文
            dispatch_set_context(timeout_timer, timeout_context); 
            // 设置超时source
            dispatch_source_set_event_handler_f(timeout_timer, __CFRunLoopTimeout);
            // 设置超时取消source
            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值大概相当于317年)
            seconds = 9999999999.0;
            timeout_context->termTSR = UINT64_MAX;
        }
    
        Boolean didDispatchPortLastTime = true;
        // 函数的返回值 (return value),默认为0
        int32_t retVal = 0;
        // do {} while() 这个循环就是runloop的核心代码块
        do {
    #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
            voucher_mach_msg_state_t voucherState = VOUCHER_MACH_MSG_STATE_UNCHANGED;
            voucher_t voucherCopy = NULL;
    #endif  
    #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
            mach_msg_header_t *msg = NULL;
            mach_port_t livePort = MACH_PORT_NULL;
    #elif DEPLOYMENT_TARGET_WINDOWS
            HANDLE livePort = NULL;
            Boolean windowsMessageReceived = false;
    #endif
            // 申请一个存放消息的空间
            uint8_t msg_buffer[3 * 1024];
    
            __CFPortSet waitSet = rlm->_portSet;
    
            __CFRunLoopUnsetIgnoreWakeUps(rl);
    
            // 1.通知 observer,即将处理 timers
            if (rlm->_observerMask & kCFRunLoopBeforeTimers) 
                __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
            // 2.通知 observer,即将处理 sources
            if (rlm->_observerMask & kCFRunLoopBeforeSources) 
                __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
            
            // 3.处理 blocks
            __CFRunLoopDoBlocks(rl, rlm);
    
            // 4.处理 sources0
            Boolean sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm, stopAfterHandle);
            // 如果实际处理了 sources0,则再一次处理 blocks
            if (sourceHandledThisLoop) {
                __CFRunLoopDoBlocks(rl, rlm);
            }
            
            // 处理完 sources0 或 超时时间为0
            Boolean poll = sourceHandledThisLoop || (0ULL == timeout_context->termTSR);
          
            // 5.处理主线程中的GCD事件,循环的第一次是不会进入的,因为didDispatchPortLastTime永远是true
            if (MACH_PORT_NULL != dispatchPort && !didDispatchPortLastTime) {
    #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
                msg = (mach_msg_header_t *)msg_buffer;
                if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0, &voucherState, NULL)) {
                    goto handle_msg;
                }
    #elif DEPLOYMENT_TARGET_WINDOWS
                if (__CFRunLoopWaitForMultipleObjects(NULL, &dispatchPort, 0, 0, &livePort, NULL)) {
                    goto handle_msg;
                }
    #endif
            }
            didDispatchPortLastTime = false;
    
            // 6.没有处理完sources0 && 没有超时,通知 observer,即将进入睡眠
            if (!poll && (rlm->_observerMask & kCFRunLoopBeforeWaiting))    
                __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
            // 7.设置标志,正在睡眠 (实际runloop还没有睡眠)
            __CFRunLoopSetSleeping(rl);
            // 8.将GCD端口加入所有监听端口集合中
            __CFPortSetInsert(dispatchPort, waitSet);
            
            __CFRunLoopModeUnlock(rlm);
            __CFRunLoopUnlock(rl);
    
            // 记录睡眠开始时间
            CFAbsoluteTime sleepStart = poll ? 0.0 : CFAbsoluteTimeGetCurrent();
    
    #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
    #if USE_DISPATCH_SOURCE_FOR_TIMERS
            // 如果使用 GCD timer,获取消息后需要对GCD Timer做一些额外的处理
            do {        
                if (kCFUseCollectableAllocator) {
                    memset(msg_buffer, 0, sizeof(msg_buffer));
                }
                msg = (mach_msg_header_t *)msg_buffer;
                
                __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy);
                
                if (modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort) {
                    while (_dispatch_runloop_root_queue_perform_4CF(rlm->_queue));
                    if (rlm->_timerFired) {
                        rlm->_timerFired = false;
                        break;
                    } else {
                        if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg);
                    }
                } else {
                    break;
                }
            } while (1);
    #else
            if (kCFUseCollectableAllocator) {
                memset(msg_buffer, 0, sizeof(msg_buffer));
            }
            msg = (mach_msg_header_t *)msg_buffer;
            __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy);
    #endif
            
    #elif DEPLOYMENT_TARGET_WINDOWS
            __CFRunLoopWaitForMultipleObjects(waitSet, NULL, poll ? 0 : TIMEOUT_INFINITY, rlm->_msgQMask, &livePort, &windowsMessageReceived);
    #endif
            
            __CFRunLoopLock(rl);
            __CFRunLoopModeLock(rlm);
    
            rl->_sleepTime += (poll ? 0.0 : (CFAbsoluteTimeGetCurrent() - sleepStart));
    
            // 移除 GCD 端口
            __CFPortSetRemove(dispatchPort, waitSet);
            
            __CFRunLoopSetIgnoreWakeUps(rl);
    
            //  处理完成 GCD 后,通知 observer,即将进入睡眠
            __CFRunLoopUnsetSleeping(rl);
            if (!poll && (rlm->_observerMask & kCFRunLoopAfterWaiting)) 
                __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
    
            // 收到消息的标签
            // 1. 基于 port 的 Sources1 的事件
            // 2. Timer 到时间
            // 3. RunLoop 超时
            // 4. 被手动唤醒
            handle_msg:;
            __CFRunLoopSetIgnoreWakeUps(rl);
    
    #if DEPLOYMENT_TARGET_WINDOWS
            if (windowsMessageReceived) {
                __CFRunLoopModeUnlock(rlm);
                __CFRunLoopUnlock(rl);
    
                if (rlm->_msgPump) {
                    rlm->_msgPump();
                } else {
                    MSG msg;
                    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD)) {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                    }
                }
                
                __CFRunLoopLock(rl);
                __CFRunLoopModeLock(rlm);
                sourceHandledThisLoop = true;
                
                __CFRunLoopSetSleeping(rl);
                __CFRunLoopModeUnlock(rlm);
                __CFRunLoopUnlock(rl);
                
                __CFRunLoopWaitForMultipleObjects(waitSet, NULL, 0, 0, &livePort, NULL);
                
                __CFRunLoopLock(rl);
                __CFRunLoopModeLock(rlm);            
                __CFRunLoopUnsetSleeping(rl);
            }  
    #endif
    
            if (MACH_PORT_NULL == livePort) {
                // 不知道哪个端口唤醒的
                CFRUNLOOP_WAKEUP_FOR_NOTHING();
            } else if (livePort == rl->_wakeUpPort) {
                // 被 CFRunLoopWakeUp 函数唤醒的
                CFRUNLOOP_WAKEUP_FOR_WAKEUP();
            }
    
    #if USE_DISPATCH_SOURCE_FOR_TIMERS
            else if (modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort) {
                // 被 GCD timers 唤醒,处理 timers
                CFRUNLOOP_WAKEUP_FOR_TIMER();
                if (!__CFRunLoopDoTimers(rl, rlm, mach_absolute_time())) {
                    __CFArmNextTimerInMode(rlm, rl);
                }
            }
    #endif
    
    #if USE_MK_TIMER_TOO
            else if (rlm->_timerPort != MACH_PORT_NULL && livePort == rlm->_timerPort) {
                // 被其它 timers 唤醒,处理 timers
                CFRUNLOOP_WAKEUP_FOR_TIMER();
                if (!__CFRunLoopDoTimers(rl, rlm, mach_absolute_time())) {
                    __CFArmNextTimerInMode(rlm, rl);
                }
            }
    #endif
            else if (livePort == dispatchPort) {
                // 被主线程 GCD 唤醒,处理 GCD
                CFRUNLOOP_WAKEUP_FOR_DISPATCH();
                __CFRunLoopModeUnlock(rlm);
                __CFRunLoopUnlock(rl);
                _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)6, NULL);
    #if DEPLOYMENT_TARGET_WINDOWS
                void *msg = 0;
    #endif
                __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);
                _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)0, NULL);
                __CFRunLoopLock(rl);
                __CFRunLoopModeLock(rlm);
                sourceHandledThisLoop = true;
                didDispatchPortLastTime = true;
            } else {
                // 被 sources1 唤醒,处理 sources1
                CFRUNLOOP_WAKEUP_FOR_SOURCE();
                voucher_t previousVoucher = _CFSetTSD(__CFTSDKeyMachMessageHasVoucher, (void *)voucherCopy, os_release);
    
                CFRunLoopSourceRef rls = __CFRunLoopModeFindSourceForMachPort(rl, rlm, livePort);
                if (rls) {
    #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
                    mach_msg_header_t *reply = NULL;
                    sourceHandledThisLoop = __CFRunLoopDoSource1(rl, rlm, rls, msg, msg->msgh_size, &reply) || sourceHandledThisLoop;
                    if (NULL != reply) {
                        (void)mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
                        CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply);
                    }
    #elif DEPLOYMENT_TARGET_WINDOWS
                    sourceHandledThisLoop = __CFRunLoopDoSource1(rl, rlm, rls) || sourceHandledThisLoop;
    #endif
                }
                _CFSetTSD(__CFTSDKeyMachMessageHasVoucher, previousVoucher, os_release);
            } 
    #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
            if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg);
    #endif
    
            // 再一次处理 blocks
            __CFRunLoopDoBlocks(rl, rlm);
             
            // 判断是否退出
            if (sourceHandledThisLoop && stopAfterHandle) {
                // 处理完事件后退出
                retVal = kCFRunLoopRunHandledSource;
            } else if (timeout_context->termTSR < mach_absolute_time()) {
                // 超时退出
                retVal = kCFRunLoopRunTimedOut;
            } else if (__CFRunLoopIsStopped(rl)) {
                // 调用CFRunLoopStop()退出
                __CFRunLoopUnsetStopped(rl);
                retVal = kCFRunLoopRunStopped;
            } else if (rlm->_stopped) {
                // 运行模式被终止时退出
                rlm->_stopped = false;
                retVal = kCFRunLoopRunStopped;
            } else if (__CFRunLoopModeIsEmpty(rl, rlm, previousMode)) {
                // 没有要处理的事件时退出
                retVal = kCFRunLoopRunFinished;
            }
            
    #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
            voucher_mach_msg_revert(voucherState);
            os_release(voucherCopy);
    #endif
    
        } while (0 == retVal);
    
        if (timeout_timer) {
            dispatch_source_cancel(timeout_timer);
            dispatch_release(timeout_timer);
        } else {
            free(timeout_context);
        }
    
        return retVal;
    }
    

    Runloop 运行的核心函数__CFRunLoopRun大概有300多行代码,看似很多代码,其实其中有很多是为了适配不同平台的代码,如果我们将其删减一下,删掉那些平台的适配以及一些复杂的逻辑判断,我们就可以得到如下的runloop执行过程

    staticint32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) {
        do {
            // 1. 通知 observers,RunLoop 即将处理 Timers
            __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
            // 2. 通知 observers,RunLoop 即将处理 Sources
            __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
            // 3. 处理 sources0 事件
            __CFRunLoopDoSources0(rl, rlm, stopAfterHandle);
            // 4. 处理 blocks
            __CFRunLoopDoBlocks(rl, rlm);
            // 5. 处理 sources1 事件
            goto handle_msg;
            // 6. 通知 observers, RunLoop 即将休眠
            __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
            // 7. RunLoop 休眠
            __CFRunLoopSetSleeping(rl);
            // 8. 线程进入休眠, 直到被下面某一个事件唤醒:
            // a. 基于 port 的 Source1 的事件
            // b. Timer 到时间了
            // c. RunLoop 启动时设置的最大超时时间到了
            // d. 被手动唤醒
            // 9. 当接收到第8步中的消息时,Runloop 醒来
            __CFRunLoopUnsetSleeping(rl);
            // 10. 通知 observers,RunLoop 已被唤醒
            __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
            // 11. 处理消息
            handle_msg:;
            if(MACH_PORT_NULL == livePort) {
                CFRUNLOOP_WAKEUP_FOR_NOTHING();
            } else if(livePort == rl->_wakeUpPort) {
                CFRUNLOOP_WAKEUP_FOR_WAKEUP();
            } else if(modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort) {
                // 处理定时器事件
                CFRUNLOOP_WAKEUP_FOR_TIMER();
            } else if(livePort == dispatchPort) {
                // 处理主线程消息
                CFRUNLOOP_WAKEUP_FOR_DISPATCH();
            } else {
                // 处理 sources1
                CFRUNLOOP_WAKEUP_FOR_SOURCE();
            } 
            // 12. 退出 RunLoop
        return retVal;
    }
    

    相关文章

      网友评论

        本文标题:RunLoop 源码阅读

        本文链接:https://www.haomeiwen.com/subject/nnpjjftx.html