GLib 实现了一个功能强大的事件循环分发处理机制,被抽象成为 GMainLoop,用于循环处理事件源上的事件。每个 GMainLoop 都工作在指定的 GMainContext 上。事件源在 GLib 中则被抽象成了 GSource。在 GMainContext 中有一个 GSource 列表。GLib 内部定义实现了三种类型的事件源,分别是 Idle, Timeout 和 I/O。同时也支持创建自定义的事件源。
自定义事件源的基本作用
自定义的事件源可以用来将外部信号(事件)挂到程序中的指定主循环上,从而在 g_main_loop_run 中可以响应这些事件。
如何创建自定义事件源
GLib 提供了一系列的接口用于创建自定义的事件源,下面我们先讲解一下创建事件源的基本函数和数据结构,最后给出一些实例。
自定义的事件源是一个继承 GSource 的结构体,即自定义事件源的结构体 的第一个成员是 GSource 结构体, 其后便可放置程序所需数据,
实现了事件源数据结构的定义之后,还需要实现事件源所规定的接口,主要为 prepare, check, dispatch, finalize 等事件处理函数(回调函数),它们包含于 GSourceFuncs 结构体中。将 GSourceFuncs 结构以及事件源结构的存储空间宽度作为参数传给 g_source_new 便可构造一个新的事件源,继而可使用 g_source_attach 函数将新的事件源添加到主循环上下文中。
Timeout 类事件源,GLib 也提供了预定义的定时器事件源,其用法与 GLib 预定义的空闲事件源类似。例如:
如果要自定义定时器类型的事件源,只需让事件源的 prepare 与 check 接口在时间超过所设定的时间间隔时返回 TRUE, 否则返回 FALSE。
I/O 类型的事件源要稍微难理解一些,因为涉及到了操作系统层面的 poll 机制。所谓 poll 机制,就是操作系统提供的对文件描述符所关联的 I/O 的状态监视功能 ,例如向文件中写入数据 ,那么 I/O 的状态可以表示为 POLLOUT, 而从文件中读取数据,那么 I/O 的状态就变为 POLLIN。GLib 为 Unix 系统与Windows 系统的 poll 机制进行了封装,并且可以将文件与主事件循环的事件源建立关联,在主循环的过程中, g_main_loop_run 会轮询各个关联到文件的事件源,并处理相应的事件响应。I/O 类型的事件源, prepare,其 check, dispatch 等接口的执行次序如下:
a. 主事件循环会首先调用 check 接口, 询问事件源是否准备好。因为此时, g_main_loop_run 尚未轮询那些与 I/O 相关联的事件源, 所以 I/O 类型的事件源, check 接口的返回值应该是 FALSE。其主事件循环调用 g_main_context_iteration 轮询各事件源,探寻是否有 I/O 类型事件源的状态发生变化,并记录变化结果。
b. 主循环调用 check 接口, 询问事件是否准备好。此时, 如果 I/O 类型事件源的状态变化符合要求,那么就返回 TRUEE,否则返回 FALSE。
c. 如果 prepare 与 check接口的返回值均为 TRUE, 那么此时主事件循环会调用 dispatch 接口分发消息。
像 Idle 类型与 Timeout 类型事件源那样,GLib 也提供了预定义的 I/O 类型事件源,
-
Glibc
+关注
关注
0文章
9浏览量
7493
发布评论请先 登录
相关推荐
评论