Gecko 线程分析一

线程管理及主要线程

作为一个浏览器内核,Gecko所要完成的任务是非常繁杂的,其主要任务就是根据用户提供的资源地址(网址或本地文件路径),通过http协议从Web服务器中取得页面文档,然后解析其内容,最后根据一定的约定在浏览器指定区域中显示出页面,其中往往涉及网络编程及图形界面编程,而大家通常都知道的是网络编程中的连接、读取数据等往往需要考虑到服务器端的情况,一般采用异步方式来确保有效处理服务端返回的数据包括连接不成功、错误处理等;而图形界面的处理往往需要采用一个主消息循环及回调函数的方式来处理用户的动作,为了给用户提供平滑的操作而又兼顾后台服务器的不确定性,一个可行的浏览器内核必须充分利用多线程来协调处理复杂的应用场景,只有这样才能高效的完成其所要完成的任务,初步了解Gecko内核的线程模型及相关线程管理的知识,对了解Gecko是非常有帮助的,下面初步了解Gecko是如何进行线程管理及其主要线程实现。

Gecko线程模型

为了统一接口编程,Gecko将其线程模型按照组件的方式来处理,定义的接口主要有nsIRunnablensIEventTargetnsIThreadnsIThreadManagernsIThreadPool,其中nsIThreadManagernsThreadManager来实现(nsI开头的一般为接口一般有ns开头的来实现),它主要用于来管理所有的nsThread,包括创建nsThread实例,并通过维护一些系统原生线程的属性可以判断同一段代码是在什么线程的上下文中调用,从而可作出不同的处理,如GetIsMainThread可以判定当前执行线程是否为主线程,这一点在Gecko中应该得到了充分的应用,同时nsThreadManager的实例属于单例模式,在第一次启用XPCOM组件时由NS_InitXPCOM3实例化出来,以供以后管理nsThread(位置gecko/xpcom/threads/nsThread.cpp)使用。

gecko的线程管理位于:gecko/xpcom/threads中:


nsIRunnable:


这个接口是所有events/runnable对象的基类。(events/runnable在线程中调度)

具体的事件调度情况在nsRunnable中体现。在此就不多赘述了,之后会进行详细分析。

nsThread的类图:



nsThread代表一个普通的线程。

在其构造函数中会初始化它并启动原生线程,它同时增加了EventQueueThreadObserver的概念

函数入口为nsThread::ThreadFunc

在线程的整个周期中也即nsThread::ThreadFunc中不断的处理外部线程或本身向其EventQueueDispatch来的Event,同时每处理一个Event之前都会检查其是否存在Observer,如存在则先让Observer调用其OnProcessNextEvent来处理该Event,然后调用Event本身提供的run方法,这样增加了nsThread处理Event的灵活性

nsThread统一由nsThreadManager来创建,通过调用其Shutdown方法来结束该线程;并提供了一组外部接口来进行线程管理操作

如:
NS_NewThread
NS_GetMainThreadNS_DispatchToMainThreadNS_ProcessNextEvent等以供不同线程调用,同时保证线程安全(文件位置:gecko/xpcom/glue/nsThreadUtils.cpp

       nsThreadPool代表一组线程(即线程池),当外部向其Dispatch一个Event时它先会向其中的EventQueue添加该Event,然后它会根据设置的参数来决定是否分配一个nsThread来处理该Event,一旦创建了一些nsThread则将其维护在mThreads队列中,同时向该nsThreadDispatch这个nsThreadPool实例以让该nsThread去执行该nsThreadPoolrun方法,这样可保证线程池中的每个nsThread的执行体都是nsThreadPool中的run方法,在其run方法中会根据是否空闲等条件自动ShutDown一些暂时不用的nsThread,以达到线程池的目的,即当任务事件Event繁多的时候多开启一些线程来处理,一旦任务完成则释放大部分空闲线程,保持一小部分线程以等待新任务的分配及提交;nsThreadPool在异步读取网络流数据的时候会经常用到。


Gecko主要线程

MainThreadGecko的主线程,也即进程启动时的执行序列,它主要处理图形界面的消息循环以及其他线程向它Dispatch过来的Event,这样可以有机的结合图形界面的处理及网络数据的读取、解析、渲染等。MainThread线程充分利用了Gecko线程模型特点,既能处理原生的窗口消息,又可及时处理其它线程通知给它的Event,其执行主体往往是Gecko的核心,据初步统计其执行时间往往占整个程序执行时间的90%以上,其效率的高低直接决定了是否会让用户产生阻塞停顿的感觉。其主要实现逻辑是在启动XPCOM当中会在nsThreadManager初始化时自动产生一个nsThread实例mMainThread,它代表进程启动时的执行序列,待该执行序列完成其他基本准备后,在nsBaseAppShell::Init中将其Observer设置为nsBaseAppShell实例本身

先分析到这,待续。。


参考文献:

https://developer.mozilla.org/en/docs/The_Thread_Manager

https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Threads

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章