<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Computer, Electron and Technology &#187; ubuntu</title>
	<atom:link href="http://www.donevii.com/post/tag/ubuntu/feed" rel="self" type="application/rss+xml" />
	<link>http://www.donevii.com</link>
	<description>关注技术、移动互联网以及一切 GEEK &#38; NERD 的事情</description>
	<lastBuildDate>Wed, 21 Dec 2011 10:49:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>GTK+主循环(main loop)的工作原理</title>
		<link>http://www.donevii.com/post/580.html</link>
		<comments>http://www.donevii.com/post/580.html#comments</comments>
		<pubDate>Mon, 20 Oct 2008 14:09:49 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[c/c++/c#]]></category>
		<category><![CDATA[doc]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[glib]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[循环]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=580</guid>
		<description><![CDATA[转至：http://www.builder.com.cn 我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自于用户，比如键盘事件、鼠标事件或笔点事件。还有一些事件来自于系统内部，比如定时事件、socket事件... ]]></description>
			<content:encoded><![CDATA[<p>转至：http://www.builder.com.cn</p>
<p><span style="font-family: 宋体;"><span style="font-size: small;">我们知道<span lang="EN-US">GUI应用程序都是事件驱动的。这些事件大部分都来自于用户，比如键盘事件、鼠标事件或笔点事件。还有一些事件来自于系统内部，比如定时事件、socket事件和其它文件事件等等。在没有任何事件的情况下，应用程序处于睡眠状态。</span></span></span></p>
<p><span style="font-family: 宋体;" lang="EN-US"><span style="font-size: small;"> </span></span></p>
<p><span style="font-family: 宋体;"><span style="font-size: small;">因为这种事件驱动机制，<span lang="EN-US">GUI应用程序都毫无例外的需要一个主循环(main loop)。主循环(main loop)控制应用程序什么时候进入睡眠状态，什么时候被唤醒。主循环实现得好，应用程序才能工作正常又省电。</span></span></span></p>
<p><span style="font-family: 宋体;" lang="EN-US"><span style="font-size: small;"> </span></span></p>
<p><span style="font-family: 宋体;" lang="EN-US"><span style="font-size: small;">Win32 GUI应用程序的主循环是我们比较熟悉的，其大致如下：</span></span></p>
<table style="border: medium none; background: #e6e6e6 none repeat scroll 0% 0%; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0" bgcolor="#e6e6e6">
<tbody>
<tr>
<td style="border: 0.5pt solid windowtext; padding: 0cm 5.4pt; width: 426.1pt; background-color: transparent;" width="568" valign="top">
<p align="left"><span style="font-family: Times New Roman;"><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span> </span></span><span style="color: #009900;" lang="EN-US">// Main message loop:</span></span></span></p>
<p align="left"><span style="font-family: Times New Roman;"><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span> </span></span><span style="color: blue;" lang="EN-US">while</span><span style="color: black;" lang="EN-US"> (</span><span style="color: #a000a0;" lang="EN-US">GetMessage</span><span style="color: black;" lang="EN-US">(&amp;</span><span style="color: gray;" lang="EN-US">msg</span><span style="color: black;" lang="EN-US">, </span><span style="color: #a000a0;" lang="EN-US">NULL</span><span style="color: black;" lang="EN-US">, 0, 0)) </span></span></span></p>
<p align="left"><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"><span> </span>{</span></span></span></p>
<p align="left"><span style="font-family: Times New Roman;"><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span> </span></span><span style="color: blue;" lang="EN-US">if</span><span style="color: black;" lang="EN-US"> (!</span><span style="color: #a000a0;" lang="EN-US">TranslateAccelerator</span><span style="color: black;" lang="EN-US">(</span><span style="color: gray;" lang="EN-US">msg</span><span style="color: black;" lang="EN-US">.</span><span style="color: gray;" lang="EN-US">hwnd</span><span style="color: black;" lang="EN-US">, </span><span style="color: gray;" lang="EN-US">hAccelTable</span><span style="color: black;" lang="EN-US">, &amp;</span><span style="color: gray;" lang="EN-US">msg</span><span style="color: black;" lang="EN-US">)) </span></span></span></p>
<p align="left"><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"><span> </span>{</span></span></span></p>
<p align="left"><span style="font-family: Times New Roman;"><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span> </span></span><span style="color: #880000;" lang="EN-US">TranslateMessage</span><span style="color: black;" lang="EN-US">(&amp;</span><span style="color: gray;" lang="EN-US">msg</span><span style="color: black;" lang="EN-US">);</span></span></span></p>
<p align="left"><span style="font-family: Times New Roman;"><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span> </span></span><span style="color: #a000a0;" lang="EN-US">DispatchMessage</span><span style="color: black;" lang="EN-US">(&amp;</span><span style="color: gray;" lang="EN-US">msg</span><span style="color: black;" lang="EN-US">);</span></span></span></p>
<p align="left"><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"><span> </span>}</span></span></span></p>
<p><span style="font-family: Times New Roman;"><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span> </span>}</span></span></span></td>
</tr>
</tbody>
</table>
<p><span style="font-family: 宋体;" lang="EN-US"><span style="font-size: small;"> </span></span></p>
<p><span style="font-size: small;"><span style="font-family: 宋体;">在这个主循环中，它不断的从消息队列中提取消息，然后分发给消息的目标</span><span lang="EN-US"><span style="font-family: Times New Roman;">(</span></span><span style="font-family: 宋体;">通常是窗口</span><span lang="EN-US"><span style="font-family: Times New Roman;">)</span></span><span style="font-family: 宋体;">，直到</span><span lang="EN-US"><span style="font-family: Times New Roman;">GetMessage</span></span><span style="font-family: 宋体;">返回</span><span lang="EN-US"><span style="font-family: Times New Roman;">FALSE</span></span><span style="font-family: 宋体;">（收到</span><span lang="EN-US"><span style="font-family: Times New Roman;">WM_QUIT</span></span><span style="font-family: 宋体;">消息，一般调用</span><span lang="EN-US"><span style="font-family: Times New Roman;">PostQuitMessage</span></span><span style="font-family: 宋体;">）为止，如果队列中没有消息，应用程序就进入睡眠状态。这种方法简单明了，缺陷也是明显的，它只能挂在消息队列上，而不能同时挂在多个</span><span style="color: black; font-family: 宋体;">事件</span><span style="font-family: 宋体;">源上</span><span lang="EN-US"><span style="font-family: Times New Roman;">(</span></span><span style="font-family: 宋体;">如管道和</span><span lang="EN-US"><span style="font-family: Times New Roman;">socket</span></span><span style="font-family: 宋体;">等</span><span lang="EN-US"><span style="font-family: Times New Roman;">)</span></span><span style="font-family: 宋体;">。要挂在多个</span><span style="color: black; font-family: 宋体;">事件</span><span style="font-family: 宋体;">源上，需要使用其它方式，比如用</span><span lang="EN-US"><span style="font-family: Times New Roman;">WaitForMultipleObjects</span></span><span style="font-family: 宋体;">，那就比较麻烦了。</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: 宋体;">而在</span><span lang="EN-US"><span style="font-family: Times New Roman;"><a href="http://www.donevii.com/post/tag/gtk" class="st_tag internal_tag" rel="tag" title="Posts tagged with gtk">GTK</a>+</span></span><span style="font-family: 宋体;">应用程序中，其</span><span style="font-family: 宋体;">主循环<span lang="EN-US">(main loop)更加简单，但是非常的不明了：</span></span></span></p>
<table style="border: medium none; background: #e6e6e6 none repeat scroll 0% 0%; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0" bgcolor="#e6e6e6">
<tbody>
<tr>
<td style="border: 0.5pt solid windowtext; padding: 0cm 5.4pt; width: 426.1pt; background-color: transparent;" width="568" valign="top"><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman; font-size: small;">gtk_main ();</span></span></td>
</tr>
</tbody>
</table>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: 宋体;">不少人用</span><span lang="EN-US"><span style="font-family: Times New Roman;">GTK+</span></span><span style="font-family: 宋体;">写了很长时间的程序，还是觉得这行代码很神秘，不知道里面到底干了什么。本文试图分析一下</span><span lang="EN-US"><span style="font-family: Times New Roman;">gtk_main</span></span><span style="font-family: 宋体;">的工作原理：</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">gtk_main</span></span><span style="font-family: 宋体;">主要是对</span><span lang="EN-US"><span style="font-family: Times New Roman;"><a href="http://www.donevii.com/post/tag/glib" class="st_tag internal_tag" rel="tag" title="Posts tagged with glib">glib</a></span></span><span style="font-family: 宋体;">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">main loop</span></span><span style="font-family: 宋体;">的包装，基本上分为三步：</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;">1.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span></span><span style="font-family: 宋体;"><span style="font-size: small;">调用初始化函数。</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;">2.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">进入</span><span lang="EN-US"><span style="font-family: Times New Roman;">glib main loop</span></span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;">3.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">调用</span><span lang="EN-US"><span style="font-family: Times New Roman;">~</span></span><span style="font-family: 宋体;">初始化函数。</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: 宋体;">所以弄清楚</span><span lang="EN-US"><span style="font-family: Times New Roman;">glib main loop</span></span><span style="font-family: 宋体;">之后，</span><span lang="EN-US"><span style="font-family: Times New Roman;">gtk_main</span></span><span style="font-family: 宋体;">的实现也就尽收眼底了，本文重点分析</span><span lang="EN-US"><span style="font-family: Times New Roman;">glib</span></span><span style="font-family: 宋体;">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">main loop</span></span><span style="font-family: 宋体;">的实现。</span><span lang="EN-US"><span style="font-family: Times New Roman;">main loop</span></span><span style="font-family: 宋体;">使用模式大致如下：</span></span></p>
<table style="border: medium none; background: #e6e6e6 none repeat scroll 0% 0%; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0" bgcolor="#e6e6e6">
<tbody>
<tr>
<td style="border: 0.5pt solid windowtext; padding: 0cm 5.4pt; width: 426.1pt; background-color: transparent;" width="568" valign="top">
<p align="left"><span style="font-family: Times New Roman;"><span style="font-size: small;"><span style="color: black;" lang="EN-US">loop = g_main_loop_new (</span><span style="color: #a000a0;" lang="EN-US">NULL</span><span style="color: black;" lang="EN-US">, </span><span style="color: #a000a0;" lang="EN-US">TRUE</span><span style="color: black;" lang="EN-US">);</span></span></span></p>
<p align="left"><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman; font-size: small;">g_main_loop_run (loop);</span></span></p>
</td>
</tr>
</tbody>
</table>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">g_main_loop_new</span></span><span style="color: black; font-family: 宋体;">创建一个</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">main loop</span></span><span style="color: black; font-family: 宋体;">对象，一个</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">main loop</span></span><span style="color: black; font-family: 宋体;">对象只能被一个线程使用，但一个线程可以有多个</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">main loop</span></span><span style="color: black; font-family: 宋体;">对象。在</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">GTK+</span></span><span style="color: black; font-family: 宋体;">应用中，一个线程使用多个</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">main loop</span></span><span style="color: black; font-family: 宋体;">的主要用途是实现模态对话框，它在</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">gtk_dialog_run</span></span><span style="color: black; font-family: 宋体;">函数里创建一个新的</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">main loop</span></span><span style="color: black; font-family: 宋体;">，通过该</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">main loop</span></span><span style="color: black; font-family: 宋体;">分发消息，直到对话框关闭为止。</span></span></p>
<p><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">g_main_loop_run</span></span><span style="color: black; font-family: 宋体;">则是进入主循环，它会一直阻塞在这里，直到让它退出为止。有事件时，它就处理事件，没事件时就睡眠。</span></span></p>
<p><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">g_main_loop_quit</span></span><span style="font-family: 宋体;">则是用于退出</span><span style="color: black; font-family: 宋体;">主循环，相当于</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">Win32</span></span><span style="color: black; font-family: 宋体;">下的</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">PostQuitMessage</span></span><span style="font-family: 宋体;">函数。</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">Glib main loop</span></span><span style="color: black; font-family: 宋体;">的最大特点就是支持多事件源，使用非常方便。来自用户的键盘和鼠标事件、来自系统的定时事件和</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">socket</span></span><span style="color: black; font-family: 宋体;">事件等等，还支持一个称为</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">idle</span></span><span style="color: black; font-family: 宋体;">的事件源，其主要用途是实现异步事件。</span><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;">Main loop</span></span><span style="color: black; font-family: 宋体;">的基本组成如下图所示：</span></span></p>
<p><span style="font-size: small;"><span lang="EN-US"></span></span></p>
<p><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/absurd/211144/o_mainloop_struct.jpg" alt="" /></span></span></span></p>
<p><span style="color: black;" lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">GMainLoop</span></span><span style="font-family: 宋体;">的主要部件是</span><span lang="EN-US"><span style="font-family: Times New Roman;">GMainContext</span></span><span style="font-family: 宋体;">，</span><span lang="EN-US"><span style="font-family: Times New Roman;">GMainContext</span></span><span style="font-family: 宋体;">可以在多个</span><span lang="EN-US"><span style="font-family: Times New Roman;">GMainLoop</span></span><span style="font-family: 宋体;">间共享，但要求这些</span><span lang="EN-US"><span style="font-family: Times New Roman;">GMainLoop</span></span><span style="font-family: 宋体;">都在同一个线程中运行，前面提到的模态对话框就属于这一类。</span><span lang="EN-US"><span style="font-family: Times New Roman;">GMainContext</span></span><span style="font-family: 宋体;">通常由多个</span><span lang="EN-US"><span style="font-family: Times New Roman;">GSource</span></span><span style="font-family: 宋体;">组成，</span><span lang="EN-US"><span style="font-family: Times New Roman;">GSource</span></span><span style="font-family: 宋体;">是事件源的抽象，任何事件源，只要实现</span><span lang="EN-US"><span style="font-family: Times New Roman;">GSource</span></span><span style="font-family: 宋体;">规定的接口，都可以挂到</span><span lang="EN-US"><span style="font-family: Times New Roman;">GMainContext</span></span><span style="font-family: 宋体;">中来。</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">GSource</span></span><span style="font-family: 宋体;">的接口函数有：</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">1.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">gboolean (*prepare)<span> </span>(GSource<span> </span>*source, gint<span> </span>*timeout_);</span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">进入睡眠之前，在</span><span lang="EN-US"><span style="font-family: Times New Roman;">g_main_context_prepare</span></span><span style="font-family: 宋体;">里，</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">调用所有</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">prepare</span></span><span style="font-family: 宋体;">函数，计算最小的</span><span lang="EN-US"><span style="font-family: Times New Roman;">timeout</span></span><span style="font-family: 宋体;">时间，该时间决定下一次睡眠的时间。</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">2.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">gboolean (*check)<span> </span>(GSource<span> </span>*source); poll</span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">被唤醒后，在</span><span lang="EN-US"><span style="font-family: Times New Roman;">g_main_context_check</span></span><span style="font-family: 宋体;">里，</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">调用所有</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">check</span></span><span style="font-family: 宋体;">函数，检查是否有</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">已经准备好了。如果</span><span lang="EN-US"><span style="font-family: Times New Roman;">poll</span></span><span style="font-family: 宋体;">是由于错误或者超时等原因唤醒的，就不必进行</span><span lang="EN-US"><span style="font-family: Times New Roman;">dispatch</span></span><span style="font-family: 宋体;">了。</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">3.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">gboolean (*dispatch) (GSource*source, GSourceFunc callback,gpointer user_data); </span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">当有</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">准备好了，在</span><span lang="EN-US"><span style="font-family: Times New Roman;">g_main_context_dispatch</span></span><span style="font-family: 宋体;">里，</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">调用所有</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">dispatch</span></span><span style="font-family: 宋体;">函数，去分发消息。</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">4.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">void<span> </span>(*finalize) (GSource<span> </span>*source); </span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">在</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">被移出时，</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">调用该函数去销毁</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">。</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">Main loop</span></span><span style="font-family: 宋体;">的工作流程简图如下：</span></span></p>
<p><span lang="EN-US"></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/absurd/211144/o_mainloop_workflow.jpg" alt="" /></span></span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: 宋体;">下面我们看看几个内置</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">的实现机制：</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Times New Roman;"><strong><span lang="EN-US">Idle</span></strong><span lang="EN-US"> </span></span><span style="font-family: 宋体;">它主要用实现异步事件，功能类似于</span><span lang="EN-US"><span style="font-family: Times New Roman;">Win32</span></span><span style="font-family: 宋体;">下的</span><span lang="EN-US"><span style="font-family: Times New Roman;">PostMessage</span></span><span style="font-family: 宋体;">。但它还支持重复执行的特性，根据用户注册的回调函数的返回值而定。</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">1.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">g_idle_prepare</span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">把超时设置为</span><span lang="EN-US"><span style="font-family: Times New Roman;">0</span></span><span style="font-family: 宋体;">，也就是即时唤醒，不进入睡眠状态。</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">2.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">g_idle_check </span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">始终返回</span><span lang="EN-US"><span style="font-family: Times New Roman;">TRUE</span></span><span style="font-family: 宋体;">，表示准备好了。</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">3.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">g_idle_dispatch </span></span></span><span style="font-family: 宋体;"><span style="font-size: small;">调用用户注册的回调函数。</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: Times New Roman;"><strong><span lang="EN-US">Timeout</span></strong><span lang="EN-US"> </span></span><span style="font-family: 宋体;">它主要用于实现定时器，支持一次定时和重复定时，根据用户注册的回调函数的返回值而定。</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">1.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">g_timeout_prepare </span></span></span><span style="font-family: 宋体;"><span style="font-size: small;">计算下一次的超时时间。</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">2.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">g_timeout_check </span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">检查超时时间是否到了，如果到了就返回</span><span lang="EN-US"><span style="font-family: Times New Roman;">TRUE</span></span><span style="font-family: 宋体;">，否则返回</span><span lang="EN-US"><span style="font-family: Times New Roman;">FALSE</span></span><span style="font-family: 宋体;">。</span></span></p>
<p><span style="font-family: Times New Roman;"><span lang="EN-US"><span style="font-size: small;">3.</span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span><span lang="EN-US"><span style="font-size: small;">g_timeout_dispatch</span></span></span><span style="font-family: 宋体;"><span style="font-size: small;">调用用户注册的回调函数。</span></span></p>
<p><span lang="EN-US"><span style="font-family: Times New Roman;"><span style="font-size: small;"> </span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: 宋体;">线程可以向自己的</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">中增加</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">，也可以向其它线程的</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">增加</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">。向自己的</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">中增加</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">时，</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">已经唤醒了，所以不会存在什么问题。而向其它线程的</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">增加</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">时，对方线程可能正挂在</span><span lang="EN-US"><span style="font-family: Times New Roman;">poll</span></span><span style="font-family: 宋体;">里睡眠，所以要想法唤醒它，否则</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">可能来不及处理。在</span><span lang="EN-US"><span style="font-family: Times New Roman;"><a href="http://www.donevii.com/post/tag/linux" class="st_tag internal_tag" rel="tag" title="Posts tagged with linux">Linux</a></span></span><span style="font-family: 宋体;">下，这是通过</span><span lang="EN-US"><span style="font-family: Times New Roman;">wake_up_pipe</span></span><span style="font-family: 宋体;">管道实现的，</span><span lang="EN-US"><span style="font-family: Times New Roman;">mainloop</span></span><span style="font-family: 宋体;">在</span><span lang="EN-US"><span style="font-family: Times New Roman;">poll</span></span><span style="font-family: 宋体;">时，它除了等待所有的</span><span lang="EN-US"><span style="font-family: Times New Roman;">Source</span></span><span style="font-family: 宋体;">外，还会等待</span><span lang="EN-US"><span style="font-family: Times New Roman;">wake_up_pipe</span></span><span style="font-family: 宋体;">管道。要唤醒</span><span lang="EN-US"><span style="font-family: Times New Roman;">poll</span></span><span style="font-family: 宋体;">，调用</span><span lang="EN-US"><span style="font-family: Times New Roman;">g_main_context_wakeup_unlocked</span></span><span style="font-family: 宋体;">向</span><span lang="EN-US"><span style="font-family: Times New Roman;">wake_up_pipe</span></span><span style="font-family: 宋体;">里写入字母</span><span lang="EN-US"><span style="font-family: Times New Roman;">A</span></span><span style="font-family: 宋体;">就行了。</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/580.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

