`
Joson_Coney
  • 浏览: 57229 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

GTK+主循环(main loop)的工作原理

 
阅读更多

GTK+主循环(main loop)的工作原理

 

转载时请注明出处和作者联系方式:http://blog.csdn.net/absurd

作者联系方式:Li XianJing <xianjimli at hotmail dot com>

更新时间:2007-3-17

 

我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自于用户,比如键盘事件、鼠标事件或笔点事件。还有一些事件来自于系统内部,比如定时事件、socket事件和其它文件事件等等。在没有任何事件的情况下,应用程序处于睡眠状态。

 

因为这种事件驱动机制,GUI应用程序都毫无例外的需要一个主循环(main loop)。主循环(main loop)控制应用程序什么时候进入睡眠状态,什么时候被唤醒。主循环实现得好,应用程序才能工作正常又省电。

 

Win32 GUI应用程序的主循环是我们比较熟悉的,其大致如下:

       // Main message loop:

       while (GetMessage(&msgNULL, 0, 0))

       {

              if (!TranslateAccelerator(msg.hwndhAccelTable, &msg))

              {

                     TranslateMessage(&msg);

                     DispatchMessage(&msg);

              }

       }

 

在这个主循环中,它不断的从消息队列中提取消息,然后分发给消息的目标(通常是窗口),直到GetMessage返回FALSE(收到WM_QUIT消息,一般调用PostQuitMessage)为止,如果队列中没有消息,应用程序就进入睡眠状态。这种方法简单明了,缺陷也是明显的,它只能挂在消息队列上,而不能同时挂在多个事件源上(如管道和socket)。要挂在多个事件源上,需要使用其它方式,比如用WaitForMultipleObjects,那就比较麻烦了。

 

而在GTK+应用程序中,其主循环(main loop)更加简单,但是非常的不明了:

gtk_main ();

 

不少人用GTK+写了很长时间的程序,还是觉得这行代码很神秘,不知道里面到底干了什么。本文试图分析一下gtk_main的工作原理:

 

gtk_main主要是对glibmain loop的包装,基本上分为三步:

1.         调用初始化函数。

2.         进入glib main loop

3.         调用~初始化函数。

 

所以弄清楚glib main loop之后,gtk_main的实现也就尽收眼底了,本文重点分析glibmain loop的实现。main loop使用模式大致如下:

loop = g_main_loop_new (NULLTRUE);

g_main_loop_run (loop);

 

g_main_loop_new创建一个main loop对象,一个main loop对象只能被一个线程使用,但一个线程可以有多个main loop对象。在GTK+应用中,一个线程使用多个main loop的主要用途是实现模态对话框,它在gtk_dialog_run函数里创建一个新的main loop,通过该main loop分发消息,直到对话框关闭为止。

 

g_main_loop_run则是进入主循环,它会一直阻塞在这里,直到让它退出为止。有事件时,它就处理事件,没事件时就睡眠。

 

g_main_loop_quit则是用于退出主循环,相当于Win32下的PostQuitMessage函数。

 

Glib main loop的最大特点就是支持多事件源,使用非常方便。来自用户的键盘和鼠标事件、来自系统的定时事件和socket事件等等,还支持一个称为idle的事件源,其主要用途是实现异步事件。Main loop的基本组成如下图所示:

 

GMainLoop的主要部件是GMainContextGMainContext可以在多个GMainLoop间共享,但要求这些GMainLoop都在同一个线程中运行,前面提到的模态对话框就属于这一类。GMainContext通常由多个GSource组成,GSource是事件源的抽象,任何事件源,只要实现GSource规定的接口,都可以挂到GMainContext中来。

 

GSource的接口函数有:

1.         gboolean (*prepare)  (GSource    *source, gint       *timeout_);进入睡眠之前,在g_main_context_prepare里,mainloop调用所有Sourceprepare函数,计算最小的timeout时间,该时间决定下一次睡眠的时间。

2.         gboolean (*check)    (GSource    *source); poll被唤醒后,在g_main_context_check里,mainloop调用所有Sourcecheck函数,检查是否有Source已经准备好了。如果poll是由于错误或者超时等原因唤醒的,就不必进行dispatch了。

3.         gboolean (*dispatch) (GSource*source, GSourceFunc callback,gpointer user_data); 当有Source准备好了,在g_main_context_dispatch里,mainloop调用所有Sourcedispatch函数,去分发消息。

4.         void     (*finalize) (GSource    *source); Source被移出时,mainloop调用该函数去销毁Source

 

Main loop的工作流程简图如下:

 

下面我们看看几个内置Source的实现机制:

Idle 它主要用实现异步事件,功能类似于Win32下的PostMessage。但它还支持重复执行的特性,根据用户注册的回调函数的返回值而定。

1.         g_idle_prepare把超时设置为0,也就是即时唤醒,不进入睡眠状态。

2.         g_idle_check 始终返回TRUE,表示准备好了。

3.         g_idle_dispatch 调用用户注册的回调函数。

 

Timeout 它主要用于实现定时器,支持一次定时和重复定时,根据用户注册的回调函数的返回值而定。

1.         g_timeout_prepare 计算下一次的超时时间。

2.         g_timeout_check 检查超时时间是否到了,如果到了就返回TRUE,否则返回FALSE

3.         g_timeout_dispatch调用用户注册的回调函数。

 

线程可以向自己的mainloop中增加Source,也可以向其它线程的mainloop增加Source。向自己的mainloop中增加Source时,mainloop已经唤醒了,所以不会存在什么问题。而向其它线程的mainloop增加Source时,对方线程可能正挂在poll里睡眠,所以要想法唤醒它,否则Source可能来不及处理。在Linux下,这是通过wake_up_pipe管道实现的,mainlooppoll时,它除了等待所有的Source外,还会等待wake_up_pipe管道。要唤醒poll,调用g_main_context_wakeup_unlockedwake_up_pipe里写入字母A就行了。

 

~~end~~

分享到:
评论

相关推荐

    GTK+主循环的工作原理

    ### GTK+ 主循环的工作原理详解 #### 一、引言 在GUI图形用户界面的应用程序设计中,事件驱动机制是一项核心的技术。...理解和掌握GTK+主循环的工作原理,对于深入学习GTK+乃至其他类似的GUI框架都有着重要的意义。

    Draw in GTK+(GTK+组件绘制_英文)

    1. **事件循环(Event Loop)**: GTK+使用事件循环来处理来自用户的输入和其他事件。当组件需要更新其显示时,事件循环将触发相应的处理函数。 2. **曝光事件(Exposure Events)**: 当窗口的一部分需要重新绘制时,...

    python3+GTK+3.0的示例代码(包括GUI界面的控件示例,代码没有中文注释,英文不好的别下载)

    10. **事件循环**:理解GTK+的主事件循环(main loop)如何运行,以及如何使用`Gtk.main()`启动和退出。 在深入学习这些示例代码时,建议具备一定的Python基础和英语阅读能力。同时,配合GTK+3.0的官方文档和其他...

    gtk_属性改变事件

    主循环(main loop)不断监听事件,包括属性改变事件。当事件发生时,GTK+会调用相应的处理函数,使得程序能够对事件做出反应。 7. **回调函数的编写**: 在连接到属性改变信号的回调函数中,你可以检查哪些属性...

    gtk定时器功能实现

    1. GTK Main Loop:GTK应用程序基于事件驱动模型,其核心是主循环(Main Loop)。在这个循环中,GTK会处理各种事件,包括用户交互、定时器触发等。 2. g_timeout_add()函数:这是GTK中最常用的添加定时器的函数。它...

    基于gtk编写的计算器程序

    7. 主循环(Main Loop):GTK程序通过`gtk_main()`启动主循环,等待并处理来自窗口系统的事件。 在项目中的源代码文件`count1.c`和`count.c`很可能是实现计算器功能的C语言代码,其中包含了上述GTK组件的使用以及...

    gtk空白窗口

    通过`g_main_loop_run()`启动这个循环,程序会等待并处理事件,直到调用`g_main_loop_quit()`退出循环。 6. **编译与链接**:编写GTK程序时,需要链接到GTK库。对于C语言,编译命令可能类似`gcc -o build_demo main...

    GTK写的定时提醒

    - 对于C语言实现,开发者可能使用`glib`库进行内存管理和线程操作,用`GLib Main Loop`处理事件循环。 - 如果是Python,可以使用`PyGTK`或`GTK+3`的Python绑定,Python的内置数据结构和文件操作库会简化代码编写。...

    GTK进阶学习:定时器 源代码

    通常,这可以通过`gtk_main()`或`g_main_loop_run()`实现。 6. **优化与性能**:考虑到性能,你应该谨慎使用定时器,特别是频繁触发的定时器,因为它们会占用事件循环,可能影响应用响应速度。 通过上述讲解,你...

    glib-html-2.12.13.tar.gz

    事件循环是GLib中的重要概念,它允许程序在一个主循环中处理多个输入源和定时事件。`g_main_loop`和`g_main_context`是实现这一机制的关键组件,开发者可以注册回调函数来响应特定的事件。 文件系统操作部分,GLib...

    message_pump_glib.rar_On Message

    当调用`g_main_loop_run`时,程序进入事件循环,不断调用`g_main_context_iteration`直到有退出事件发生。 在GLib中,事件可以分为两类:定时器事件和I/O事件。定时器事件通过`g_timeout_add`等函数设置,会在指定...

    用Python3编写的简单X11窗口管理器.zip

    3. **Event Loop**: 为了响应用户的输入和窗口系统的事件,窗口管理器需要一个事件循环来处理这些事件。 4. **Window Decorations**: 窗口管理器需要为窗口添加标题栏、边框、最大化/最小化按钮等装饰元素,这通常...

    c语言实现flyppy bird-带安装包

    4. **游戏循环**:游戏通常基于主循环(main game loop)进行,这个循环不断检测输入、更新游戏状态、渲染屏幕。学习如何构建和优化这样的循环至关重要。 5. **碰撞检测**:在"Flyppy Bird"中,检测小鸟与管道之间...

    计算机专业术语50个翻译.pdf

    50.main processing loop 主处理循环 主处理循环是一个编程概念,定义了程序的主循环方式。它可以在编程语言中被使用,用于实现程序的主循环方式。 计算机专业术语50个翻译为我们提供了一个计算机专业领域的概述,...

    glib常用库函数总结

    - 通过`g_main_loop_run()`函数启动glib的事件循环,可以处理来自计时器或其他事件源的事件。 #### 三、提供上层建筑的基石-socket ##### 3.1 获取网络地址 - 在网络编程中,通过`g_socket_address_new_from_...

    qemu code overview

    2. **主循环**:QEMU采用事件驱动的设计,支持异步API来处理各种事件,如文件描述符读写、定时器到期、延后工作等。全局互斥锁用于保护QEMU的核心代码,确保并发安全性。随着项目的演进,这些互斥锁正逐步被去除以...

    计算机专业术语五十个翻译.pdf

    43. Main Processing Loop(主处理循环):是程序运行的核心循环,用于处理输入、更新状态和渲染输出。 以上术语覆盖了计算机科学领域中的基础概念和组件,了解这些术语对于进行软件开发、系统维护和IT支持等工作至...

    嵌入式系统的图形用户界面.ppt

    在嵌入式领域,有多种GUI框架可供选择,如QT、GTK、Clutter、Java (Android)、DirectFB、MiniGUI和MicroWindows/NanoX等。 QT,全称Quantum Toolkit,是一个流行的跨平台C++图形用户界面库,由Nokia公司开发并维护...

Global site tag (gtag.js) - Google Analytics