当前位置:   article > 正文

CFRunLoop

cfsetcontainsvalue

数据结构

__CFRunLoopMode

  1. struct __CFRunLoopMode {
  2. CFRuntimeBase _base;
  3. pthread_mutex_t _lock; /* must have the run loop locked before locking
  4. this */
  5. //mode名
  6. CFStringRef _name;
  7. Boolean _stopped;
  8. char _padding[3];
  9. //source0 源
  10. CFMutableSetRef _sources0;
  11. //source1 源
  12. CFMutableSetRef _sources1;
  13. //observer 源
  14. CFMutableArrayRef _observers;
  15. //timer 源
  16. CFMutableArrayRef _timers;
  17. //mach port 到 mode的映射,为了在runloop主逻辑中过滤runloop自己的port消息。
  18. CFMutableDictionaryRef _portToV1SourceMap;
  19. //记录了所有当前mode中需要监听的port,作为调用监听消息函数的参数。
  20. __CFPortSet _portSet;
  21. CFIndex _observerMask;
  22. #if USE_DISPATCH_SOURCE_FOR_TIMERS
  23. dispatch_source_t _timerSource;
  24. dispatch_queue_t _queue;
  25. Boolean _timerFired; // set to true by the source when a timer has fired
  26. Boolean _dispatchTimerArmed;
  27. #endif
  28. #if USE_MK_TIMER_TOO
  29. //使用 mk timer, 用到的mach port,和source1类似,都依赖于mach port
  30. mach_port_t _timerPort;
  31. Boolean _mkTimerArmed;
  32. #endif
  33. //timer触发的理想时间
  34. uint64_t _timerSoftDeadline; /* TSR */
  35. //timer触发的实际时间,理想时间加上tolerance(偏差)
  36. uint64_t _timerHardDeadline; /* TSR */
  37. };
  38. 复制代码

__CFRunLoop

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

__CFRunLoops

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

函数:

