runloop总结:runloop基础知识

上传人:第*** 文档编号:30558801 上传时间:2018-01-30 格式:DOC 页数:9 大小:161KB
返回 下载 相关 举报
runloop总结:runloop基础知识_第1页
第1页 / 共9页
runloop总结:runloop基础知识_第2页
第2页 / 共9页
runloop总结:runloop基础知识_第3页
第3页 / 共9页
runloop总结:runloop基础知识_第4页
第4页 / 共9页
runloop总结:runloop基础知识_第5页
第5页 / 共9页
点击查看更多>>
资源描述

《runloop总结:runloop基础知识》由会员分享,可在线阅读,更多相关《runloop总结:runloop基础知识(9页珍藏版)》请在金锄头文库上搜索。

1、RunLoop 总结:RunLoop 基础知识什么是 RunLoop?顾名思义,它就是一个运行循环。一个 RunLoop 就是一个用于处理既定工作和接收到的外来事件的事件处理循环。RunLoop 的存在目的就是当线程中有任务时,保证线程忙着干活;当线程中没有任务时,让线程睡眠,以节省资料(想想看,你是在房间里一直转圈抗饿还是躺在床上睡觉更抗饿?) 。 理解了 EventLoop 就 能很好的理解 RunLoop 了。 简单的用伪代码来表示就是这样的:function loop() initialize();while (message != quit) var message = get_ne

2、xt_message();process_message(message); 关于 RunLoop,苹果的 Cocoa 和 CoreFoundation 框架都分别提供了 NSRunLoop 和 CFRunLoopRef 供开发者调用和执行操作。 CFRunLoopRef 只是一个结构体,而 NSRunLoop 是一个 NSObject 对象,必然是苹果将 CFRunLoopRef 进行了封装。 需要注意的是 NSRunLoop 并不是线程安全的,而 CFRunLoopRef 是线程安全的。 官方文档原文是:Thread safety varies depending on which API

3、 you are using to manipulate your run loop. The functions in Core Foundation are generally thread-safe and can be called from any thread. If you are performing operations that alter the configuration of the run loop, however, it is still good practice to do so from the thread that owns the run loop

4、whenever possible.The Cocoa NSRunLoop class is not as inherently thread safe as its Core Foundation counterpart. If you are using the NSRunLoop class to modify your run loop, you should do so only from the same thread that owns that run loop. Adding an input source or timer to a run loop belonging t

5、o a different thread could cause your code to crash or behave in an unexpected way.接下来,看一下 CFRunLoopRef 里都保存了哪些数据?可以从 CF 框架源码 的 CFRunLoop.h 和 CFRunLoop.c,看看 苹果对 CFRunLoopRef 的定义。 CFRunLoopRef 是 结构体_CFRunLoop *的重命名,由 typedef struct _CFRunLoop * CFRunLoopRef; 可知; _CFRunLoop 的定义:struct _CFRunLoop CFRun

6、timeBase _base;pthread_mutex_t _lock; /* locked for accessing mode list,每次读取 mode list 要加锁 */_CFPort _wakeUpPort; / used for CFRunLoopWakeUp Boolean _unused;volatile _per_run_data *_perRunData; / reset for runs of the run looppthread_t _pthread; /与该 runLoop 关联的线程uint32_t _winthread;CFMutableSetRef _

7、commonModes; / set 中保存的就是 NSRunLoopCommonModes 表示的 mode,我们也可以将自定义的 mode 添加到这个 set 里。CFMutableSetRef _commonModeItems; /添加到 NSRunLoopCommonModes 中的source/timer 等 item 都会被添加到这个 set 里,这在应用场景一中有打印出来。CFRunLoopModeRef _currentMode; /RunLoop 当前执行的是哪个 modeCFMutableSetRef _modes; / 该 runLoop 中所有的 modestruct

