美文网首页
RunLoop -4⃣️- __CFRunLoopRun

RunLoop -4⃣️- __CFRunLoopRun

作者: 派大星的博客 | 来源:发表于2020-06-13 19:25 被阅读0次

__CFRunLoopRun是内部私有方法,只在CFRunLoopRunSpecific中一处调用

  • 方法声明
/**
* @param CFRunLoopRef : rl
* @param CFRunLoopModeRef : rlm
* @param CFTimeInterval : seconds
* @param Boolean: stopAfterHandle
* @param CFRunLoopModeRef : previousMode
*/
static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) 
  • 返回值类型
/* Reasons for CFRunLoopRunInMode() to Return */
typedef CF_ENUM(SInt32, CFRunLoopRunResult) {
    kCFRunLoopRunFinished = 1,
    kCFRunLoopRunStopped = 2,
    kCFRunLoopRunTimedOut = 3,
    kCFRunLoopRunHandledSource = 4
};

kCFRunLoopRunFinished 和 kCFRunLoopRunStopped 会终止循环。


分段解析

  • 1、输入参数检查,Stoped直接返回
   // runloop 的状态是否是Stopped
    if (__CFRunLoopIsStopped(rl))
    {
        __CFRunLoopUnsetStopped(rl);
        return kCFRunLoopRunStopped;
    }
   // runloopMode 的状态是否是Stopped
    else if (rlm->_stopped)
    {
        rlm->_stopped = false;
        return kCFRunLoopRunStopped;
    }
  • 2、 GCD 队列的端口设置

if ( 队列安全libdispatchQSafe && isMainRunloop && CurrentRunLoopMode在 _commonModes 的set集合中 ) { dispatchPort 设置为 主线程 runloop 所关联的的通信端口}

    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();
  • 3、超时时长操作: 使用的是GCD的Timer。
    dispatch_source_t timeout_timer = NULL;
    struct __timeout_context *timeout_context = (struct __timeout_context *)malloc(sizeof(*timeout_context));
    if (seconds <= 0.0)
    { // instant timeout
        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);
        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;
    }
  • 4、进入 do - while 循环,直到 reVal 不为 0 。
  // 伪代码,转自·孙源@sunnyxx·的PPT
    SetupThisRunLoopRunTimeoutTimer(); // by GCD timer
    do {
        __CFRunLoopDoObservers(kCFRunLoopBeforeTimers);
        __CFRunLoopDoObservers(kCFRunLoopBeforeSources);
        
        __CFRunLoopDoBlocks();
        __CFRunLoopDoSource0();
        
        CheckIfExistMessagesInMainDispatchQueue(); // GCD
        
        __CFRunLoopDoObservers(kCFRunLoopBeforeWaiting);
        var wakeUpPort = SleepAndWaitForWakingUpPorts();
        // mach_msg_trap
        // Zzz...
        // Received mach_msg, wake up
        __CFRunLoopDoObservers(kCFRunLoopAfterWaiting);
        // Handle msgs
        if (wakeUpPort == timerPort) {
            __CFRunLoopDoTimers();
        } else if (wakeUpPort == mainDispatchQueuePort) { // GCD
            __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__()
        } else {
            __CFRunLoopDoSource1();
        }
       __CFRunLoopDoBlocks();
   } while (!stop && !timeout);
do - while.png
  • __CFRunLoopDoBlocks
    处理的回调Blocks包括:
    1. VC的声明周期函数ViewDidLoadviewWillAppear ……
    2. 类似UICollectionViewDataSource的回调方法等

    1. 处理唤醒时收到的消息,Handler msgs
   // Handler msgs  
   if(wakeUpPort == timerPort){  
       //如果是timer唤醒就去执行timer  
       __CFRunLoopDoTimer();  
   }else if(wakeUpPort == mainDispatchQueuePort){  
       //GCD需要我,就去调GCD的事件  
       __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE();  
   }else{  
       //比如说网络来数据了就会用这个端口唤醒,然后做数据处理  
       __CFRunloopDoSource1();  
   }  
Handler msgs
处理timer
执行GCD丢进MainThread的Blocks
处理Source1

相关文章

  • RunLoop -4⃣️- __CFRunLoopRun

    __CFRunLoopRun是内部私有方法,只在CFRunLoopRunSpecific中一处调用 方法声明 返回...

  • 十二、RunLoop详解

    一、什么是RunLoop 先来看下RunLoop中CFRunLoopRun函数的实现: 开启RunLoop之后会调...

  • iOS RunLoop都做了什么?

    RunLoop的运行流程图 RunLoop从入口函数开始都做了什么? 1.从CFRunLoopRun入口函数可以看...

  • 对RunLoop的一点理解

    1.RunLoop与dispatch的关系 1.在__CFRunLoopRun函数中,用dispatch_sour...

  • RunLoop

    实际上 RunLoop 内部就是一个 do-while 循环 当你调用 CFRunLoopRun() 时,线程就会...

  • 运行循环&运行时

    实际上RunLoop 就是一个函数,其内部是一个do-while 循环。当你调用CFRunLoopRun() 时,...

  • 36.iOS底层学习之RunLoop

    本章提纲:1、RunLoop基础知识2、RunLoop的数据结构3、RunLoop的相关源码分析4、RunLoop...

  • iOS-Runloop常驻线程/性能优化

    主要聊聊以下内容 1 Runloop基本概要2 Runloop与定时器3 Runloop常驻线程4 Runloop...

  • RunLoop的概念及作用

    1.RunLoop的概念及作用 2.RunLoop的使用 3.RunLoop的相关类 4.RunLoop的工作原理...

  • RunLoop

    1.RunLoop的概念及作用 2.RunLoop的使用 3.RunLoop的相关类 4.RunLoop的工作原理...

网友评论

      本文标题:RunLoop -4⃣️- __CFRunLoopRun

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