美文网首页iOS高级进阶
Runloop源码解析:运行逻辑

Runloop源码解析:运行逻辑

作者: 南城同學 | 来源:发表于2019-11-12 11:58 被阅读0次

Runloop应用:


Runloop的运行逻辑:

入口函数

SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled)
  1. 通知Observers:进入Loop;
__CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
  1. 通知Observers:即将处理Timers;
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
  1. 通知Observers:即将处理Sources;
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
  1. 处理Blocks;
__CFRunLoopDoBlocks(rl, rlm);
  1. 处理Source0(可能会再次处理Blocks);
Boolean sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm, stopAfterHandle);
        if (sourceHandledThisLoop) {
            __CFRunLoopDoBlocks(rl, rlm);
    }
  1. 如果存在Source1,就跳转到第8步;
if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0, &voucherState, NULL)) {
                goto handle_msg;
            }
  1. 通知Observers:开始休眠(等待消息唤醒);
//通知Observers:即将休眠
__CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
__CFRunLoopSetSleeping(rl);

//等待别的消息来唤醒当前线程
__CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy);
            
  1. 通知Observers:结束休眠(被某个消息唤醒):
//通知Observers:结束休眠
 __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);

  1. 处理Timer;
  2. 处理GCD Async To Main Queue;
  3. 处理Source1;
if(被timer唤醒) {
//处理Timers
__CFRunLoopDoTimers(rl, rlm, mach_absolute_time());
} else if (被GCD唤醒) {
//处理CGD
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);

} else { //被Source1唤醒
//处理Source1
 __CFRunLoopDoSource1(rl, rlm, rls, msg, msg->msgh_size, &reply) || sourceHandledThisLoop;
}

  1. 处理Blocks;
__CFRunLoopDoBlocks(rl, rlm);

  1. 根据前面的执行结果,决定如何操作:
    1. 回到第02步;
    2. 或 退出Loop;
 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);
  1. 通知Observers:退出Loop.
 __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);

扩展:Runloop休眠实现的原理:

  • runloop休眠函数:
//等待别的消息来唤醒当前线程
__CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy);
  • 原理:通过函数mach_msg()切换到内核态,控制线程休眠。

线程阻塞有两种方式:

  1. 代码阻塞,但是当前线程并没有休息;
  • 如下,死循环:
while(1);
  1. 真的让当前线程去“休息”。
  • 内核层面API:mach_msg()
    1. 没有消息就让线程休眠;
    2. 有消息就唤醒。

相关文章

  • Runloop源码解析:运行逻辑

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

  • RunLoop(二)

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

  • iOS RunLoop 相关面试题

    RunLoop监听 Runloop运行逻辑

  • 记录一些介绍Runloop的牛文

    老司机出品——源码解析之RunLoop详解深入理解RunLoop关于RunLoop部分源码的注释CFRunLoop...

  • 15-RunLoop-02

    一、RunLoop运行逻辑 1.源码分析:精简版(保留了核心代码) 2.休眠细节 二、RunLoop在实际开发中的...

  • NSRunLoop

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

  • RunLoop 理解

    Runloop解析 概述 从字面的意思来看,就是运行循环,没有终点,一直运行。下面先看下大致 runloop 运行...

  • 底层原理探究(二)RunLoop

    转自: 老司机出品——源码解析之RunLoop详解入门使用: RunLoop入门 看我就够了孙源的Runloop视...

  • 从源码看Runloop-内部逻辑

    从源码看Runloop-内部逻辑 RunLoop的入口 NSRunLoop有三个启动runloop的方法,CFRu...

  • RunLoop -- 运行逻辑

    直接分析下源码CFRunLoopRef源码地址通过打断点可以从 CFRunLoopRun 方法进行查看 01、通知...

网友评论

    本文标题:Runloop源码解析:运行逻辑

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