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
上一篇下一篇

猜你喜欢

热点阅读