__CFRunLoopRun

  1. static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm,
  2. CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef
  3. previousMode) {
  4. //获取系统启动之后cpu嘀嗒数
  5. uint64_t startTSR = mach_absolute_time();
  6. if (__CFRunLoopIsStopped(rl)) {
  7. __CFRunLoopUnsetStopped(rl);
  8. return kCFRunLoopRunStopped;
  9. } else if (rlm->_stopped) {
  10. rlm->_stopped = false;
  11. return kCFRunLoopRunStopped;
  12. }
  13. //mach 端口, 线程之间通信的对象
  14. mach_port_name_t dispatchPort = MACH_PORT_NULL;
  15. //这里主要是为了判断当前线程是否为主线程
  16. Boolean libdispatchQSafe = pthread_main_np() && ((
  17. HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && NULL == previousMode) || (!
  18. HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && 0 == _CFGetTSD(
  19. __CFTSDKeyIsInGCDMainQ)));
  20. if (libdispatchQSafe && (CFRunLoopGetMain() == rl) && CFSetContainsValue(rl
  21. ->_commonModes, rlm->_name)) dispatchPort =
  22. _dispatch_get_main_queue_port_4CF();
  23. //使用GCD实现runloop超时功能
  24. dispatch_source_t timeout_timer = NULL;
  25. struct __timeout_context *timeout_context = (struct __timeout_context *)
  26. malloc(sizeof(*timeout_context));
  27. //seconds是设置的runloop超时时间
  28. if (seconds <= 0.0) { // instant timeout
  29. seconds = 0.0;
  30. timeout_context->termTSR = 0ULL;
  31. } else if (seconds <= TIMER_INTERVAL_LIMIT) {
  32. dispatch_queue_t queue = dispatch_get_global_queue(
  33. DISPATCH_QUEUE_PRIORITY_HIGH, DISPATCH_QUEUE_OVERCOMMIT);
  34. timeout_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
  35. queue);
  36. dispatch_retain(timeout_timer);
  37. timeout_context->ds = timeout_timer;
  38. timeout_context->rl = (CFRunLoopRef)CFRetain(rl);
  39. timeout_context->termTSR = startTSR + __CFTimeIntervalToTSR(seconds);
  40. dispatch_set_context(timeout_timer, timeout_context); // source gets
  41. //ownership of context
  42. dispatch_source_set_event_handler_f(timeout_timer, __CFRunLoopTimeout);
  43. dispatch_source_set_cancel_handler_f(timeout_timer,
  44. __CFRunLoopTimeoutCancel);
  45. uint64_t ns_at = (uint64_t)((__CFTSRToTimeInterval(startTSR) + seconds)
  46. * 1000000000ULL);
  47. dispatch_source_set_timer(timeout_timer, dispatch_time(1, ns_at),
  48. DISPATCH_TIME_FOREVER, 1000ULL);
  49. dispatch_resume(timeout_timer);
  50. } else { // infinite timeout
  51. seconds = 9999999999.0;
  52. timeout_context->termTSR = UINT64_MAX;
  53. }
  54. Boolean didDispatchPortLastTime = true;
  55. int32_t retVal = 0;
  56. do {
  57. uint8_t msg_buffer[3 * 1024];
  58. mach_msg_header_t *msg = NULL;
  59. mach_port_t livePort = MACH_PORT_NULL;
  60. __CFPortSet waitSet = rlm->_portSet;
  61. __CFRunLoopUnsetIgnoreWakeUps(rl);
  62. //rl->_perRunData->ignoreWakeUps = 0x0;
  63. if (rlm->_observerMask & kCFRunLoopBeforeTimers) __CFRunLoopDoObservers
  64. (rl, rlm, kCFRunLoopBeforeTimers);
  65. if (rlm->_observerMask & kCFRunLoopBeforeSources)
  66. __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
  67. //Perform blocks queued by CFRunLoopPerformBlock;
  68. __CFRunLoopDoBlocks(rl, rlm);
  69. Boolean sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm,
  70. stopAfterHandle);
  71. //如果rl中有source0消息
  72. if (sourceHandledThisLoop) {
  73. //处理block Perform blocks newly queued by CFRunLoopPerformBlock;
  74. __CFRunLoopDoBlocks(rl, rlm);
  75. }
  76. //poll标志着有没有处理source0的消息,如果没有则为false,反之为true
  77. Boolean poll = sourceHandledThisLoop || (0ULL == timeout_context->
  78. termTSR);
  79. //第一次进来不走这个逻辑,didDispatchPortLastTime是true
  80. if (MACH_PORT_NULL != dispatchPort && !didDispatchPortLastTime) {
  81. msg = (mach_msg_header_t *)msg_buffer;
  82. //__CFRunLoopServiceMachPort用于接受指定端口(一个也可以是多个)
  83. //的消息,最后一个参数代表当端口无消息的时候是否休眠,0是立刻返回不休眠,
  84. //TIMEOUT_INFINITY代表休眠
  85. //处理通过GCD派发到主线程的任务,这些任务优先级最高会被最先处理
  86. if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(
  87. msg_buffer), &livePort, 0)) {
  88. goto handle_msg;
  89. }
  90. }
  91. didDispatchPortLastTime = false;
  92. //根据之前有没有处理过source0消息,来判断如果也没有source1消息的时候是否让线程进入睡眠,这里处
  93. //理observer源,如果睡眠则通知Observer进入睡眠。
  94. if (!poll && (rlm->_observerMask & kCFRunLoopBeforeWaiting))
  95. __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
  96. __CFRunLoopSetSleeping(rl);
  97. // do not do any user callouts after this point (after notifying of
  98. //sleeping)
  99. // Must push the local-to-this-activation ports in on every loop
  100. // iteration, as this mode could be run re-entrantly and we don't
  101. // want these ports to get serviced.
  102. __CFPortSetInsert(dispatchPort, waitSet);
  103. __CFRunLoopModeUnlock(rlm);
  104. __CFRunLoopUnlock(rl);
  105. if (kCFUseCollectableAllocator) {
  106. objc_clear_stack(0);
  107. memset(msg_buffer, 0, sizeof(msg_buffer));
  108. }
  109. msg = (mach_msg_header_t *)msg_buffer;
  110. //如果poll为null,且waitset中无port有消息,线程进入休眠
  111. __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort,
  112. poll ? 0 : TIMEOUT_INFINITY);
  113. __CFRunLoopLock(rl);
  114. __CFRunLoopModeLock(rlm);
  115. // Must remove the local-to-this-activation ports in on every loop
  116. // iteration, as this mode could be run re-entrantly and we don't
  117. // want these ports to get serviced. Also, we don't want them left
  118. // in there if this function returns.
  119. __CFPortSetRemove(dispatchPort, waitSet);
  120. __CFRunLoopSetIgnoreWakeUps(rl);
  121. // user callouts now OK again
  122. __CFRunLoopUnsetSleeping(rl);
  123. //处理observer源,线程醒来
  124. if (!poll && (rlm->_observerMask & kCFRunLoopAfterWaiting))
  125. __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
  126. handle_msg:;
  127. __CFRunLoopSetIgnoreWakeUps(rl);
  128. if (MACH_PORT_NULL == livePort) {
  129. CFRUNLOOP_WAKEUP_FOR_NOTHING();
  130. // handle nothing
  131. //通过CFRunloopWake将当前线程唤醒
  132. } else if (livePort == rl->_wakeUpPort) {
  133. CFRUNLOOP_WAKEUP_FOR_WAKEUP();
  134. // do nothing on Mac OS
  135. }
  136. //处理timer源
  137. else if (rlm->_timerPort != MACH_PORT_NULL && livePort == rlm->
  138. _timerPort) {
  139. CFRUNLOOP_WAKEUP_FOR_TIMER();
  140. if (!__CFRunLoopDoTimers(rl, rlm, mach_absolute_time())) {
  141. // Re-arm the next timer
  142. __CFArmNextTimerInMode(rlm, rl);
  143. }
  144. }
  145. //通过GCD派发给主线程的任务
  146. else if (livePort == dispatchPort) {
  147. CFRUNLOOP_WAKEUP_FOR_DISPATCH();
  148. __CFRunLoopModeUnlock(rlm);
  149. __CFRunLoopUnlock(rl);
  150. _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)6, NULL);
  151. __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);
  152. _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)0, NULL);
  153. __CFRunLoopLock(rl);
  154. __CFRunLoopModeLock(rlm);
  155. sourceHandledThisLoop = true;
  156. didDispatchPortLastTime = true;
  157. } else {
  158. //通过macPort给当前线程派发消息,处理source1
  159. CFRUNLOOP_WAKEUP_FOR_SOURCE();
  160. // Despite the name, this works for windows handles as well
  161. //过滤macPort消息,有一些消息不一定是runloop中注册的,这里只处理runloop中注册的
  162. //消息,在rlm->_portToV1SourceMap通过macPort找有没有对应的runloopMode
  163. CFRunLoopSourceRef rls = __CFRunLoopModeFindSourceForMachPort(rl,
  164. rlm, livePort);
  165. if (rls) {
  166. mach_msg_header_t *reply = NULL;
  167. sourceHandledThisLoop = __CFRunLoopDoSource1(rl, rlm, rls, msg,
  168. msg->msgh_size, &reply) || sourceHandledThisLoop;
  169. if (NULL != reply) {
  170. //当前线程处理完source1,给发消息的线程反馈消息,
  171. //MACH_SEND_MSG表示给replay端口发送消息
  172. (void)mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0,
  173. MACH_PORT_NULL, 0, MACH_PORT_NULL);
  174. CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply);
  175. }
  176. }
  177. }
  178. if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg);
  179. __CFRunLoopDoBlocks(rl, rlm);
  180. if (sourceHandledThisLoop && stopAfterHandle) {
  181. retVal = kCFRunLoopRunHandledSource;
  182. } else if (timeout_context->termTSR < mach_absolute_time()) {
  183. //runloop超时时间到
  184. retVal = kCFRunLoopRunTimedOut;
  185. } else if (__CFRunLoopIsStopped(rl)) {
  186. __CFRunLoopUnsetStopped(rl);
  187. retVal = kCFRunLoopRunStopped;
  188. } else if (rlm->_stopped) {
  189. rlm->_stopped = false;
  190. retVal = kCFRunLoopRunStopped;
  191. } else if (__CFRunLoopModeIsEmpty(rl, rlm, previousMode)) {
  192. retVal = kCFRunLoopRunFinished;
  193. }
  194. } while (0 == retVal);
  195. if (timeout_timer) {
  196. dispatch_source_cancel(timeout_timer);
  197. dispatch_release(timeout_timer);
  198. } else {
  199. free(timeout_context);
  200. }
  201. return retVal;
  202. }
  203. 复制代码

