RunLoop底层源码分析

定义

  • RunLoop本质上是一个do-while循环

RunLoop状态

  • kCFRunLoopEntry
  • kCFRunLoopBeforeTimers
  • kCFRunLoopBeforeSources
  • kCFRunLoopBeforeWaiting
  • kCFRunLoopAfterWaiting
  • kCFRunLoopExit

底层源码分析

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) {     /* DOES CALLOUT */
   //通知Observer 进入kCFRunLoopEntry状态 【进入】
    if (currentMode->_observerMask & kCFRunLoopEntry ) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
    result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode);
    //通知Observer 进入kCFRunLoopExit状态 【退出】
    if (currentMode->_observerMask & kCFRunLoopExit ) __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 {
      
          //通知observer 进入kCFRunLoopBeforeTimers 处理timers
        __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
        //通知observer kCFRunLoopBeforeSources 处理source
        __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);   
        //处理blocks
        __CFRunLoopDoBlocks(rl, rlm);
        //处理sources0
        __CFRunLoopDoSources0(rl, rlm, stopAfterHandle);
        //处理完sources0,再次处理Blocks
        __CFRunLoopDoBlocks(rl, rlm);

        //判断是否有source1 Port
        if (MACH_PORT_NULL != dispatchPort && !didDispatchPortLastTime) {
            msg = (mach_msg_header_t *)msg_buffer;
            if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0, &voucherState, NULL)) {
              //如果有 goto:handle_msg
                goto handle_msg;
            }
        }

        //通知observer,进入kCFRunLoopBeforeWaiting状态
        __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
        //开始睡眠
        __CFRunLoopSetSleeping(rl);
    
        //等待别的消息来唤醒当前线程
        do {
            __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy);
            
        } while (1);
        
        //通知observer,结束休眠
        __CFRunLoopUnsetSleeping(rl);
        __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);

 handle_msg:
      
      //被timer唤醒
      if (WAKEUP_FOR_TIMER) {
         CFRUNLOOP_WAKEUP_FOR_TIMER();
        //处理timers
         __CFRunLoopDoTimers(rl, rlm, mach_absolute_time())
       //被GCD唤醒
      }else if (WAKEUP_FOR_DISPATCH) {
        //处理GCD
         __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);
        //被SOURCE1唤醒
      } else WAKEUP_FOR_SOURCE {
        //处理Source1
         __CFRunLoopDoSource1(rl, rlm, rls, msg, msg->msgh_size, &reply)
      }
        //处理Block
        __CFRunLoopDoBlocks(rl, rlm);
        
      //设置retVal的状态
      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)) {
          //没有Source、Timers、observers  
          retVal = kCFRunLoopRunFinished;
      }

    } while (0 == retVal);

    return retVal;
}

总结

RunLoop的内部执行逻辑:

  1. 通知Observer 进入kCFRunLoopEntry状态 【进入】
  2. 通知Observer 进入kCFRunLoopBeforeTimers 【处理timers】
  3. 通知Observer 进入kCFRunLoopBeforeSources【处理source】
  4. 处理blocks
  5. 处理sources0
  6. 处理完sources0,再次处理Blocks
  7. 如果有source1 进入进入9
  8. 通知observer,进入kCFRunLoopBeforeWaiting状态 【开始休眠】
  9. 通知observer,进入kCFRunLoopAfterWaiting状态 【结束休眠】
    • 处理Timers
    • 处理GCD
    • 处理Source1
  10. 通知Observer 进入kCFRunLoopExit状态 【退出】
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容