WebKit之消息循环

# 消息循环

## 概述

前面介绍了线程间如何传递chromium自定义任务(task),那么在线程内,消息循环(messageloop)是如何处理这所有的消息和任务呢?本章节重点介绍消息循环的工作原理。

在Chromium里,需要处理三种类型的消息:chromium自定义的任务,Socket或者文件等IO操作以及用户界面(UI)的消息。这里面,chromium自定义任务是平台无关的,而后面两种类型的消息是平台相关的。回忆一下前面多线程模型章节中列举的众多线程,例如主线程(UI线程)需要处理UI相关的消息和自定义任务;IO线程则需要处理Socket和自定义任务;History线程则只需要处理自定义任务;其它线程需要处理消息类型不会超出以上三个线程。根据三个组合,chromium定义和实现三种相对应的类来支持它们,下面让我们来看看具体的实现吧。

##Chromium中主要的类

这是本章中最重要的三个基类,依次介绍它们:

类RunLoop:一个辅助类,主要封装消息循环MessageLoop类,其本身没有特别的功能,主要提供一组公共接口被调用,其实质是调用MessageLoop类的接口和实现。

类MessageLoop:主消息循环,原理上讲,它应该可以处理三种类型的消息,包括支持不同平台的消息。事实上,如果让它处理所有这些消息,这会让其代码结构复杂不清难以理解。因此,根据上面对各个线程的分析,消息循环也只需要三种类型,一种仅能处理自定义任务,一种能处理自定义任务和IO操作,一种是能处理自定义任务和UI消息。很自然地,Chromium定义一个基类MessageLoop用于处理自定义任务,两个子类对应于第二和第三种类型。如下图所示。对于第二和第三种MessageLoop类型,它们除了要处理任务外,还要处理平台相关的消息,为了结构清晰,chromium定义一个新的基类及其子类来负责处理它们,这就是MessagePump。MessagePump的每个子类针对不同平台和不同的消息类型。事实上,不仅如此,消息处理的主循环也在MessagePump中,这有些令人意外,后面会详细介绍。因此,MessageLoop通过实现MessagePumpDelegate的接口来负责处理Chromium自定义任务。如下图所示。

类MessagePump: 一个抽象出来的基类,可以用来处理第二和第三种消息类型。对于每个平台,它们有不同的MessagePump的子类来对应,这些子类被包含在MessageLoopForUI和MessageLoopForIO类中。


结合上面的图,针对三种类型的消息循环,三种典型的线程在不同平台所使用的类如下:

 

主线程

IO线程

History线程

Linux

MessageLoopForUI, MessagePumpGtk

MessageLoopForIO, MessagePumpLibEvent

MessageLoop, MessagePumpDefault

Windows

MessageLoopForUI, MessagePumpForUI

MessageLoopForIO, MessagePumpForIO

MessageLoop, MessagePumpDefault

Mac

MessageLoopForUI, MessagePumpMac

MessageLoopForIO, MessagePumpLibEvent

MessageLoop, MessagePumpDefault

Android

MessagePumpForUI

Android.os.Looper

SystemMessageHandler

MessagePumpAndroid

MessageLoopForIO, MessagePumpLibEvent

MessageLoop, MessagePumpDefault

对于所有平台来说,History线程所使用的类是一样的;UI线程和IO线程分别对应不同的MessagePump。相信大家注意到了,最后一个平台Android跟其它的稍有不同,那就是它的UI线程,原因在于主循环在Java层,用户界面的事件派发机制都在Java代码来处理,因而需要在Android的消息循环机制中加入对自定义任务的处理,后面会作介绍。

## 无限循环

这里面还有一个重要的部分需要介绍,那就是消息循环的主逻辑。该循环本质就是一个无限循环,不停的处理消息循环接收到的任务和消息,直到需要推出为止。如前面所述,主消息循环的逻辑在MessagePump中,而MessageLoop只是负责处理自定义的任务,MessagePump通过调用MessagePumpDelegate来达到该目的。下面是IO线程的消息处理主逻辑的时序图。