CFRunLoopAddSource

  1. void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef rls,
  2. CFStringRef modeName) { /* DOES CALLOUT */
  3. CHECK_FOR_FORK();
  4. if (__CFRunLoopIsDeallocating(rl)) return;
  5. if (!__CFIsValid(rls)) return;
  6. Boolean doVer0Callout = false;
  7. __CFRunLoopLock(rl);
  8. if (modeName == kCFRunLoopCommonModes) {
  9. //par1 : 处理commonModeItmes的逻辑
  10. /*rl->_commonModes的作用是记录了当前runloop中标记为commonMode的mode,rl->_commonModeI
  11. tems记录了当前runloop中注册到commonMode中的源
  12. 两者用来处理跟commonMode相关的逻辑,比如当一个mode被标记为commonMode的时候,会将rl->_common
  13. ModeItems中的源添加到新的mode当中去,在当前mode下这些源的消息就会被
  14. 监听并处理。例如一个timer被注册到commonMode中,那么在所有被标记为commonMode的mode中都会处理该timer的消息。
  15. */
  16. CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault
  17. , rl->_commonModes) : NULL;
  18. if (NULL == rl->_commonModeItems) {
  19. rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
  20. }
  21. CFSetAddValue(rl->_commonModeItems, rls);
  22. if (NULL != set) {
  23. CFTypeRef context[2] = {rl, rls};
  24. /* add new item to all common-modes */
  25. //对每一个mode,调用part2的逻辑
  26. CFSetApplyFunction(set, (__CFRunLoopAddItemToCommonModes), (void *)context);
  27. CFRelease(set);
  28. }
  29. } else {
  30. //part2 : 处理某个具体的mode中addSource的逻辑
  31. CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, true);
  32. if (NULL != rlm && NULL == rlm->_sources0) {
  33. rlm->_sources0 = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &
  34. kCFTypeSetCallBacks);
  35. rlm->_sources1 = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &
  36. kCFTypeSetCallBacks);
  37. rlm->_portToV1SourceMap = CFDictionaryCreateMutable(
  38. kCFAllocatorSystemDefault, 0, NULL, NULL);
  39. }
  40. if (NULL != rlm && !CFSetContainsValue(rlm->_sources0, rls) && !
  41. CFSetContainsValue(rlm->_sources1, rls)) {
  42. if (0 == rls->_context.version0.version) {
  43. CFSetAddValue(rlm->_sources0, rls);
  44. } else if (1 == rls->_context.version0.version) {
  45. CFSetAddValue(rlm->_sources1, rls);
  46. __CFPort src_port = rls->_context.version1.getPort(rls->_context.
  47. version1.info);
  48. if (CFPORT_NULL != src_port) {
  49. //rlm->_portToV1SourceMap是port到source1的映射,
  50. //为了在runloop主逻辑中过滤runloop自己的port消息。
  51. CFDictionarySetValue(rlm->_portToV1SourceMap, (const void *)(
  52. uintptr_t)src_port, rls);
  53. //rml->_portSet记录了所有当前mode中需要监听的port,作为调用监听消息函数的参数。
  54. __CFPortSetInsert(src_port, rlm->_portSet);
  55. }
  56. }
  57. __CFRunLoopSourceLock(rls);
  58. if (NULL == rls->_runLoops) {
  59. rls->_runLoops = CFBagCreateMutable(kCFAllocatorSystemDefault, 0, &
  60. kCFTypeBagCallBacks); // sources retain run loops!
  61. }
  62. CFBagAddValue(rls->_runLoops, rl);
  63. __CFRunLoopSourceUnlock(rls);
  64. if (0 == rls->_context.version0.version) {
  65. if (NULL != rls->_context.version0.schedule) {
  66. doVer0Callout = true;
  67. }
  68. }
  69. }
  70. if (NULL != rlm) {
  71. __CFRunLoopModeUnlock(rlm);
  72. }
  73. }
  74. __CFRunLoopUnlock(rl);
  75. if (doVer0Callout) {
  76. // although it looses some protection for the source, we have no
  77. //choice but
  78. // to do this after unlocking the run loop and mode locks, to avoid
  79. //deadlocks
  80. // where the source wants to take a lock which is already held in
  81. //another
  82. // thread which is itself waiting for a run loop/mode lock
  83. rls->_context.version0.schedule(rls->_context.version0.info, rl, modeName); /* CALLOUT */
  84. }
  85. }
  86. 复制代码

