数据结构

__CFRunLoopMode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

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

函数:

__CFRunLoopRun

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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->_commonModeI
tems记录了当前runloop中注册到commonMode中的源
两者用来处理跟commonMode相关的逻辑,比如当一个mode被标记为commonMode的时候,会将rl->_common
ModeItems中的源添加到新的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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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
                // <rdar://problem/14447675>
                 
                // 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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;
}