main loop
GLib和GTK 应用的主事件循环管理着所有事件源。
GLib 实现了一个功能强大的事件循环分发处理机制,这些事件的来源有很多种比如文件描述符(文件、管道或套接字)或超时。
新类型的事件源可以通过g_source_attach()函数添加。
为了让多组独立事件源能够在不同的线程中被处理,每个事件源都会关联一个GMainContext。
一个线程只能运行一个GMainContext,但是在其他线程中能够对事件源进行添加和删除操作。 每个事件源都被赋予了优先级。默认的优先级是G_PRIORITY_DEFAULT(0)。值越小优先级越高,优先级高的事件源优先处理。
Idle函数在没有更高优先级的事件被处理的时候才会执行。
GMainLoop数据类型代表了一个主事件循环。 通过g_main_loop_new()来创建GMainLoop对象。 在添加完初始事件源后执行g_main_loop_run(),主循环将持续不断的检查每个事件源产生的新事件,然后分发它们,直到处理来自某个事件源的事件的时候触发了g_main_loop_quit()调用退出主循环为止。
image.png
GMainLoop实例能够被递归创建。在GTK 应用中经常使用这种方式来显示模态对话框。注意如果一个事件源被添加到一个GMainContext,那么它将被所有关联这个GMainContext的主线程检查和分发。 GTK 对这些函数做了些封装,例如gtk_main、gtk_mian_quit和gtk_events_pending。
main loop使用实例:
代码语言:javascript复制loop = g_main_loop_new (NULL, TRUE);
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则是用于退出主循环。
Glib main loop的最大特点就是支持多事件源,使用非常方便。来自用户的键盘和鼠标事件、来自系统的定时事件和socket事件等等,还支持一个称为idle的事件源,其主要用途是实现异步事件。
image.png