8、_block_item *_blocks_head;struct _block_item *_blocks_tail;CFAbsoluteTime _runTime;CFAbsoluteTime _sleepTime;CFTypeRef _counterpart;再来看一下 RunLoopMode 的结构,之前说过 RunLoopMode 中存放的是两种source/timer/observer,而 CFRunLoopModeRef 是 struct _CFRunLoopMode *重命名的(typedef struct _CFRunLoopMode *CFRunLoopModeRef;),

9、看下定义就明白了:struct _CFRunLoopMode CFRuntimeBase _base;pthread_mutex_t _lock; /* must have the run loop locked before locking this */CFStringRef _name; /mode 的 nameBoolean _stopped;char _padding3;CFMutableSetRef _sources0; / 保存所有 source0 的 setCFMutableSetRef _sources1; / 保存所有 source1 的 set CFMutableArra

10、yRef _observers; / 保存所有 observer 的数组CFMutableArrayRef _timers; / 保存所有 timer 的数组CFMutableDictionaryRef _portToV1SourceMap;_CFPortSet _portSet;CFIndex _observerMask;#if USE_DISPATCH_SOURCE_FOR_TIMERSdispatch_source_t _timerSource;dispatch_queue_t _queue;Boolean _timerFired; / set to true by the source

11、 when a timer has firedBoolean _dispatchTimerArmed;#endif#if USE_MK_TIMER_TOOmach_port_t _timerPort;Boolean _mkTimerArmed;#endif#if DEPLOYMENT_TARGET_WINDOWSDWORD _msgQMask;void (*_msgPump)(void);#endifuint64_t _timerSoftDeadline; /* TSR */uint64_t _timerHardDeadline; /* TSR */;看完上面 _CFRunLoopMode 和

12、 _CFRunLoop 的定义,关于 RunLoop 中保存的是RunLoopMode,而 RunLoopMode 中保存的才是实际的任务这点没有疑问了。如何创建一个 RunLoop?包括 MainRunLoop 在内,每一个 RunLoop 都与一个线程关联着。确切的说,是先有线程,再有 RunLoop。 关于线程与 RunLoop 的关系,在 RunLoop 官方文档的第一节讲的很清楚。 我们不用,也最好不要显示的创建 RunLoop,苹果提供了两个 API,便于我们来获取RunLoop。 CFRunLoopGetMain() 和 CFRunLoopGetCurrent(),分别用于获取

13、MainRunLoop 和当前线程的 RunLoop(在主线程中调用 CFRunLoopGetCurrent()与 CFRunLoopGetMain()获取的其实都是 MainRunLoop) 。先来看一下,这两个函数的源码实现:CFRunLoopRef CFRunLoopGetMain(void) CHECK_FOR_FORK();static CFRunLoopRef _main = NULL; / no retain needed/通过_CFRunLoopGet0 这个关键函数,取出 MainRunLoop。if (!_main) _main = _CFRunLoopGet0(pthre

14、ad_main_thread_np(); / no CAS neededreturn _main;CFRunLoopRef CFRunLoopGetCurrent(void) CHECK_FOR_FORK();CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(_CFTSDKeyRunLoop);if (rl) return rl;/通过_CFRunLoopGet0 这个关键函数,取出当前 RunLoop。return _CFRunLoopGet0(pthread_self();从以上源码,可以看出 RunLoop 是通过 _CFRunLoopGet0 函数来获

15、取的,并且以线程作为参数。 这个函数的作用与 通过 key 从 NSDictionary 获取 Value 极为相似。接下来,看一下 _CFRunLoopGet0 的实现(太长不想看,可以看下面的伪代码):static CFMutableDictionaryRef _CFRunLoops = NULL;static CFLock_t loopsLock = CFLockInit;/ should only be called by Foundation/ t=0 is a onym for main thread that always worksCF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) if (pthread_equal(t, kNilPthreadT) t = pthread_main_thread_np();_CFLock(if (!_CFRunLoops) _CFUnlock(CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, CFRunLoopRef mainLoop = _CFRunLoopCreate(pthread_main_thread_np();CFDict

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 其它办公文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号