CFRunLoopRemoveSource

  1. void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef rls,
  2. CFStringRef modeName) { /* DOES CALLOUT */
  3. CHECK_FOR_FORK();
  4. Boolean doVer0Callout = false, doRLSRelease = false;
  5. __CFRunLoopLock(rl);
  6. if (modeName == kCFRunLoopCommonModes) {
  7. if (NULL != rl->_commonModeItems && CFSetContainsValue(rl->
  8. _commonModeItems, rls)) {
  9. CFSetRef set = rl->_commonModes ? CFSetCreateCopy(
  10. kCFAllocatorSystemDefault, rl->_commonModes) : NULL;
  11. CFSetRemoveValue(rl->_commonModeItems, rls);
  12. if (NULL != set) {
  13. CFTypeRef context[2] = {rl, rls};
  14. /* remove new item from all common-modes */
  15. CFSetApplyFunction(set, (__CFRunLoopRemoveItemFromCommonModes), (
  16. void *)context);
  17. CFRelease(set);
  18. }
  19. }
  20. } else {
  21. CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, false);
  22. if (NULL != rlm && ((NULL != rlm->_sources0 && CFSetContainsValue(rlm->
  23. _sources0, rls)) || (NULL != rlm->_sources1 && CFSetContainsValue(rlm->
  24. _sources1, rls)))) {
  25. //source0或者source1中的一种
  26. CFRetain(rls);
  27. if (1 == rls->_context.version0.version) {
  28. __CFPort src_port = rls->_context.version1.getPort(rls->_context.
  29. version1.info);
  30. if (CFPORT_NULL != src_port) {
  31. CFDictionaryRemoveValue(rlm->_portToV1SourceMap, (const void *)(
  32. uintptr_t)src_port);
  33. __CFPortSetRemove(src_port, rlm->_portSet);
  34. }
  35. }
  36. CFSetRemoveValue(rlm->_sources0, rls);
  37. CFSetRemoveValue(rlm->_sources1, rls);
  38. __CFRunLoopSourceLock(rls);
  39. if (NULL != rls->_runLoops) {
  40. CFBagRemoveValue(rls->_runLoops, rl);
  41. }
  42. __CFRunLoopSourceUnlock(rls);
  43. if (0 == rls->_context.version0.version) {
  44. if (NULL != rls->_context.version0.cancel) {
  45. doVer0Callout = true;
  46. }
  47. }
  48. doRLSRelease = true;
  49. }
  50. if (NULL != rlm) {
  51. __CFRunLoopModeUnlock(rlm);
  52. }
  53. }
  54. __CFRunLoopUnlock(rl);
  55. if (doVer0Callout) {
  56. // although it looses some protection for the source, we have no choice but
  57. // to do this after unlocking the run loop and mode locks, to avoid deadlocks
  58. // where the source wants to take a lock which is already held in another
  59. // thread which is itself waiting for a run loop/mode lock
  60. rls->_context.version0.cancel(rls->_context.version0.info, rl, modeName); /* CALLOUT */
  61. }
  62. if (doRLSRelease) CFRelease(rls);
  63. }
  64. 复制代码

