博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CFRunLoop
阅读量:7014 次
发布时间:2019-06-28

本文共 29648 字,大约阅读时间需要 98 分钟。

数据结构

__CFRunLoopMode

struct __CFRunLoopMode {
CFRuntimeBase _base; pthread_mutex_t _lock; /* must have the run loop locked before locking this *///mode名 CFStringRef _name; Boolean _stopped; char _padding[3];//source0 源 CFMutableSetRef _sources0;//source1 源 CFMutableSetRef _sources1;//observer 源 CFMutableArrayRef _observers;//timer 源 CFMutableArrayRef _timers; //mach port 到 mode的映射,为了在runloop主逻辑中过滤runloop自己的port消息。 CFMutableDictionaryRef _portToV1SourceMap; //记录了所有当前mode中需要监听的port,作为调用监听消息函数的参数。 __CFPortSet _portSet; CFIndex _observerMask;#if USE_DISPATCH_SOURCE_FOR_TIMERS dispatch_source_t _timerSource; dispatch_queue_t _queue; Boolean _timerFired; // set to true by the source when a timer has fired Boolean _dispatchTimerArmed;#endif#if USE_MK_TIMER_TOO//使用 mk timer, 用到的mach port,和source1类似,都依赖于mach port mach_port_t _timerPort; Boolean _mkTimerArmed;#endif//timer触发的理想时间 uint64_t _timerSoftDeadline; /* TSR *///timer触发的实际时间,理想时间加上tolerance(偏差) uint64_t _timerHardDeadline; /* TSR */};复制代码

__CFRunLoop

struct __CFRunLoop {
CFRuntimeBase _base; pthread_mutex_t _lock; /* locked for accessing mode list */ //用于手动将当前runloop线程唤醒,通过调用CFRunLoopWakeUp完成,//CFRunLoopWakeUp会向_wakeUpPort发送一条消息 __CFPort _wakeUpPort; // used for CFRunLoopWakeUp Boolean _unused; volatile _per_run_data *_perRunData; // reset for runs of the run loop pthread_t _pthread; uint32_t _winthread;//记录了当前runloop中所有的mode名 CFMutableSetRef _commonModes;//记录了当前runloop中所有注册到commonMode中的源 CFMutableSetRef _commonModeItems; CFRunLoopModeRef _currentMode; CFMutableSetRef _modes;//记录了添加到runloop中的block,它也可以像其他源一样被runloop处理,//通过CFRunLoopPerformBlock可向runloop中添加block任务。 struct _block_item *_blocks_head; struct _block_item *_blocks_tail; CFTypeRef _counterpart;};复制代码

__CFRunLoops

//全局字典,保存线程和对应runloop之间的关系static CFMutableDictionaryRef __CFRunLoops = NULL;复制代码

函数:

__CFRunLoopRun

static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm,     CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef     previousMode) {    //获取系统启动之后cpu嘀嗒数    uint64_t startTSR = mach_absolute_time();    if (__CFRunLoopIsStopped(rl)) {        __CFRunLoopUnsetStopped(rl);    return kCFRunLoopRunStopped;    } else if (rlm->_stopped) {    rlm->_stopped = false;    return kCFRunLoopRunStopped;    }         //mach 端口, 线程之间通信的对象    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();         //使用GCD实现runloop超时功能    dispatch_source_t timeout_timer = NULL;    struct __timeout_context *timeout_context = (struct __timeout_context *)    malloc(sizeof(*timeout_context));    //seconds是设置的runloop超时时间    if (seconds <= 0.0) { // instant timeout        seconds = 0.0;        timeout_context->termTSR = 0ULL;    } else if (seconds <= TIMER_INTERVAL_LIMIT) {    dispatch_queue_t queue = dispatch_get_global_queue(        DISPATCH_QUEUE_PRIORITY_HIGH, DISPATCH_QUEUE_OVERCOMMIT);    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;    }    Boolean didDispatchPortLastTime = true;    int32_t retVal = 0;    do {        uint8_t msg_buffer[3 * 1024];        mach_msg_header_t *msg = NULL;        mach_port_t livePort = MACH_PORT_NULL;    __CFPortSet waitSet = rlm->_portSet;        __CFRunLoopUnsetIgnoreWakeUps(rl);        //rl->_perRunData->ignoreWakeUps = 0x0;        if (rlm->_observerMask & kCFRunLoopBeforeTimers) __CFRunLoopDoObservers        (rl, rlm, kCFRunLoopBeforeTimers);        if (rlm->_observerMask & kCFRunLoopBeforeSources)         __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);//Perform blocks queued by CFRunLoopPerformBlock;    __CFRunLoopDoBlocks(rl, rlm);        Boolean sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm,             stopAfterHandle);        //如果rl中有source0消息        if (sourceHandledThisLoop) {            //处理block  Perform blocks newly queued by CFRunLoopPerformBlock;            __CFRunLoopDoBlocks(rl, rlm);       }//poll标志着有没有处理source0的消息,如果没有则为false,反之为true        Boolean poll = sourceHandledThisLoop || (0ULL == timeout_context->            termTSR);        //第一次进来不走这个逻辑,didDispatchPortLastTime是true        if (MACH_PORT_NULL != dispatchPort && !didDispatchPortLastTime) {            msg = (mach_msg_header_t *)msg_buffer;            //__CFRunLoopServiceMachPort用于接受指定端口(一个也可以是多个)            //的消息,最后一个参数代表当端口无消息的时候是否休眠,0是立刻返回不休眠,            //TIMEOUT_INFINITY代表休眠            //处理通过GCD派发到主线程的任务,这些任务优先级最高会被最先处理            if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(                msg_buffer), &livePort, 0)) {                goto handle_msg;            }        }        didDispatchPortLastTime = false;//根据之前有没有处理过source0消息,来判断如果也没有source1消息的时候是否让线程进入睡眠,这里处//理observer源,如果睡眠则通知Observer进入睡眠。    if (!poll && (rlm->_observerMask & kCFRunLoopBeforeWaiting))     __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);    __CFRunLoopSetSleeping(rl);    // do not do any user callouts after this point (after notifying of         //sleeping)        // Must push the local-to-this-activation ports in on every loop        // iteration, as this mode could be run re-entrantly and we don't        // want these ports to get serviced.        __CFPortSetInsert(dispatchPort, waitSet);             __CFRunLoopModeUnlock(rlm);    __CFRunLoopUnlock(rl);    if (kCFUseCollectableAllocator) {        objc_clear_stack(0);        memset(msg_buffer, 0, sizeof(msg_buffer));    }    msg = (mach_msg_header_t *)msg_buffer;    //如果poll为null,且waitset中无port有消息,线程进入休眠    __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort,     poll ? 0 : TIMEOUT_INFINITY);         __CFRunLoopLock(rl);    __CFRunLoopModeLock(rlm);    // Must remove the local-to-this-activation ports in on every loop    // iteration, as this mode could be run re-entrantly and we don't    // want these ports to get serviced. Also, we don't want them left    // in there if this function returns.    __CFPortSetRemove(dispatchPort, waitSet);         __CFRunLoopSetIgnoreWakeUps(rl);        // user callouts now OK again    __CFRunLoopUnsetSleeping(rl);    //处理observer源,线程醒来    if (!poll && (rlm->_observerMask & kCFRunLoopAfterWaiting))     __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);        handle_msg:;        __CFRunLoopSetIgnoreWakeUps(rl);        if (MACH_PORT_NULL == livePort) {            CFRUNLOOP_WAKEUP_FOR_NOTHING();            // handle nothing//通过CFRunloopWake将当前线程唤醒        } else if (livePort == rl->_wakeUpPort) {            CFRUNLOOP_WAKEUP_FOR_WAKEUP();            // do nothing on Mac OS        }//处理timer源        else if (rlm->_timerPort != MACH_PORT_NULL && livePort == rlm->            _timerPort) {            CFRUNLOOP_WAKEUP_FOR_TIMER();            if (!__CFRunLoopDoTimers(rl, rlm, mach_absolute_time())) {                // Re-arm the next timer                __CFArmNextTimerInMode(rlm, rl);            }        }//通过GCD派发给主线程的任务        else if (livePort == dispatchPort) {            CFRUNLOOP_WAKEUP_FOR_DISPATCH();            __CFRunLoopModeUnlock(rlm);            __CFRunLoopUnlock(rl);            _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)6, NULL);            __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);            _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)0, NULL);            __CFRunLoopLock(rl);            __CFRunLoopModeLock(rlm);            sourceHandledThisLoop = true;            didDispatchPortLastTime = true;        } else {//通过macPort给当前线程派发消息,处理source1            CFRUNLOOP_WAKEUP_FOR_SOURCE();            // Despite the name, this works for windows handles as well            //过滤macPort消息,有一些消息不一定是runloop中注册的,这里只处理runloop中注册的            //消息,在rlm->_portToV1SourceMap通过macPort找有没有对应的runloopMode            CFRunLoopSourceRef rls = __CFRunLoopModeFindSourceForMachPort(rl,                 rlm, livePort);            if (rls) {                mach_msg_header_t *reply = NULL;                sourceHandledThisLoop = __CFRunLoopDoSource1(rl, rlm, rls, msg,                 msg->msgh_size, &reply) || sourceHandledThisLoop;                if (NULL != reply) {                    //当前线程处理完source1,给发消息的线程反馈消息,                     //MACH_SEND_MSG表示给replay端口发送消息                    (void)mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0,                         MACH_PORT_NULL, 0, MACH_PORT_NULL);                    CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply);                }           }        }    if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg);             __CFRunLoopDoBlocks(rl, rlm);    if (sourceHandledThisLoop && stopAfterHandle) {        retVal = kCFRunLoopRunHandledSource;    } else if (timeout_context->termTSR < mach_absolute_time()) {        //runloop超时时间到            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);    if (timeout_timer) {        dispatch_source_cancel(timeout_timer);        dispatch_release(timeout_timer);    } else {        free(timeout_context);    }    return retVal;}复制代码

CFRunLoopAddSource

void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef rls,     CFStringRef modeName) {    /* DOES CALLOUT */    CHECK_FOR_FORK();    if (__CFRunLoopIsDeallocating(rl)) return;    if (!__CFIsValid(rls)) return;    Boolean doVer0Callout = false;    __CFRunLoopLock(rl);    if (modeName == kCFRunLoopCommonModes) {        //par1 : 处理commonModeItmes的逻辑/*rl->_commonModes的作用是记录了当前runloop中标记为commonMode的mode,rl->_commonModeItems记录了当前runloop中注册到commonMode中的源两者用来处理跟commonMode相关的逻辑,比如当一个mode被标记为commonMode的时候,会将rl->_commonModeItems中的源添加到新的mode当中去,在当前mode下这些源的消息就会被监听并处理。例如一个timer被注册到commonMode中,那么在所有被标记为commonMode的mode中都会处理该timer的消息。*/    CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault        , rl->_commonModes) : NULL;    if (NULL == rl->_commonModeItems) {        rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);    }    CFSetAddValue(rl->_commonModeItems, rls);    if (NULL != set) {        CFTypeRef context[2] = {rl, rls};        /* add new item to all common-modes */        //对每一个mode,调用part2的逻辑        CFSetApplyFunction(set, (__CFRunLoopAddItemToCommonModes), (void *)context);        CFRelease(set);    }    } else {    //part2 : 处理某个具体的mode中addSource的逻辑    CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, true);    if (NULL != rlm && NULL == rlm->_sources0) {        rlm->_sources0 = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &            kCFTypeSetCallBacks);        rlm->_sources1 = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &            kCFTypeSetCallBacks);        rlm->_portToV1SourceMap = CFDictionaryCreateMutable(            kCFAllocatorSystemDefault, 0, NULL, NULL);    }    if (NULL != rlm && !CFSetContainsValue(rlm->_sources0, rls) && !    CFSetContainsValue(rlm->_sources1, rls)) {        if (0 == rls->_context.version0.version) {            CFSetAddValue(rlm->_sources0, rls);        } else if (1 == rls->_context.version0.version) {            CFSetAddValue(rlm->_sources1, rls);        __CFPort src_port = rls->_context.version1.getPort(rls->_context.            version1.info);        if (CFPORT_NULL != src_port) {        //rlm->_portToV1SourceMap是port到source1的映射,        //为了在runloop主逻辑中过滤runloop自己的port消息。            CFDictionarySetValue(rlm->_portToV1SourceMap, (const void *)(                uintptr_t)src_port, rls);        //rml->_portSet记录了所有当前mode中需要监听的port,作为调用监听消息函数的参数。            __CFPortSetInsert(src_port, rlm->_portSet);            }        }        __CFRunLoopSourceLock(rls);        if (NULL == rls->_runLoops) {            rls->_runLoops = CFBagCreateMutable(kCFAllocatorSystemDefault, 0, &            kCFTypeBagCallBacks); // sources retain run loops!        }        CFBagAddValue(rls->_runLoops, rl);        __CFRunLoopSourceUnlock(rls);        if (0 == rls->_context.version0.version) {            if (NULL != rls->_context.version0.schedule) {                doVer0Callout = true;            }        }    }        if (NULL != rlm) {        __CFRunLoopModeUnlock(rlm);    }    }    __CFRunLoopUnlock(rl);    if (doVer0Callout) {        // although it looses some protection for the source, we have no         //choice but        // to do this after unlocking the run loop and mode locks, to avoid         //deadlocks        // where the source wants to take a lock which is already held in         //another        // thread which is itself waiting for a run loop/mode lock    rls->_context.version0.schedule(rls->_context.version0.info, rl, modeName);   /* CALLOUT */    }}复制代码

CFRunLoopRemoveSource

void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef rls,     CFStringRef modeName) { /* DOES CALLOUT */    CHECK_FOR_FORK();    Boolean doVer0Callout = false, doRLSRelease = false;    __CFRunLoopLock(rl);    if (modeName == kCFRunLoopCommonModes) {        if (NULL != rl->_commonModeItems && CFSetContainsValue(rl->            _commonModeItems, rls)) {            CFSetRef set = rl->_commonModes ? CFSetCreateCopy(                kCFAllocatorSystemDefault, rl->_commonModes) : NULL;            CFSetRemoveValue(rl->_commonModeItems, rls);            if (NULL != set) {            CFTypeRef context[2] = {rl, rls};            /* remove new item from all common-modes */            CFSetApplyFunction(set, (__CFRunLoopRemoveItemFromCommonModes), (                void *)context);            CFRelease(set);            }        }    } else {    CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, false);    if (NULL != rlm && ((NULL != rlm->_sources0 && CFSetContainsValue(rlm->        _sources0, rls)) || (NULL != rlm->_sources1 && CFSetContainsValue(rlm->            _sources1, rls)))) {        //source0或者source1中的一种        CFRetain(rls);        if (1 == rls->_context.version0.version) {        __CFPort src_port = rls->_context.version1.getPort(rls->_context.            version1.info);                if (CFPORT_NULL != src_port) {            CFDictionaryRemoveValue(rlm->_portToV1SourceMap, (const void *)(                uintptr_t)src_port);                    __CFPortSetRemove(src_port, rlm->_portSet);                }        }        CFSetRemoveValue(rlm->_sources0, rls);        CFSetRemoveValue(rlm->_sources1, rls);            __CFRunLoopSourceLock(rls);            if (NULL != rls->_runLoops) {                CFBagRemoveValue(rls->_runLoops, rl);            }            __CFRunLoopSourceUnlock(rls);        if (0 == rls->_context.version0.version) {            if (NULL != rls->_context.version0.cancel) {                doVer0Callout = true;            }        }        doRLSRelease = true;    }        if (NULL != rlm) {        __CFRunLoopModeUnlock(rlm);    }    }    __CFRunLoopUnlock(rl);    if (doVer0Callout) {        // although it looses some protection for the source, we have no choice but        // to do this after unlocking the run loop and mode locks, to avoid deadlocks        // where the source wants to take a lock which is already held in another        // thread which is itself waiting for a run loop/mode lock        rls->_context.version0.cancel(rls->_context.version0.info, rl, modeName); /* CALLOUT */    }    if (doRLSRelease) CFRelease(rls);}复制代码

CFRunLoopAddTimer

void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef     modeName) {       CHECK_FOR_FORK();    if (__CFRunLoopIsDeallocating(rl)) return;    if (!__CFIsValid(rlt) || (NULL != rlt->_runLoop && rlt->_runLoop != rl))     return;    __CFRunLoopLock(rl);    if (modeName == kCFRunLoopCommonModes) {    CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault        , rl->_commonModes) : NULL;    if (NULL == rl->_commonModeItems) {        rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0,         &kCFTypeSetCallBacks);    }    CFSetAddValue(rl->_commonModeItems, rlt);    if (NULL != set) {        CFTypeRef context[2] = {rl, rlt};        /* add new item to all common-modes */        CFSetApplyFunction(set, (__CFRunLoopAddItemToCommonModes), (void *)        context);        CFRelease(set);    }    } else {    CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, true);    if (NULL != rlm) {            if (NULL == rlm->_timers) {                CFArrayCallBacks cb = kCFTypeArrayCallBacks;                cb.equal = NULL;                rlm->_timers = CFArrayCreateMutable(kCFAllocatorSystemDefault,                     0, &cb);            }    }    if (NULL != rlm && !CFSetContainsValue(rlt->_rlModes, rlm->_name)) {            __CFRunLoopTimerLock(rlt);            if (NULL == rlt->_runLoop) {        rlt->_runLoop = rl;        } else if (rl != rlt->_runLoop) {                __CFRunLoopTimerUnlock(rlt);            __CFRunLoopModeUnlock(rlm);                __CFRunLoopUnlock(rl);        return;        }        CFSetAddValue(rlt->_rlModes, rlm->_name);            __CFRunLoopTimerUnlock(rlt);            __CFRunLoopTimerFireTSRLock();            //__CFRepositionTimerInMode是添加或者删除timer,            //这里是往rlm->_timers添加timer            __CFRepositionTimerInMode(rlm, rlt, false);            __CFRunLoopTimerFireTSRUnlock();            if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionLion)) {                // Normally we don't do this on behalf of clients, but for                // backwards compatibility due to the change in timer handling...                if (rl != CFRunLoopGetCurrent()) CFRunLoopWakeUp(rl);            }    }        if (NULL != rlm) {        __CFRunLoopModeUnlock(rlm);    }    }    __CFRunLoopUnlock(rl);}复制代码

__CFRunLoopFindMode

static CFRunLoopModeRef __CFRunLoopFindMode(CFRunLoopRef rl, CFStringRef     modeName, Boolean create) {    CHECK_FOR_FORK();    CFRunLoopModeRef rlm;    struct __CFRunLoopMode srlm;    memset(&srlm, 0, sizeof(srlm));    _CFRuntimeSetInstanceTypeIDAndIsa(&srlm, __kCFRunLoopModeTypeID);    srlm._name = modeName;    rlm = (CFRunLoopModeRef)CFSetGetValue(rl->_modes, &srlm);    if (NULL != rlm) {    __CFRunLoopModeLock(rlm);    return rlm;    }    if (!create) {    return NULL;    }    rlm = (CFRunLoopModeRef)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault,     __kCFRunLoopModeTypeID, sizeof(struct __CFRunLoopMode) - sizeof(        CFRuntimeBase), NULL);    if (NULL == rlm) {    return NULL;    }    __CFRunLoopLockInit(&rlm->_lock);    rlm->_name = CFStringCreateCopy(kCFAllocatorSystemDefault, modeName);    rlm->_stopped = false;    rlm->_portToV1SourceMap = NULL;    rlm->_sources0 = NULL;    rlm->_sources1 = NULL;    rlm->_observers = NULL;    rlm->_timers = NULL;    rlm->_observerMask = 0;    rlm->_portSet = __CFPortSetAllocate();    rlm->_timerSoftDeadline = UINT64_MAX;    rlm->_timerHardDeadline = UINT64_MAX;         kern_return_t ret = KERN_SUCCESS;    //1#if USE_DISPATCH_SOURCE_FOR_TIMERS    rlm->_timerFired = false;    rlm->_queue = _dispatch_runloop_root_queue_create_4CF("Run Loop Mode Queue"    , 0);    mach_port_t queuePort = _dispatch_runloop_root_queue_get_port_4CF(rlm->        _queue);    if (queuePort == MACH_PORT_NULL) CRASH("*** Unable to create run loop mode     queue port. (%d) ***", -1);    rlm->_timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0        , rlm->_queue);         __block Boolean *timerFiredPointer = &(rlm->_timerFired);    dispatch_source_set_event_handler(rlm->_timerSource, ^{        *timerFiredPointer = true;    });         // Set timer to far out there. The unique leeway makes this timer easy to spot in debug output.    _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource,         DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 321);    dispatch_resume(rlm->_timerSource);         ret = __CFPortSetInsert(queuePort, rlm->_portSet);    if (KERN_SUCCESS != ret) CRASH("*** Unable to insert timer port into port     set. (%d) ***", ret);     #endif    //1#if USE_MK_TIMER_TOO    rlm->_timerPort = mk_timer_create();    ret = __CFPortSetInsert(rlm->_timerPort, rlm->_portSet);    if (KERN_SUCCESS != ret) CRASH("*** Unable to insert timer port into port     set. (%d) ***", ret);#endif         ret = __CFPortSetInsert(rl->_wakeUpPort, rlm->_portSet);    if (KERN_SUCCESS != ret) CRASH("*** Unable to insert wake up port into     port set. (%d) ***", ret);         CFSetAddValue(rl->_modes, rlm);    CFRelease(rlm);    __CFRunLoopModeLock(rlm);   /* return mode locked */    return rlm;}  ``return` `rlm;``}`复制代码

__CFRepositionTimerInMode

static void __CFRepositionTimerInMode(CFRunLoopModeRef rlm, CFRunLoopTimerRef     rlt, Boolean isInArray) {    if (!rlt) return;         CFMutableArrayRef timerArray = rlm->_timers;    if (!timerArray) return;    Boolean found = false;         // If we know in advance that the timer is not in the array (just being added now) then we can skip this search    if (isInArray) {        CFIndex idx = CFArrayGetFirstIndexOfValue(timerArray, CFRangeMake(0,             CFArrayGetCount(timerArray)), rlt);        if (kCFNotFound != idx) {            CFRetain(rlt);            CFArrayRemoveValueAtIndex(timerArray, idx);            found = true;        }    }    if (!found && isInArray) return;    CFIndex newIdx = __CFRunLoopInsertionIndexInTimerArray(timerArray, rlt);   //timer开始计时    CFArrayInsertValueAtIndex(timerArray, newIdx, rlt);    __CFArmNextTimerInMode(rlm, rlt->_runLoop);    if (isInArray) CFRelease(rlt);}复制代码

__CFArmNextTimerInMode

static void __CFArmNextTimerInMode(CFRunLoopModeRef rlm, CFRunLoopRef rl) {       uint64_t nextHardDeadline = UINT64_MAX;    uint64_t nextSoftDeadline = UINT64_MAX;    if (rlm->_timers) {        // Look at the list of timers. We will calculate two TSR values; the //next soft and next hard deadline.        // The next soft deadline is the first time we can fire any timer. //This is the fire date of the first timer in our sorted list of timers.        // The next hard deadline is the last time at which we can fire the //timer before we've moved out of the allowable tolerance of the timers in our list.        for (CFIndex idx = 0, cnt = CFArrayGetCount(rlm->_timers); idx < cnt; idx++) {            CFRunLoopTimerRef t = (CFRunLoopTimerRef)CFArrayGetValueAtIndex(rlm    ->_timers , idx);            // discount timers currently firing            if (__CFRunLoopTimerIsFiring(t)) continue;                         int32_t err = CHECKINT_NO_ERROR;            uint64_t oneTimerSoftDeadline = t->_fireTSR;            uint64_t oneTimerHardDeadline = check_uint64_add(t->_fireTSR,     __CFTimeIntervalToTSR(t->_tolerance), &err);            if (err != CHECKINT_NO_ERROR) oneTimerHardDeadline = UINT64_MAX;                         // We can stop searching if the soft deadline for this timer exceeds the current hard deadline. Otherwise, later timers with lower tolerance could still have earlier hard deadlines.            if (oneTimerSoftDeadline > nextHardDeadline) {                break;            }                         if (oneTimerSoftDeadline < nextSoftDeadline) {                nextSoftDeadline = oneTimerSoftDeadline;            }                         if (oneTimerHardDeadline < nextHardDeadline) {                nextHardDeadline = oneTimerHardDeadline;            }        }                 if (nextSoftDeadline < UINT64_MAX && (nextHardDeadline != rlm->    _timerHardDeadline || nextSoftDeadline != rlm->_timerSoftDeadline)) {            if (CFRUNLOOP_NEXT_TIMER_ARMED_ENABLED()) {                CFRUNLOOP_NEXT_TIMER_ARMED((unsigned long)(nextSoftDeadline -     mach_absolute_time()));            }#if USE_DISPATCH_SOURCE_FOR_TIMERS            // We're going to hand off the range of allowable timer fire date //to dispatch and let it fire when appropriate for the system.            uint64_t leeway = __CFTSRToNanoseconds(nextHardDeadline -     nextSoftDeadline);            dispatch_time_t deadline = __CFTSRToDispatchTime(nextSoftDeadline);#if USE_MK_TIMER_TOO//leeway表示timer的偏差,如果_tolerance(>=0)为0,则leeway等于0            if (leeway > 0) {//GCD timer                // Only use the dispatch timer if we have any leeway                // 
                                 // Cancel the mk timer                if (rlm->_mkTimerArmed && rlm->_timerPort) {                    AbsoluteTime dummy;                    mk_timer_cancel(rlm->_timerPort, &dummy);                    rlm->_mkTimerArmed = false;                }                                 // Arm the dispatch timer                _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, deadline, DISPATCH_TIME_FOREVER, leeway);                rlm->_dispatchTimerArmed = true;            } else {//mk timer,实际中是这种情况                // Cancel the dispatch timer                if (rlm->_dispatchTimerArmed) {                    // Cancel the dispatch timer                    _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 888);                    rlm->_dispatchTimerArmed = false;                }                                 // Arm the mk timer                if (rlm->_timerPort) {//timer开始运行                    mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime( nextSoftDeadline));                    rlm->_mkTimerArmed = true;                }            }#else            _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, deadline, DISPATCH_TIME_FOREVER, leeway);#endif#else            if (rlm->_timerPort) {                mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime( nextSoftDeadline));            }#endif        } else if (nextSoftDeadline == UINT64_MAX) {            // Disarm the timers - there is no timer scheduled                         if (rlm->_mkTimerArmed && rlm->_timerPort) {                AbsoluteTime dummy;                mk_timer_cancel(rlm->_timerPort, &dummy);                rlm->_mkTimerArmed = false;            }             #if USE_DISPATCH_SOURCE_FOR_TIMERS            if (rlm->_dispatchTimerArmed) {                _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 333);                rlm->_dispatchTimerArmed = false;            }#endif        }    }    rlm->_timerHardDeadline = nextHardDeadline;    rlm->_timerSoftDeadline = nextSoftDeadline;}复制代码

_CFRunLoopGet0

CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {    //判断t是否是传的空,如果是当成主线程处理    if (pthread_equal(t, kNilPthreadT)) {        t = pthread_main_thread_np();    }    __CFSpinLock(&loopsLock);//__CFRunLoops是全局存储线程和runloop关系的字典    if (!__CFRunLoops) {//__CFRunLoop第一次初始化        __CFSpinUnlock(&loopsLock);//初始化__CFRunLoop    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(        kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);//生成主线程对应runloop    CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());//存储到__CFRunLoop字典中    CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);    if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&    __CFRunLoops)) {        CFRelease(dict);    }    CFRelease(mainLoop);        __CFSpinLock(&loopsLock);    }//找到线程t对应的runloop    CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops,         pthreadPointer(t));    __CFSpinUnlock(&loopsLock);    if (!loop) {//没有找到,创建一个    CFRunLoopRef newLoop = __CFRunLoopCreate(t);        __CFSpinLock(&loopsLock);//??????    loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));    if (!loop) {//保存到全局字典中        CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop);        loop = newLoop;    }        // don't release run loops inside the loopsLock, because         //CFRunLoopDeallocate may end up taking it --> -->        __CFSpinUnlock(&loopsLock);    CFRelease(newLoop);    }    if (pthread_equal(t, pthread_self())) {        _CFSetTSD(__CFTSDKeyRunLoop, (void *)loop, NULL);        if (0 == _CFGetTSD(__CFTSDKeyRunLoopCntr)) {            _CFSetTSD(__CFTSDKeyRunLoopCntr, (void *)(                PTHREAD_DESTRUCTOR_ITERATIONS-1), (void (*)(void *))                __CFFinalizeRunLoop);        }    }    return loop;}复制代码

转载于:https://juejin.im/post/5b6817aee51d4519610e44f7

你可能感兴趣的文章
深入学习Hive应用场景及架构原理
查看>>
07-01 Java 封装
查看>>
HDU_1143_tri tiling
查看>>
codeforces_1075_C. The Tower is Going Home
查看>>
使用BBED模拟Oracle数据库坏块
查看>>
C# 关于XML的简单操作实例
查看>>
ggplot2:画世界地图和中国地图 合并数据 增添信息 标记
查看>>
VertexBuffer渲染次序
查看>>
div高度自适应
查看>>
python中使用 xpath
查看>>
集中管理:领导者,不能不考虑的几件事之—— 拿什么辅助你,我的决策?(一)...
查看>>
四、物理优化(6)数据库引擎优化顾问
查看>>
我的友情链接
查看>>
关于VirtualBox虚拟机安装GhostXP出现蓝屏proce***.sys 的解决办法
查看>>
浅谈 C#委托
查看>>
Atitit.跨语言反射api 兼容性提升与增强 java c#。Net php js
查看>>
【Thread】多线程的异常处理?
查看>>
H.264 CODEC
查看>>
计算机图形学中的经常使用模型
查看>>
Android生成keystore是报错拒绝访问
查看>>