这一篇就接上篇,说说CEF的线程模型,因为在CEF框架的main entry中,主要的三个函数CefInitialize、CefRunMessageLoop和CefShutdown都和这个模型有关。
官方文档主要参考两篇:
CEF框架是基于Chromium的代码框架来实现的,所以CEF的进程与线程模型就都使用的是Chromuim的模型框架。所以,除了CEF项目的代码,还需要参考CEF LIB和chromium的代码:
网上有一些使用翻译软件直接翻译的文章,不太建议看,实在是太难理解,不如直接看google的英文资料+代码,理解起来比较快。
我针对资料和代码的理解,画了一张大致的图:
几个大的框就是CEF框架拥有的几个子进程:
每个进程中包含的内容基本上是一样的,我图中就是以Browser进程为例。
在Chromium中,有一个重要的概念:Sequence,官方也给出了一个非常好的说明文档:[Chromium Sequence]
一个进程中的多个线程,一般来说都是共享同样的内存空间,所以需要解决线程并行执行期间,数据的准确性问题:
一般的解决办法有两类:
chromium对这个通讯方式给出了更具体的实现方式:Sequence。
简单的说,就是多个任务的一个有序集合,这个有序集合在一个虚拟的线程上运行,这个虚拟的线程可以在实际运行过程中,由不同的实际线程(Physical thread)来承载。
至于这个承载方式,chromium也给出了选择方式:
也就是一个对多对的关系,类似线程池,在chromium框架中有一个SequenceManager类,就是用来做这个东西的调度用的。
调度过程大致如下:
Google的官方文档都已经一一列举出来了:
Task: A unit of work to be processed. Effectively a function pointer with optionally associated state. In Chrome this is base::OnceCallback and base::RepeatingCallback created via base::BindOnce and base::BindRepeating, respectively. (documentation).
简单的说,一个task就可以对应一个任务,或者换到代码里的概念就是一个函数,这个任务或者函数需要被执行。
void TaskA() {}
void TaskB(int v) {}
auto task_a = base::BindOnce(&TaskA);
auto task_b = base::BindOnce(&TaskB, 42);