Run Loop
运行循环
app 程序只有不停地运行, 能力一直响应用户的操作
Run Loop 两大性能:
- 睡眠中,期待音讯
- 解决音讯
从睡眠中 -> 解决音讯, 须要一个唤醒的过程
1、讲讲 RunLoop, 我的项目中有用到吗?
RunLoop 的根本作用:
放弃程序的继续运行
节俭 CPU 的资源,进步程序的性能(没有事件,就请休眠,不要功耗。有事件,就解决)
2、RunLoop 外部实现逻辑?
- Core Foundation 中对于 RunLoop 的 5 个类:
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef
-
__CFRunLoop
的数据结构
struct __CFRunLoop {
CFRuntimeBase _base;
pthread_mutex_t _lock; /* locked for accessing mode list */
__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;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
// 这里有一个汇合
CFMutableSetRef _modes;
struct _block_item *_blocks_head;
struct _block_item *_blocks_tail;
CFAbsoluteTime _runTime;
CFAbsoluteTime _sleepTime;
CFTypeRef _counterpart;
};
3、RunLoop 和线程的关系?
- 每条线程,都有惟一的一个,与之对应的 RunLoop 对象
runloops[thread] = runloop
- RunLoop 保留在一个全局的 Dictionary 里,线程作为 Key, RunLoop 作为 Value
- 线程刚创立时,并没有 RunLoop 对象,RunLoop 会在第一次获取它时,创立
- RunLoop 会在线程完结时,销毁
线程都没有了,runloop 也就没有意义了
子线程,要什么 runloop?
没有 runloop , 就是命令行,调用一次就完结
有了 runloop, 能够重复休眠、唤醒、解决音讯
- 主线程的 RunLoop 曾经主动获取(创立),子线程默认没有开启 RunLoop
子线程中,获取一下 currentRunLoop, 就创立开启了 RunLoop
CFRunLoopRef CFRunLoopGetCurrent(void) {CHECK_FOR_FORK();
CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(__CFTSDKeyRunLoop);
if (rl) return rl;
// 从这里拿
return _CFRunLoopGet0(pthread_self());
}
进入详情
// should only be called by Foundation
// t==0 is a synonym for "main thread" that always works
CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {if (pthread_equal(t, kNilPthreadT)) {t = pthread_main_thread_np();
}
__CFLock(&loopsLock);
if (!__CFRunLoops) {__CFUnlock(&loopsLock);
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());
CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);
if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) {CFRelease(dict);
}
CFRelease(mainLoop);
__CFLock(&loopsLock);
}
CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
__CFUnlock(&loopsLock);
if (!loop) {CFRunLoopRef newLoop = __CFRunLoopCreate(t);
__CFLock(&loopsLock);
// 从字典外面,获取 runloop 对象
// __CFRunLoops 字典
// pthreadPointer(t),键 key
loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
// runloop 对象 loop 不存在,就新建
if (!loop) {
// 字典中,设置
// __CFRunLoops 字典
// pthreadPointer(t),键 key
// newLoop,值 value
CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop);
loop = newLoop;
}
// don't release run loops inside the loopsLock, because CFRunLoopDeallocate may end up taking it
__CFUnlock(&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;
}
4、timer 和 runloop 的关系?
5、程序中增加每 3 秒响应一次的 NSTimer, 当拖动 tableView 时 timer 可能无奈响应,要怎么解决?
6、RunLoop 是怎么响应用户操作的,具体流程是什么样的?
7、说说 RunLoop 的几种状态
8、runloop 的 mode 作用是什么?
应用的代码,目前最新 1153