CFRunLoopAddTimer

  1. void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef
  2. modeName) {
  3. CHECK_FOR_FORK();
  4. if (__CFRunLoopIsDeallocating(rl)) return;
  5. if (!__CFIsValid(rlt) || (NULL != rlt->_runLoop && rlt->_runLoop != rl))
  6. return;
  7. __CFRunLoopLock(rl);
  8. if (modeName == kCFRunLoopCommonModes) {
  9. CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault
  10. , rl->_commonModes) : NULL;
  11. if (NULL == rl->_commonModeItems) {
  12. rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0,
  13. &kCFTypeSetCallBacks);
  14. }
  15. CFSetAddValue(rl->_commonModeItems, rlt);
  16. if (NULL != set) {
  17. CFTypeRef context[2] = {rl, rlt};
  18. /* add new item to all common-modes */
  19. CFSetApplyFunction(set, (__CFRunLoopAddItemToCommonModes), (void *)
  20. context);
  21. CFRelease(set);
  22. }
  23. } else {
  24. CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, true);
  25. if (NULL != rlm) {
  26. if (NULL == rlm->_timers) {
  27. CFArrayCallBacks cb = kCFTypeArrayCallBacks;
  28. cb.equal = NULL;
  29. rlm->_timers = CFArrayCreateMutable(kCFAllocatorSystemDefault,
  30. 0, &cb);
  31. }
  32. }
  33. if (NULL != rlm && !CFSetContainsValue(rlt->_rlModes, rlm->_name)) {
  34. __CFRunLoopTimerLock(rlt);
  35. if (NULL == rlt->_runLoop) {
  36. rlt->_runLoop = rl;
  37. } else if (rl != rlt->_runLoop) {
  38. __CFRunLoopTimerUnlock(rlt);
  39. __CFRunLoopModeUnlock(rlm);
  40. __CFRunLoopUnlock(rl);
  41. return;
  42. }
  43. CFSetAddValue(rlt->_rlModes, rlm->_name);
  44. __CFRunLoopTimerUnlock(rlt);
  45. __CFRunLoopTimerFireTSRLock();
  46. //__CFRepositionTimerInMode是添加或者删除timer,
  47. //这里是往rlm->_timers添加timer
  48. __CFRepositionTimerInMode(rlm, rlt, false);
  49. __CFRunLoopTimerFireTSRUnlock();
  50. if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionLion)) {
  51. // Normally we don't do this on behalf of clients, but for
  52. // backwards compatibility due to the change in timer handling...
  53. if (rl != CFRunLoopGetCurrent()) CFRunLoopWakeUp(rl);
  54. }
  55. }
  56. if (NULL != rlm) {
  57. __CFRunLoopModeUnlock(rlm);
  58. }
  59. }
  60. __CFRunLoopUnlock(rl);
  61. }
  62. 复制代码

