runloop底层源码探究一(runloop的创建)
2021-01-08 本文已影响0人
iOS劝退师
一、创建runloop
1、子线程默认不创建runloop,主动获取的时候才去创建(或直接从__CFTSDTable中取)runloop
[NSRunLoop currentRunLoop]
//底层源码
//主线程runloop
CFRunLoopRef CFRunLoopGetMain(void) {
CHECK_FOR_FORK();
static CFRunLoopRef __main = NULL; // no retain needed
//没有mainrunloop就创建
if (!__main) __main = _CFRunLoopGet0(pthread_main_thread_np()); // no CAS needed
return __main;
}
//其他线程runloop
CFRunLoopRef CFRunLoopGetCurrent(void) {
CHECK_FOR_FORK();
// 从一个 -》 runLoop
CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(__CFTSDKeyRunLoop);
if (rl) return rl;
// 创建一个
return _CFRunLoopGet0(pthread_self());
}
流程我画了个图:
1、首先会从__CFTSDTable找,是否有可用的runloop
2、如过有就直接将可用的return,如果没有就调用下面这个方法创建一个新的,创建成功后,还是回存到__CFTSDTable中,然后再return
_CFRunLoopGet0(pthread_self())
__CFTSDTable的定义:
其中的data[CF_TSD_MAX_SLOTS]应该就是存放runloop的数组
// Data structure to hold TSD data, cleanup functions for each
typedef struct __CFTSDTable {
uint32_t destructorCount;
uintptr_t data[CF_TSD_MAX_SLOTS];
tsdDestructor destructors[CF_TSD_MAX_SLOTS];
} __CFTSDTable;
//最大存入个数是70个,看注释超过70个会crash
// If slot >= CF_TSD_MAX_SLOTS, the SPI functions will crash at NULL + slot address.
// If thread data has been torn down, these functions should crash on CF_TSD_BAD_PTR + slot address.
#define CF_TSD_MAX_SLOTS 70
other loop获取流程图.png