CFRunLoopRef CFRunLoopGetCurrent(void) {
CHECK_FOR_FORK();
CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(__CFTSDKeyRunLoop);
if (rl) return rl;
return _CFRunLoopGet0(pthread_self());
}
- RunLoop --- CHECK_FOR_FORK()
Forking is a system call where a process creates a copy of itself. CHECK_FOR_FORK
is a boolean value in the code which checks whether the given process was forked.
在Mac_OS中有用: (current thread 是不是 从别的进程fork()过来的?)
-
do {...} while (0)
在宏定义中的作用
使用do{...}while(0)构造后的宏定义不会受到大括号、分号等的影响,总是会按你期望的方式调用运行。
- linux中
fork()
函数
入门:一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
TSD是
thread special data
,
表示线程私有数据,在 C++ 中,全局变量可以被所有线程访问,局部变量只有函数内部可以访问。而 TSD 的作用就是能够在同一个线程的不同函数中被访问。(转载,感觉说的挺对。)__CFTSDKeyRunLoop
是CFInternal.h
的一个枚举值, 其他的值如下:
// Foundation uses 20-40
// Foundation knows about the value of __CFTSDKeyAutoreleaseData1
enum {
__CFTSDKeyAllocator = 1,
__CFTSDKeyIsInCFLog = 2,
__CFTSDKeyIsInNSCache = 3,
__CFTSDKeyIsInGCDMainQ = 4,
__CFTSDKeyICUConverter = 7,
__CFTSDKeyCollatorLocale = 8,
__CFTSDKeyCollatorUCollator = 9,
__CFTSDKeyRunLoop = 10,
__CFTSDKeyRunLoopCntr = 11,
__CFTSDKeyMachMessageBoost = 12, // valid only in the context of a CFMachPort callout
__CFTSDKeyMachMessageHasVoucher = 13,
// autorelease pool stuff must be higher than run loop constants
__CFTSDKeyAutoreleaseData2 = 61,
__CFTSDKeyAutoreleaseData1 = 62,
__CFTSDKeyExceptionData = 63,
};
- _CFGetTSD 以枚举值[slot]为key在
__CFTSDTable
.data
上查找
// CFPlatform.c
// For the use of CF and Foundation only
CF_EXPORT void *_CFGetTSD(uint32_t slot) {
// CF_TSD_MAX_SLOTS =70,
if (slot > CF_TSD_MAX_SLOTS) {
_CFLogSimple(kCFLogLevelError, "Error: TSD slot %d out of range (get)", slot);
HALT;
}
__CFTSDTable *table = __CFTSDGetTable();
if (!table) {
// Someone is getting TSD during thread destruction. The table is gone, so we can't get any data anymore.
_CFLogSimple(kCFLogLevelWarning, "Warning: TSD slot %d retrieved but the thread data has already been torn down.", slot);
return NULL;
}
uintptr_t *slots = (uintptr_t *)(table->data);
return (void *)slots[slot];
}
- __CFTSDGetTable
// Get or initialize a thread local storage. It is created on demand.
static __CFTSDTable *__CFTSDGetTable() {
__CFTSDTable *table = (__CFTSDTable *)__CFTSDGetSpecific();
// Make sure we're not setting data again after destruction.
if (table == CF_TSD_BAD_PTR) {
return NULL;
}
// Create table on demand
if (!table) {
// This memory is freed in the finalize function
table = (__CFTSDTable *)calloc(1, sizeof(__CFTSDTable));
// Windows and Linux have created the table already, we need to initialize it here for other platforms. On Windows, the cleanup function is called by DllMain when a thread exits. On Linux the destructor is set at init time.
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
pthread_key_init_np(CF_TSD_KEY, __CFTSDFinalize);
#endif
__CFTSDSetSpecific(table);
}
return table;
}
- _CFGetTSD 获取线程私有数据的Method。
参数:slot 枚举值 eg: __CFTSDKeyRunLoop