__CFRunLoopFindMode

  1. static CFRunLoopModeRef __CFRunLoopFindMode(CFRunLoopRef rl, CFStringRef
  2. modeName, Boolean create) {
  3. CHECK_FOR_FORK();
  4. CFRunLoopModeRef rlm;
  5. struct __CFRunLoopMode srlm;
  6. memset(&srlm, 0, sizeof(srlm));
  7. _CFRuntimeSetInstanceTypeIDAndIsa(&srlm, __kCFRunLoopModeTypeID);
  8. srlm._name = modeName;
  9. rlm = (CFRunLoopModeRef)CFSetGetValue(rl->_modes, &srlm);
  10. if (NULL != rlm) {
  11. __CFRunLoopModeLock(rlm);
  12. return rlm;
  13. }
  14. if (!create) {
  15. return NULL;
  16. }
  17. rlm = (CFRunLoopModeRef)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault,
  18. __kCFRunLoopModeTypeID, sizeof(struct __CFRunLoopMode) - sizeof(
  19. CFRuntimeBase), NULL);
  20. if (NULL == rlm) {
  21. return NULL;
  22. }
  23. __CFRunLoopLockInit(&rlm->_lock);
  24. rlm->_name = CFStringCreateCopy(kCFAllocatorSystemDefault, modeName);
  25. rlm->_stopped = false;
  26. rlm->_portToV1SourceMap = NULL;
  27. rlm->_sources0 = NULL;
  28. rlm->_sources1 = NULL;
  29. rlm->_observers = NULL;
  30. rlm->_timers = NULL;
  31. rlm->_observerMask = 0;
  32. rlm->_portSet = __CFPortSetAllocate();
  33. rlm->_timerSoftDeadline = UINT64_MAX;
  34. rlm->_timerHardDeadline = UINT64_MAX;
  35. kern_return_t ret = KERN_SUCCESS;
  36. //1
  37. #if USE_DISPATCH_SOURCE_FOR_TIMERS
  38. rlm->_timerFired = false;
  39. rlm->_queue = _dispatch_runloop_root_queue_create_4CF("Run Loop Mode Queue"
  40. , 0);
  41. mach_port_t queuePort = _dispatch_runloop_root_queue_get_port_4CF(rlm->
  42. _queue);
  43. if (queuePort == MACH_PORT_NULL) CRASH("*** Unable to create run loop mode
  44. queue port. (%d) ***", -1);
  45. rlm->_timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0
  46. , rlm->_queue);
  47. __block Boolean *timerFiredPointer = &(rlm->_timerFired);
  48. dispatch_source_set_event_handler(rlm->_timerSource, ^{
  49. *timerFiredPointer = true;
  50. });
  51. // Set timer to far out there. The unique leeway makes this timer easy to spot in debug output.
  52. _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource,
  53. DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 321);
  54. dispatch_resume(rlm->_timerSource);
  55. ret = __CFPortSetInsert(queuePort, rlm->_portSet);
  56. if (KERN_SUCCESS != ret) CRASH("*** Unable to insert timer port into port
  57. set. (%d) ***", ret);
  58. #endif
  59. //1
  60. #if USE_MK_TIMER_TOO
  61. rlm->_timerPort = mk_timer_create();
  62. ret = __CFPortSetInsert(rlm->_timerPort, rlm->_portSet);
  63. if (KERN_SUCCESS != ret) CRASH("*** Unable to insert timer port into port
  64. set. (%d) ***", ret);
  65. #endif
  66. ret = __CFPortSetInsert(rl->_wakeUpPort, rlm->_portSet);
  67. if (KERN_SUCCESS != ret) CRASH("*** Unable to insert wake up port into
  68. port set. (%d) ***", ret);
  69. CFSetAddValue(rl->_modes, rlm);
  70. CFRelease(rlm);
  71. __CFRunLoopModeLock(rlm); /* return mode locked */
  72. return rlm;
  73. }  ``return` `rlm;``}`
  74. 复制代码

__CFRepositionTimerInMode

  1. static void __CFRepositionTimerInMode(CFRunLoopModeRef rlm, CFRunLoopTimerRef
  2. rlt, Boolean isInArray) {
  3. if (!rlt) return;
  4. CFMutableArrayRef timerArray = rlm->_timers;
  5. if (!timerArray) return;
  6. Boolean found = false;
  7. // If we know in advance that the timer is not in the array (just being added now) then we can skip this search
  8. if (isInArray) {
  9. CFIndex idx = CFArrayGetFirstIndexOfValue(timerArray, CFRangeMake(0,
  10. CFArrayGetCount(timerArray)), rlt);
  11. if (kCFNotFound != idx) {
  12. CFRetain(rlt);
  13. CFArrayRemoveValueAtIndex(timerArray, idx);
  14. found = true;
  15. }
  16. }
  17. if (!found && isInArray) return;
  18. CFIndex newIdx = __CFRunLoopInsertionIndexInTimerArray(timerArray, rlt);
  19. //timer开始计时
  20. CFArrayInsertValueAtIndex(timerArray, newIdx, rlt);
  21. __CFArmNextTimerInMode(rlm, rlt->_runLoop);
  22. if (isInArray) CFRelease(rlt);
  23. }
  24. 复制代码

__CFArmNextTimerInMode

  1. static void __CFArmNextTimerInMode(CFRunLoopModeRef rlm, CFRunLoopRef rl) {   
  2.     uint64_t nextHardDeadline = UINT64_MAX;
  3.     uint64_t nextSoftDeadline = UINT64_MAX;
  4.     if (rlm->_timers) {
  5.         // Look at the list of timers. We will calculate two TSR values; the
  6. //next soft and next hard deadline.
  7.         // The next soft deadline is the first time we can fire any timer.
  8. //This is the fire date of the first timer in our sorted list of timers.
  9.         // The next hard deadline is the last time at which we can fire the
  10. //timer before we've moved out of the allowable tolerance of the timers in our list.
  11.         for (CFIndex idx = 0, cnt = CFArrayGetCount(rlm->_timers); idx < cnt;
  12. idx++) {
  13.             CFRunLoopTimerRef t = (CFRunLoopTimerRef)CFArrayGetValueAtIndex(rlm
  14. ->_timers , idx);
  15.             // discount timers currently firing
  16.             if (__CFRunLoopTimerIsFiring(t)) continue;
  17.              
  18.             int32_t err = CHECKINT_NO_ERROR;
  19.             uint64_t oneTimerSoftDeadline = t->_fireTSR;
  20.             uint64_t oneTimerHardDeadline = check_uint64_add(t->_fireTSR,
  21. __CFTimeIntervalToTSR(t->_tolerance), &err);
  22.             if (err != CHECKINT_NO_ERROR) oneTimerHardDeadline = UINT64_MAX;
  23.              
  24.             // 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.
  25.             if (oneTimerSoftDeadline > nextHardDeadline) {
  26.                 break;
  27.             }
  28.              
  29.             if (oneTimerSoftDeadline < nextSoftDeadline) {
  30.                 nextSoftDeadline = oneTimerSoftDeadline;
  31.             }
  32.              
  33.             if (oneTimerHardDeadline < nextHardDeadline) {
  34.                 nextHardDeadline = oneTimerHardDeadline;
  35.             }
  36.         }
  37.          
  38.         if (nextSoftDeadline < UINT64_MAX && (nextHardDeadline != rlm->
  39. _timerHardDeadline || nextSoftDeadline != rlm->_timerSoftDeadline)) {
  40.             if (CFRUNLOOP_NEXT_TIMER_ARMED_ENABLED()) {
  41.                 CFRUNLOOP_NEXT_TIMER_ARMED((unsigned long)(nextSoftDeadline -
  42. mach_absolute_time()));
  43.             }
  44. #if USE_DISPATCH_SOURCE_FOR_TIMERS
  45.             // We're going to hand off the range of allowable timer fire date
  46. //to dispatch and let it fire when appropriate for the system.
  47.             uint64_t leeway = __CFTSRToNanoseconds(nextHardDeadline -
  48. nextSoftDeadline);
  49.             dispatch_time_t deadline = __CFTSRToDispatchTime(nextSoftDeadline);
  50. #if USE_MK_TIMER_TOO
  51. //leeway表示timer的偏差,如果_tolerance(>=0)为0,则leeway等于0
  52.             if (leeway > 0) {
  53. //GCD timer
  54.                 // Only use the dispatch timer if we have any leeway
  55.                 // <rdar://problem/14447675>
  56.                  
  57.                 // Cancel the mk timer
  58.                 if (rlm->_mkTimerArmed && rlm->_timerPort) {
  59.                     AbsoluteTime dummy;
  60.                     mk_timer_cancel(rlm->_timerPort, &dummy);
  61.                     rlm->_mkTimerArmed = false;
  62.                 }
  63.                  
  64.                 // Arm the dispatch timer
  65.                 _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource,
  66. deadline, DISPATCH_TIME_FOREVER, leeway);
  67.                 rlm->_dispatchTimerArmed = true;
  68.             } else {
  69. //mk timer,实际中是这种情况
  70.                 // Cancel the dispatch timer
  71.                 if (rlm->_dispatchTimerArmed) {
  72.                     // Cancel the dispatch timer
  73.                     _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource,
  74. DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 888);
  75.                     rlm->_dispatchTimerArmed = false;
  76.                 }
  77.                  
  78.                 // Arm the mk timer
  79.                 if (rlm->_timerPort) {
  80. //timer开始运行
  81.                     mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(
  82. nextSoftDeadline));
  83.                     rlm->_mkTimerArmed = true;
  84.                 }
  85.             }
  86. #else
  87.             _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, deadline,
  88. DISPATCH_TIME_FOREVER, leeway);
  89. #endif
  90. #else
  91.             if (rlm->_timerPort) {
  92.                 mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(
  93. nextSoftDeadline));
  94.             }
  95. #endif
  96.         } else if (nextSoftDeadline == UINT64_MAX) {
  97.             // Disarm the timers - there is no timer scheduled
  98.              
  99.             if (rlm->_mkTimerArmed && rlm->_timerPort) {
  100.                 AbsoluteTime dummy;
  101.                 mk_timer_cancel(rlm->_timerPort, &dummy);
  102.                 rlm->_mkTimerArmed = false;
  103.             }
  104.              
  105. #if USE_DISPATCH_SOURCE_FOR_TIMERS
  106.             if (rlm->_dispatchTimerArmed) {
  107.                 _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource,
  108. DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 333);
  109.                 rlm->_dispatchTimerArmed = false;
  110.             }
  111. #endif
  112.         }
  113.     }
  114.     rlm->_timerHardDeadline = nextHardDeadline;
  115.     rlm->_timerSoftDeadline = nextSoftDeadline;
  116. }
  117. 复制代码

_CFRunLoopGet0

  1. CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {
  2. //判断t是否是传的空,如果是当成主线程处理
  3. if (pthread_equal(t, kNilPthreadT)) {
  4. t = pthread_main_thread_np();
  5. }
  6. __CFSpinLock(&loopsLock);
  7. //__CFRunLoops是全局存储线程和runloop关系的字典
  8. if (!__CFRunLoops) {
  9. //__CFRunLoop第一次初始化
  10. __CFSpinUnlock(&loopsLock);
  11. //初始化__CFRunLoop
  12. CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
  13. kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
  14. //生成主线程对应runloop
  15. CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());
  16. //存储到__CFRunLoop字典中
  17. CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);
  18. if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&
  19. __CFRunLoops)) {
  20. CFRelease(dict);
  21. }
  22. CFRelease(mainLoop);
  23. __CFSpinLock(&loopsLock);
  24. }
  25. //找到线程t对应的runloop
  26. CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops,
  27. pthreadPointer(t));
  28. __CFSpinUnlock(&loopsLock);
  29. if (!loop) {
  30. //没有找到,创建一个
  31. CFRunLoopRef newLoop = __CFRunLoopCreate(t);
  32. __CFSpinLock(&loopsLock);
  33. //??????
  34. loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
  35. if (!loop) {
  36. //保存到全局字典中
  37. CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop);
  38. loop = newLoop;
  39. }
  40. // don't release run loops inside the loopsLock, because
  41. //CFRunLoopDeallocate may end up taking it --> -->
  42. __CFSpinUnlock(&loopsLock);
  43. CFRelease(newLoop);
  44. }
  45. if (pthread_equal(t, pthread_self())) {
  46. _CFSetTSD(__CFTSDKeyRunLoop, (void *)loop, NULL);
  47. if (0 == _CFGetTSD(__CFTSDKeyRunLoopCntr)) {
  48. _CFSetTSD(__CFTSDKeyRunLoopCntr, (void *)(
  49. PTHREAD_DESTRUCTOR_ITERATIONS-1), (void (*)(void *))
  50. __CFFinalizeRunLoop);
  51. }
  52. }
  53. return loop;
  54. }
  55. 复制代码

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/273916
推荐阅读
相关标签
  

闽ICP备14008679号