GMainLoop的主要部件是GMainContext,GMainContext可以在多个GMainLoop间共享,
但要求这些GMainLoop都在同一个线程中运行,前面提到的模态对话框就属于这一类。
GMainContext通常由多个GSource组成,GSource是事件源的抽象,
任何事件源,只要实现GSource规定的接口,都可以挂到GMainContext中来。
GSource的接口函数有:
1. gboolean (*prepare) (GSource *source, gint *timeout_);
进入睡眠之前,在g_main_context_prepare里,mainloop调用所有Source的prepare函数,
计算最小的timeout时间,该时间决定下一次睡眠的时间。
2. gboolean (*check) (GSource *source);
poll被唤醒后,在g_main_context_check里,mainloop调用所有Source的check函数,检查是否有Source已经准备好了。
如果poll是由于错误或者超时等原因唤醒的,就不必进行dispatch了。
3. gboolean (*dispatch) (GSource*source, GSourceFunc callback,gpointer user_data);
当有Source准备好了,在g_main_context_dispatch里,mainloop调用所有Source的dispatch函数,去分发消息。
4. void (*finalize) (GSource *source);
在Source被移出时,mainloop调用该函数去销毁Source。
基本上,所有需要异步操作的地方都可以用事件循环。像文件、管道、设备、套接字、定时器、idle和其他自定义的事件都可以产生事件.
今天,让我们简单的了解下GMainLoop, GMainContext和GSource。
要让GMainLoop能够处理事件,首先就必须把它们加到GMainLoop去。
首先我们需要了解事件循环的三个基本结构:GMainLoop, GMainContext和GSource。
它们之间的关系是这样的:
GMainLoop -> GMainContext -> {GSource1, GSource2, GSource3......}
每个GmainLoop都包含一个GMainContext成员,而这个GMainContext成员可以装各种各样的GSource,GSource则是具体的各种Event处理逻辑了。在这里,可以把GMainContext理解为GSource的容器。(不过它的用处不只是装GSource)