美文网首页
三十五、Runloop之(四)Runloop的运行逻辑

三十五、Runloop之(四)Runloop的运行逻辑

作者: yqc5521 | 来源:发表于2019-05-11 19:08 被阅读0次

Runloop的运行逻辑

Runloop的运行逻辑

CFRunloopObserver的创建及监听

CFRunloopObserver

监听CFRunloopModeRef的切换

在主线程默认开启runloop,模式为kCFRunloopDefaultMode,当屏幕滚动时,会退出当前mode,重新选择UITrackingMode进入,当停止滚动时,就会结束当前mode,重新回到defaultMode


CFRunloopModeRef的切换

Runloop的运行逻辑流程图

Runloop的运行逻辑流程图

Runloop的运行逻辑的底层代码实现

1.先调用CFRunLoopRunSpecific方法

SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) {
    
    //1.通知observer,进入loop
    __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
    //2.runloop具体要做的事情
    result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode);
    //3.通知observer,退出loop
    __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);

    return result;
}

2.再调用__CFRunLoopRun方法(内部有一个do while 循环)

static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) {
    
    int32_t retVal = 0;
    do {
        //通知observer,即将处理timer
        __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
        //通知observer,即将处理sources
        __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
        //处理blocks
        __CFRunLoopDoBlocks(rl, rlm);
        //处理source0
        if (__CFRunLoopDoSources0(rl, rlm, stopAfterHandle);) {
            //处理blocks
            __CFRunLoopDoBlocks(rl, rlm);
    } 
        //判断有无source1
        if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0, &voucherState, NULL)) {
            //如果有source1,就跳转到handle_msg
            goto handle_msg;
        }
        
        //如果没有source1,则通知observer,即将休眠
        __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
        //执行休眠操作
        __CFRunLoopSetSleeping(rl);
        
        //等待别的消息来唤醒当前线程
        __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy);
        //结束休眠
        __CFRunLoopUnsetSleeping(rl);
        //通知observer,结束休眠
        __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
 
     handle_msg: 
        if (被timer唤醒) {
            //处理timers
            __CFArmNextTimerInMode(rlm, rl);
        }
        else if (livePort == dispatchPort) { //被GCD唤醒
            // 处理GCD相关事件 : 例如主线程更新UI
            __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(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 < 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;
}

Runloop实现休眠的原理

__CFRunLoopServiceMachPort内部调用mach_msg()函数,此时会调用内核层面的API(相对于应用层面的API),执行应用层面的API时,是用户态,内核API则是内核态。在用户态调用mach_msg时,会自动转到内核态的mach_msg,达到真正休眠的目的,没有消息,就让线程休息,有消息就唤醒线程,切换到用户态,处理消息。


屏幕快照 2019-05-11 下午11.00.15.png Runloop实现休眠的原理

相关文章

  • 三十五、Runloop之(四)Runloop的运行逻辑

    Runloop的运行逻辑 CFRunloopObserver的创建及监听 监听CFRunloopModeRef的切...

  • iOS RunLoop 相关面试题

    RunLoop监听 Runloop运行逻辑

  • NSRunLoop

    RunLoop运行逻辑 RunLoop面试题: 1、什么是RunLoop? 答:从字面意思上:运行循环、跑圈。 其...

  • iOS Runloop底层详解

    一 什么是Runloop 二 Runloop的运行逻辑 三 Runloop在实际开发中的应用 一 什么是Runlo...

  • 第一篇:RunLoop的一些理论知识

    目录一、什么是RunLoop二、RunLoop和线程的关系三、RunLoop的Mode四、RunLoop的内部逻辑...

  • Runloop源码解析:运行逻辑

    Runloop应用: Timer失效问题; 线程保活; Runloop的运行逻辑: 入口函数 通知Observer...

  • 2. runloop 事件处理

    Runloop处理事件模型 RunLoop 的运行逻辑 01、通知Observers:进入Loop 02、通知Ob...

  • 12.runloop问题

    问题 1.个人对runloop的理解2.runloop 运行逻辑3.监听runloop 的模式4.获取当前子线程中...

  • RunLoop(二)

    RunLoop的运行逻辑 本文Demo代码可见gitHub_Demo 查看源码: RunLoop休眠的实现原理(如...

  • RunLoop

    RunLoop简单概述 RunLoop相关类 RunLoop逻辑处理 RunLoop实践 RunLoop简单概述 ...

网友评论

      本文标题:三十五、Runloop之(四)Runloop的运行逻辑

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