美文网首页
RunLoop简易执行流程

RunLoop简易执行流程

作者: Code_人生 | 来源:发表于2019-09-30 14:02 被阅读0次

    RunLoop 执行流程


    1、通知 Observer: kCFRunLoopEntry,即将进入 RunLoop
    2、通知 observers: kCFRunLoopBeforeTimers, 即将处理 timers
    3、通知 observers: kCFRunLoopBeforeSources, 即将处理 sources
    4、处理 blocks, 可以对 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ 函数下断点观察到
    5、处理 sources 0, 可以对 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ 函数下断点观察到
    6、如果第 5 步实际处理了 sources 0,再一次处理 blocks
    7、如果在主线程,检查是否有 GCD 事件需要处理,有的话,跳转到第 11 步
    8、通知 observers: kCFRunLoopBeforeWaiting, 即将进入等待(睡眠)
    9、等待被唤醒,可以被 sources 1、timers、CFRunLoopWakeUp 函数和 GCD 事件(如果在主线程)
    10、通知 observers: kCFRunLoopAfterWaiting, 即停止等待(被唤醒)
    11、被什么唤醒就处理什么:
    11.1、 被 timers 唤醒,处理 timers,可以在 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ 函数下断点观察到
    11.2、 被 GCD 唤醒或者从第 7 步跳转过来的话,处理 GCD,可以在 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ 函数下断点观察到
    11.3、 被 sources 1 唤醒,处理 sources 1,可以在 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ 函数下断点观察到
    12、再一次处理 blocks
    13、判断是否退出,不需要退出则跳转回第 2 步
    14、通知 observers: kCFRunLoopExit, 退出 run loop
    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 {
            
            /// 通知 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__
    

    goto:是跳转的意思,直接跳到指定位置

    #include <stdio.h>
    
    int main(int argc, const char * argv[]) {
        
        int a = 1;// 打印1、2、3、4、44、444、1234、5、6、7
    //    int a = 10;//打印1、2、3、1234、5、6、7
        printf("1\n");
        printf("2\n");
        printf("3\n");
        if (a > 3) {
            goto dyz;
        }
        printf("4\n");
        printf("44\n");
        printf("444\n");
    dyz:
        printf("1234\n");
        
        printf("5\n");
        printf("6\n");
        printf("7\n");
        
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:RunLoop简易执行流程

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