前面章节我们介绍过MessageLoop有任务队列来保存需要处理的任务,这些任务可能有不同的优先级,例如需要即时处理,或者延迟处理,或者Idle时处理。上图中,当调用DoWork时候,首先将出入任务队列(incoming task)拷贝到工作任务队列中,然后依次执行该队列中的任务。之后,同理处理调用DoDelayWork和DoIdleWork。当这些处理完后,它会阻塞和等待在IO操作。

对于Android的UI线程来说,情况稍有不同,因为主循环逻辑是由Java层的Android.os.Looper来控制的,所以MessagePumpAndroid其实是被Looper调用的。当它被调用时,其会把执行任务的工作交给MessagePumpDelegate,这里也就是MessageLoopForUI来完成,如下图所示的UI线程的消息循环主逻辑。Java层的SystemMessageHandler和C++层的MessagePumpAndroid其实都是辅助Looper调用执行chromium的自定义类的。


最后还有一个问题,就是如何等待自定义的任务。假设现在MessageLoop没有任务和消息需要处理,它应该等待Socket或者IO或者任务,OS系统支持Socket和IO唤醒它,问题是如何等待自定义任务呢?总不能忙式的检查吧,那样太耗费资源了。Chromium设计了一个巧妙的方法来解决该问题,以MessagePumpLibEvent为例:在Linux平台上,该类创建一个管道,它等待读取这个管道的内容,当有自定义的新任务到来时,写入一个字节到这个管道,从而MessageLoop被唤醒,非常地简单和直接。

## 源文件目录

base/message_ loop.h|cc

base/message_pump.h|cc

  消息循环相关的众多类基本上都位于该目录中,文件名以”message_”开头

base/android/java/src/org/chromium/base/SystemMessageHandler.java

 Android平台下支持消息循环的辅助类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用[1]: 这段代码是一个使用QT框架开发的Windows应用程序的示例。它使用了QApplication和QLabel类来创建一个简单的窗口,并在窗口中显示一段文本。通过调用app.exec()来启动应用程序的事件循环,使窗口能够响应用户的操作。[1] 引用[2]: 在QT5.8中,如果你想开发一个浏览器并调用电脑中安装的插件软件,你可以使用QWebkit。其中一种方法是使用dumpcpp工具生成插件的QActive类库文件,然后创建一个QWidget来包裹这个QActiveX类,并重新实现其中的槽函数。最后,使用QWebPage::createPlugin()函数来创建自定义的浏览器插件来调用这个新建的QWidget。然而,这种方法可能会导致图层问题,即调用的插件会一直在网页图层的顶层且无法改变。为了解决这个问题,可以使用QRegion::setMask函数来勉强解决。但是,这种方法比较麻烦,还需要修改网页的js文件,因此比较繁琐。[2] 引用[3]: 在配置QT5.8时,可以使用以下命令:./configure -release -opensource -confirm-license -prefix /opt/Qt-5.8.0-x86 -xplatform linux-g -32 -nomake -examples -nomake -tests。这个命令将配置QT5.8的编译选项,包括使用开源和商业许可证、指定安装路径、选择平台、禁用示例和测试等。[3] 问题: QT5.8 webkit的使用方法是什么? 回答: 在QT5.8中,你可以使用QWebkit来开发浏览器应用程序并调用电脑中安装的插件软件。一种方法是使用dumpcpp工具生成插件的QActive类库文件,然后创建一个QWidget来包裹这个QActiveX类,并重新实现其中的槽函数。最后,使用QWebPage::createPlugin()函数来创建自定义的浏览器插件来调用这个新建的QWidget。然而,这种方法可能会导致图层问题,即调用的插件会一直在网页图层的顶层且无法改变。为了解决这个问题,可以使用QRegion::setMask函数来勉强解决。但是,这种方法比较麻烦,还需要修改网页的js文件,因此比较繁琐。[2]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值