﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-紫月城游戏软件</title><link>http://www.cppblog.com/kevinlynx/</link><description>低调做技术</description><language>zh-cn</language><lastBuildDate>Sat, 05 Jul 2008 04:18:14 GMT</lastBuildDate><pubDate>Sat, 05 Jul 2008 04:18:14 GMT</pubDate><ttl>60</ttl><item><title>建立异步操作组件:队列和线程</title><link>http://www.cppblog.com/kevinlynx/archive/2008/06/25/54554.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Wed, 25 Jun 2008 07:47:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/06/25/54554.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/54554.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/06/25/54554.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/54554.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/54554.html</trackback:ping><description><![CDATA[<p><font size=2>6.25.2008 </font>
<p><font size=2>Kevin Lynx </font>
<p><font size=2><strong>引言</strong> </font>
<p><font size=2>在一个高效的系统中，我们经常会将一些费时的操作转换为异步操作。例如往数据库中写日志。如果数据库<br>配置在网络上，那么往数据库中插入一些日志信息将非常慢(相对于程序其他部分)。 </font>
<p><font size=2><strong>如何转换为异步？</strong> </font>
<p><font size=2>将类似于以上过程转换为异步操作，一个典型的做法是：建立一个单独的数据库日志线程，一个线程安全的<br>队列。要写日志时，只需要往队列里放入数据，数据库日志线程则从这个队列里取数据然后完成写操作。 </font>
<p><font size=2>大致的过程类似于： </font>
<p><font size=2><strong></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">typedef&nbsp;safe_list</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;SafeList;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>SafeList&nbsp;gLogList;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;database&nbsp;thread.read&nbsp;log&nbsp;string.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">unsigned&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;__stdcall&nbsp;DBThread(&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;)<br><img id=Codehighlighter1_141_276_Open_Image onclick="this.style.display='none'; Codehighlighter1_141_276_Open_Text.style.display='none'; Codehighlighter1_141_276_Closed_Image.style.display='inline'; Codehighlighter1_141_276_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_141_276_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_141_276_Closed_Text.style.display='none'; Codehighlighter1_141_276_Open_Image.style.display='inline'; Codehighlighter1_141_276_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_141_276_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_141_276_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">&nbsp;)<br><img id=Codehighlighter1_165_235_Open_Image onclick="this.style.display='none'; Codehighlighter1_165_235_Open_Text.style.display='none'; Codehighlighter1_165_235_Closed_Image.style.display='inline'; Codehighlighter1_165_235_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_165_235_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_165_235_Closed_Text.style.display='none'; Codehighlighter1_165_235_Open_Image.style.display='inline'; Codehighlighter1_165_235_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_165_235_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_165_235_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;read&nbsp;gLogList&nbsp;and&nbsp;write&nbsp;log&nbsp;string&nbsp;into&nbsp;the&nbsp;database</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;_endthreadex(&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;other&nbsp;threads.&nbsp;write&nbsp;log&nbsp;string.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;wrtie_log(&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">log&nbsp;)<br><img id=Codehighlighter1_357_390_Open_Image onclick="this.style.display='none'; Codehighlighter1_357_390_Open_Text.style.display='none'; Codehighlighter1_357_390_Closed_Image.style.display='inline'; Codehighlighter1_357_390_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_357_390_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_357_390_Closed_Text.style.display='none'; Codehighlighter1_357_390_Open_Image.style.display='inline'; Codehighlighter1_357_390_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_357_390_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_357_390_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;gLogList.push_back(&nbsp;log&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>将他们包装起来</strong> </font>
<p><font size=2>我们很有可能会在同一个系统中多次遇到类似需要转换为异步操作的地方，如果每一次都手动去创建一个队列和一<br>个线程，那将会多么乏味啊！懒惰的程序员喜欢重用各种代码。所以，我自己觉得很有必要将这一切封装起来。我<br>们只需要封装这个队列和创建线程的繁琐细节，让应用层全部专注于具体的逻辑处理： </font>
<p><font size=2></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">typename&nbsp;_NodeType</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;async_operator<br><img id=Codehighlighter1_51_1052_Open_Image onclick="this.style.display='none'; Codehighlighter1_51_1052_Open_Text.style.display='none'; Codehighlighter1_51_1052_Closed_Image.style.display='inline'; Codehighlighter1_51_1052_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_51_1052_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_51_1052_Closed_Text.style.display='none'; Codehighlighter1_51_1052_Open_Image.style.display='inline'; Codehighlighter1_51_1052_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_51_1052_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_51_1052_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_65_88_Open_Image onclick="this.style.display='none'; Codehighlighter1_65_88_Open_Text.style.display='none'; Codehighlighter1_65_88_Closed_Image.style.display='inline'; Codehighlighter1_65_88_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_65_88_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_65_88_Closed_Text.style.display='none'; Codehighlighter1_65_88_Open_Image.style.display='inline'; Codehighlighter1_65_88_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_65_88_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_65_88_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;the&nbsp;list&nbsp;node&nbsp;type.</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;_NodeType&nbsp;node_type;<br><img id=Codehighlighter1_126_139_Open_Image onclick="this.style.display='none'; Codehighlighter1_126_139_Open_Text.style.display='none'; Codehighlighter1_126_139_Closed_Image.style.display='inline'; Codehighlighter1_126_139_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_126_139_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_126_139_Closed_Text.style.display='none'; Codehighlighter1_126_139_Open_Image.style.display='inline'; Codehighlighter1_126_139_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_126_139_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_126_139_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;the&nbsp;list.</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;multi_list</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">node_type,&nbsp;Mutex,&nbsp;Semaphore</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;list_type;<br><img id=Codehighlighter1_207_229_Open_Image onclick="this.style.display='none'; Codehighlighter1_207_229_Open_Text.style.display='none'; Codehighlighter1_207_229_Closed_Image.style.display='inline'; Codehighlighter1_207_229_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_207_229_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_207_229_Closed_Text.style.display='none'; Codehighlighter1_207_229_Open_Image.style.display='inline'; Codehighlighter1_207_229_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_207_229_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_207_229_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;operator&nbsp;signature</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;functor</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">,&nbsp;TYPE_LIST1(&nbsp;list_type</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;)</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;operator_type;<br><img id=Codehighlighter1_301_360_Open_Image onclick="this.style.display='none'; Codehighlighter1_301_360_Open_Text.style.display='none'; Codehighlighter1_301_360_Closed_Image.style.display='inline'; Codehighlighter1_301_360_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_301_360_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_301_360_Closed_Text.style.display='none'; Codehighlighter1_301_360_Open_Image.style.display='inline'; Codehighlighter1_301_360_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_301_360_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_301_360_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;init&nbsp;function&nbsp;signature,&nbsp;called&nbsp;when&nbsp;the&nbsp;thread&nbsp;starts.</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;functor</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;init_type;<br><img id=Codehighlighter1_402_437_Open_Image onclick="this.style.display='none'; Codehighlighter1_402_437_Open_Text.style.display='none'; Codehighlighter1_402_437_Closed_Image.style.display='inline'; Codehighlighter1_402_437_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_402_437_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_402_437_Closed_Text.style.display='none'; Codehighlighter1_402_437_Open_Image.style.display='inline'; Codehighlighter1_402_437_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_402_437_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_402_437_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;called&nbsp;before&nbsp;the&nbsp;thread&nbsp;exits.</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;functor</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;release_type;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_492_619_Open_Image onclick="this.style.display='none'; Codehighlighter1_492_619_Open_Text.style.display='none'; Codehighlighter1_492_619_Closed_Image.style.display='inline'; Codehighlighter1_492_619_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_492_619_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_492_619_Closed_Text.style.display='none'; Codehighlighter1_492_619_Open_Image.style.display='inline'; Codehighlighter1_492_619_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_492_619_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_492_619_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;start&nbsp;the&nbsp;thread&nbsp;and&nbsp;execute&nbsp;the&nbsp;operation.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;@param&nbsp;op&nbsp;the&nbsp;callback&nbsp;function&nbsp;operate&nbsp;the&nbsp;list&nbsp;node.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;execute(&nbsp;operator_type&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">op,&nbsp;init_type&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">init&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;init_type(),&nbsp;release_type&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">release&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;release_type()&nbsp;);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_736_810_Open_Image onclick="this.style.display='none'; Codehighlighter1_736_810_Open_Text.style.display='none'; Codehighlighter1_736_810_Closed_Image.style.display='inline'; Codehighlighter1_736_810_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_736_810_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_736_810_Closed_Text.style.display='none'; Codehighlighter1_736_810_Open_Image.style.display='inline'; Codehighlighter1_736_810_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_736_810_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_736_810_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;exit&nbsp;the&nbsp;thread.It&nbsp;will&nbsp;block&nbsp;until&nbsp;the&nbsp;thread&nbsp;exited.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;exit();&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_834_899_Open_Image onclick="this.style.display='none'; Codehighlighter1_834_899_Open_Text.style.display='none'; Codehighlighter1_834_899_Closed_Image.style.display='inline'; Codehighlighter1_834_899_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_834_899_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_834_899_Closed_Text.style.display='none'; Codehighlighter1_834_899_Open_Image.style.display='inline'; Codehighlighter1_834_899_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_834_899_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_834_899_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;get&nbsp;the&nbsp;list&nbsp;so&nbsp;that&nbsp;you&nbsp;can&nbsp;pust&nbsp;list&nbsp;nodes.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list_type&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">list();&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;list_type&nbsp;_list;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;operator_type&nbsp;_operator;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;init_type&nbsp;_init;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;release_type&nbsp;_release;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;_thread;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>我利用了已有的组件：线程安全的容器multi_list、包装任意执行体的functor、线程维护类thread。那么，现在，<br>应用层只需要定义队列节点类型，写应用相关的回调函数(任意可被functor包装的广义函数)。(见附件例子) </font>
<p><font size=2>之所以为这个组件加上init和release，是因为有些东西(例如COM)需要在线程启动时初始化，而在线程快结束时释放，例如对于<br>使用COM的应用来说，就需要在线程初始化时CoInitialize，结束时CoUninitialize。 </font>
<p><font size=2><strong>闲说下其他东西</strong> </font>
<p><font size=2>在本文的附件代码里，你可以获取到functor、thread、multi_list这些东西，所以我有必要提一下。 </font>
<p><font size=2>关于functor，你可以参看&lt;实现functor - 增强型的函数指针&gt;，基本上可以看成增强版的C回调函数；至于multi_list，基本上<br>是一个container adapter (套用下STL的概念)，使用条件变量参与线程同步，据说效率要比简单的互斥高点；至于thread，我需要<br>特别说下： </font>
<p><font size=2>thread最为重要的就是为其附加了一个windows的消息队列(只要调用PeekMessage之类的函数该队列就存在)，本意是可以让其他线<br>程传送数据到该线程，但是目前只用于线程退出，即其他线程可以在任何时候要求该线程安全地退出(该线程没有阻塞的情况下，<br>阻塞时获取不到消息)。我不知道这个安全退出策略是否真的有必要存在，但是我讨厌看到各种撇脚的退出方法(例如设置全局标志<br>变量，增加额外的--没封装前---event对象之类)。 </font>
<p><font size=2><strong>结束</strong> </font>
<p><font size=2>不知道其他人是如何做这种异步转换操作的，在这里我只是起个抛砖引玉的作用，欢迎大家提出意见。 </font>
<p>&nbsp;</p>
<a href="http://www.cppblog.com/Files/kevinlynx/async_logger.rar" target=_blank>例子下载</a> 
<img src ="http://www.cppblog.com/kevinlynx/aggbug/54554.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-06-25 15:47 <a href="http://www.cppblog.com/kevinlynx/archive/2008/06/25/54554.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IOCP与线程</title><link>http://www.cppblog.com/kevinlynx/archive/2008/06/23/54390.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Mon, 23 Jun 2008 09:32:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/06/23/54390.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/54390.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/06/23/54390.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/54390.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/54390.html</trackback:ping><description><![CDATA[<p><font size="2">author : Kevin Lynx</font> <p><strong><font size="1"></font></strong>&nbsp; <p><strong>什么是完成包？</strong>  <p><font size="2">完成包，即IO Completion Packet，是指异步IO操作完毕后OS提交给应用层的通知包。IOCP维护了一个IO操作结果队列，里面<br>保存着各种完成包。应用层调用GQCS(也就是GetQueueCompletionStatus)函数获取这些完成包。 </font> <p><font size="2"><strong>最大并发线程数</strong> </font> <p><font size="2">在一个典型的IOCP程序里，会有一些线程调用GQCS去获取IO操作结果。最大并发线程数指定在同一时刻处理完成包的线程数目。<br>该参数在调用CreateIoCompletionPort时由NumberOfConcurrentThreads指定。 </font> <p><font size="2"><strong>工作者线程</strong> </font> <p><font size="2">工作者线程一般指的就是调用GQCS函数的线程。要注意的是，工作者线程数和最大并发线程数并不是同一回事(见下文)。工作者<br>线程由应用层显示创建(_beginthreadex 之类)。工作者线程通常是一个循环，会不断地GQCS到完成包，然后处理完成包。 </font> <p><font size="2"><strong>调度过程</strong> </font> <p><font size="2">工作者线程以是否阻塞分为两种状态：运行状态和等待状态。当线程做一些阻塞操作时(线程同步，甚至GQCS空的完成队列)，线程<br>处于等待状态；否则，线程处于运行状态。 </font> <p><font size="2">另一方面，OS会始终保持某一时刻处于运行状态的线程数小于最大并发线程数。每一个调用GQCS函数的线程OS实际上都会进行记录，<br>当完成队列里有完成包时，OS会首先检查当前处于运行状态的工作线程数是否小于最大并发线程数，如果小于，OS会按照LIFO的顺<br>序让某个工作者线程从GQCS返回(此工作者线程转换为运行状态)。如何决定这个LIFO？这是简单地通过调用GQCS函数的顺序决定的。 </font> <p><font size="2">从这里可以看出，这里涉及到线程唤醒和睡眠的操作。如果两个线程被放置于同一个CPU上，就会有线程切换的开销。因此，为了消<br>除这个开销，最大并发线程数被建议为设置成CPU数量。 </font> <p><font size="2">从以上调度过程还可以看出，如果某个处于运行状态的工作者线程在处理完成包时阻塞了(例如线程同步、其他IO操作)，那么就有<br>CPU资源处于空闲状态。因此，我们也看到很多文档里建议，工作者线程数为(CPU数*2+2)。 </font> <p><font size="2">在一个等待线程转换到运行状态时，有可能会出现短暂的时间运行线程数超过最大并发线程数，这个时候OS会迅速地让这个新转换<br>的线程阻塞，从而减少这个数量。(关于这个观点，MSDN上只说：by not allowing any new active threads，却没说明not allowing<br>what) </font> <p><font size="2"><strong>调度原理</strong> </font> <p><font size="2">这个知道了其实没什么意义，都是内核做的事，大致上都是操作线程control block，直接摘录&lt;Inside IO Completion Ports&gt;: </font> <p><font size="2">The list of threads hangs off the queue object. A thread's control block data structure has a pointer in it that <br>references the queue object of a queue that it is associated with; if the pointer is NULL then the thread is not <br>associated with a queue. </font> <p><font size="2">So how does NT keep track of threads that become inactive because they block on something other than the completion<br>port" The answer lies in the queue pointer in a thread's control block. The scheduler routines that are executed <br>in response to a thread blocking (KeWaitForSingleObject, KeDelayExecutionThread, etc.) check the thread's queue <br>pointer and if its not NULL they will call KiActivateWaiterQueue, a queue-related function. KiActivateWaiterQueue<br> decrements the count of active threads associated with the queue, and if the result is less than the maximum and <br>there is at least one completion packet in the queue then the thread at the front of the queue's thread list is <br>woken and given the oldest packet. Conversely, whenever a thread that is associated with a queue wakes up after <br>blocking the scheduler executes the function KiUnwaitThread, which increments the queue's active count. </font> <p><font size="2"><strong>参考资料</strong> </font> <p><font size="2">&lt;Inside I/O Completion Ports&gt;:<br></font><a href="http://technet.microsoft.com/en-us/sysinternals/bb963891.aspx"><font size="2">http://technet.microsoft.com/en-us/sysinternals/bb963891.aspx</font></a><br><font size="2">&lt;I/O Completion Ports&gt;:<br></font><a href="http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx"><font size="2">http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx</font></a><br><font size="2">&lt;INFO: Design Issues When Using IOCP in a Winsock Server&gt;:<br></font><a href="http://support.microsoft.com/kb/192800/en-us/"><font size="2">http://support.microsoft.com/kb/192800/en-us/</font></a></p><img src ="http://www.cppblog.com/kevinlynx/aggbug/54390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-06-23 17:32 <a href="http://www.cppblog.com/kevinlynx/archive/2008/06/23/54390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SGI STL的内存池</title><link>http://www.cppblog.com/kevinlynx/archive/2008/06/12/53054.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Thu, 12 Jun 2008 13:26:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/06/12/53054.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/53054.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/06/12/53054.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/53054.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/53054.html</trackback:ping><description><![CDATA[<p><font size=2>stl中各种容器都有一个可选的模板参数：allocator，也就是一个负责内存分配的组件。STL标准规定的allcator<br>被定义在memory文件中。STL标准规定的allocator只是单纯地封装operator new，效率上有点过意不去。 </font>
<p><font size=2>SGI实现的STL里，所有的容器都使用SGI自己定义的allocator。这个allocator实现了一个small object的内存池。<br>Loki里为了处理小对象的内存分配，也实现了类似的内存管理机制。 </font>
<p><font size=2>该内存池大致上，就是一大块一大块地从系统获取内存，然后将其分成很多小块以链表的形式链接起来。其内部<br>有很多不同类型的链表，不同的链表维护不同大小的内存块。每一次客户端要求分配内存时，allcator就根据请求<br>的大小找到相应的链表(最接近的尺寸)，然后从链表里取出内存。当客户端归还内存时，allocator就将这块内存<br>放回到对应的链表里。 </font>
<p><font size=2>我简单地画了幅图表示整个结构：</font>
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/SGISTL_12DE6/allocator.jpg"><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=352 alt=allocator src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/SGISTL_12DE6/allocator_thumb.jpg" width=434 border=0></a>
<p><font size=2>allocator内部维护一个链表数组，数组元素全部是链表头指针。链表A每一个节点维护一个8bytes的内存块，链表<br>B每一个节点维护一个16bytes的内存块。 </font>
<p><font size=2>当客户端请求分配10bytes的内存时，allocator将10调整为最接近的16bytes(只能大于10bytes)，然后发现16bytes<br>这个链表(链表B)里有可用内存块，于是从B里取出一块内存返回。当客户端归还时，allocator找到对应的链表，将<br>内存重新放回链表B即可。 </font>
<p><font size=2>大致过程就这么简单，也许有人要说用链表维护一块内存，链表本身就会浪费一些内存(在我很早前接触内存池时，<br>总会看到类似的论点= =|)，其实通过一些简单的技巧是完全可以避免的。例如，这里allocator维护了很多内存块，<br>反正这些内存本身就是闲置的，因此我们就可以直接在这些内存里记录链表的信息(下一个元素)。 </font>
<p><font size=2>还是写点代码详细说下这个小技巧：</font>
<p>&nbsp;&nbsp;&nbsp; </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;Obj<br><img id=Codehighlighter1_15_40_Open_Image onclick="this.style.display='none'; Codehighlighter1_15_40_Open_Text.style.display='none'; Codehighlighter1_15_40_Closed_Image.style.display='inline'; Codehighlighter1_15_40_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_15_40_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_15_40_Closed_Text.style.display='none'; Codehighlighter1_15_40_Open_Image.style.display='inline'; Codehighlighter1_15_40_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_15_40_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_15_40_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Obj&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">next;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">mem&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;malloc(&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Obj&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">header&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(Obj</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;mem;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Obj&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">cur_obj&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;header;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Obj&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">next_obj&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;cur_obj;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;;&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;i&nbsp;)<br><img id=Codehighlighter1_195_441_Open_Image onclick="this.style.display='none'; Codehighlighter1_195_441_Open_Text.style.display='none'; Codehighlighter1_195_441_Closed_Image.style.display='inline'; Codehighlighter1_195_441_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_195_441_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_195_441_Closed_Text.style.display='none'; Codehighlighter1_195_441_Open_Image.style.display='inline'; Codehighlighter1_195_441_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_195_441_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_195_441_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cur_obj&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;next_obj;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next_obj&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(Obj</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)((</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)next_obj&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;i&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">9</span><span style="COLOR: #000000">&nbsp;)<br><img id=Codehighlighter1_304_364_Open_Image onclick="this.style.display='none'; Codehighlighter1_304_364_Open_Text.style.display='none'; Codehighlighter1_304_364_Closed_Image.style.display='inline'; Codehighlighter1_304_364_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_304_364_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_304_364_Closed_Text.style.display='none'; Codehighlighter1_304_364_Open_Image.style.display='inline'; Codehighlighter1_304_364_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_304_364_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_304_364_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cur_obj</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_387_435_Open_Image onclick="this.style.display='none'; Codehighlighter1_387_435_Open_Text.style.display='none'; Codehighlighter1_387_435_Closed_Image.style.display='inline'; Codehighlighter1_387_435_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_387_435_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_387_435_Closed_Text.style.display='none'; Codehighlighter1_387_435_Open_Image.style.display='inline'; Codehighlighter1_387_435_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_387_435_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_387_435_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cur_obj</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;next_obj;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;free(&nbsp;mem&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;
<p><font size=2>这样，通过header指针和next域，就可以逐块(这里是10byts)地访问mem所指向的内存，而这些链表的节点，都<br>是直接保存在这块内存里的，所以完全没有额外消耗。 </font>
<p><font size=2>我用C模仿着SGI的这个allocator写了个可配置的内存池，在其上按照STL的标准包装了一个allocator，可以直接<br>用于VC自带的STL里。</font><a href="http://www.cppblog.com/Files/kevinlynx/alloc.rar" target=_blank><font size=2>测试代码</font></a><font size=2>稍微测试了下，发现在不同的机器上有明显的差距。 </font></p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/53054.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-06-12 21:26 <a href="http://www.cppblog.com/kevinlynx/archive/2008/06/12/53054.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Proactor和Reactor模式_继续并发系统设计的扫盲</title><link>http://www.cppblog.com/kevinlynx/archive/2008/06/06/52356.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Fri, 06 Jun 2008 05:25:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/06/06/52356.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/52356.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/06/06/52356.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/52356.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/52356.html</trackback:ping><description><![CDATA[<p><font size=2>6.6.2008 </font>
<p><font size=2>Kevin Lynx </font>
<p><font size=2>Proactor和<a href="http://en.wikipedia.org/wiki/Reactor_pattern" target=_blank>Reactor</a>都是并发编程中的设计模式。在我看来，他们都是用于派发/分离IO操作事件的。这里所谓的<br>IO事件也就是诸如read/write的IO操作。"派发/分离"就是将单独的IO事件通知到上层模块。两个模式不同的地方<br>在于，Proactor用于异步IO，而Reactor用于同步IO。 </font>
<p><font size=2>摘抄一些关键的东西： </font>
<p><font size=2>"<br>Two patterns that involve event demultiplexors are called Reactor and Proactor [1]. The Reactor patterns <br>involve synchronous I/O, whereas the Proactor pattern involves asynchronous I/O.<br>" </font>
<p><font size=2>关于两个模式的大致模型，从以下文字基本可以明白： </font>
<p><font size=2>"<br>An example will help you understand the difference between Reactor and Proactor. We will focus on the read <br>operation here, as the write implementation is similar. Here's a read in Reactor: </font>
<p><font size=2>* An event handler declares interest in I/O events that indicate readiness for read on a particular socket ;<br>* The event demultiplexor waits for events ;<br>* An event comes in and wakes-up the demultiplexor, and the demultiplexor calls the appropriate handler; <br>* The event handler performs the actual read operation, handles the data read, declares renewed interest in <br>&nbsp; I/O events, and returns control to the dispatcher . </font>
<p><font size=2>By comparison, here is a read operation in Proactor (true async): </font>
<p><font size=2>* A handler initiates an asynchronous read operation (note: the OS must support asynchronous I/O). In this <br>&nbsp; case, the handler does not care about I/O readiness events, but is instead registers interest in receiving <br>&nbsp; completion events;<br>* The event demultiplexor waits until the operation is completed ;<br>* While the event demultiplexor waits, the OS executes the read operation in a parallel kernel thread, puts <br>&nbsp; data into a user-defined buffer, and notifies the event demultiplexor that the read is complete ;<br>* The event demultiplexor calls the appropriate handler; <br>* The event handler handles the data from user defined buffer, starts a new asynchronous operation, and returns<br>&nbsp; control to the event demultiplexor. </font>
<p><font size=2>" </font>
<p><font size=2>可以看出，两个模式的相同点，都是对某个IO事件的事件通知(即告诉某个模块，这个IO操作可以进行或已经完成)。在结构<br>上，两者也有相同点：demultiplexor负责提交IO操作(异步)、查询设备是否可操作(同步)，然后当条件满足时，就回调handler。<br>不同点在于，异步情况下(Proactor)，当回调handler时，表示IO操作已经完成；同步情况下(Reactor)，回调handler时，表示<br>IO设备可以进行某个操作(can read or can write)，handler这个时候开始提交操作。 </font>
<p><font size=2>用select模型写个简单的reactor，大致为： </font>
<p><font size=2></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_0_3_Open_Image onclick="this.style.display='none'; Codehighlighter1_0_3_Open_Text.style.display='none'; Codehighlighter1_0_3_Closed_Image.style.display='inline'; Codehighlighter1_0_3_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_0_3_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_0_3_Closed_Text.style.display='none'; Codehighlighter1_0_3_Open_Image.style.display='inline'; Codehighlighter1_0_3_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span id=Codehighlighter1_0_3_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_0_3_Open_Text><span style="COLOR: #808080">///</span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;handler<br><img id=Codehighlighter1_18_124_Open_Image onclick="this.style.display='none'; Codehighlighter1_18_124_Open_Text.style.display='none'; Codehighlighter1_18_124_Closed_Image.style.display='inline'; Codehighlighter1_18_124_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_18_124_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_18_124_Closed_Text.style.display='none'; Codehighlighter1_18_124_Open_Image.style.display='inline'; Codehighlighter1_18_124_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_18_124_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_18_124_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onRead()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onWrite()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onAccept()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;dispatch<br><img id=Codehighlighter1_144_804_Open_Image onclick="this.style.display='none'; Codehighlighter1_144_804_Open_Text.style.display='none'; Codehighlighter1_144_804_Closed_Image.style.display='inline'; Codehighlighter1_144_804_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_144_804_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_144_804_Closed_Text.style.display='none'; Codehighlighter1_144_804_Open_Image.style.display='inline'; Codehighlighter1_144_804_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_144_804_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_144_804_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;poll()<br><img id=Codehighlighter1_174_696_Open_Image onclick="this.style.display='none'; Codehighlighter1_174_696_Open_Text.style.display='none'; Codehighlighter1_174_696_Closed_Image.style.display='inline'; Codehighlighter1_174_696_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_174_696_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_174_696_Closed_Text.style.display='none'; Codehighlighter1_174_696_Open_Image.style.display='inline'; Codehighlighter1_174_696_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_174_696_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_174_696_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;add&nbsp;fd&nbsp;in&nbsp;the&nbsp;set.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/dot.gif"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;poll&nbsp;every&nbsp;fd</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;c&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;select(&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">read_fd,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">write_fd,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;c&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)<br><img id=Codehighlighter1_329_690_Open_Image onclick="this.style.display='none'; Codehighlighter1_329_690_Open_Text.style.display='none'; Codehighlighter1_329_690_Closed_Image.style.display='inline'; Codehighlighter1_329_690_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_329_690_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_329_690_Closed_Text.style.display='none'; Codehighlighter1_329_690_Open_Image.style.display='inline'; Codehighlighter1_329_690_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_329_690_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_329_690_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;each&nbsp;fd&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;the&nbsp;read_fd_set<br><img id=Codehighlighter1_386_533_Open_Image onclick="this.style.display='none'; Codehighlighter1_386_533_Open_Text.style.display='none'; Codehighlighter1_386_533_Closed_Image.style.display='inline'; Codehighlighter1_386_533_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_386_533_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_386_533_Closed_Text.style.display='none'; Codehighlighter1_386_533_Open_Image.style.display='inline'; Codehighlighter1_386_533_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_386_533_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_386_533_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;fd&nbsp;can&nbsp;read<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_handler</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">onRead();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;fd&nbsp;can&nbsp;accept<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_handler</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">onAccept();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;each&nbsp;fd&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;the&nbsp;write_fd_set<br><img id=Codehighlighter1_593_680_Open_Image onclick="this.style.display='none'; Codehighlighter1_593_680_Open_Text.style.display='none'; Codehighlighter1_593_680_Closed_Image.style.display='inline'; Codehighlighter1_593_680_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_593_680_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_593_680_Closed_Text.style.display='none'; Codehighlighter1_593_680_Open_Image.style.display='inline'; Codehighlighter1_593_680_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_593_680_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_593_680_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;fd&nbsp;can&nbsp;write<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_handler</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">onWrite();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setHandler(&nbsp;handler&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_h&nbsp;)<br><img id=Codehighlighter1_739_768_Open_Image onclick="this.style.display='none'; Codehighlighter1_739_768_Open_Text.style.display='none'; Codehighlighter1_739_768_Closed_Image.style.display='inline'; Codehighlighter1_739_768_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_739_768_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_739_768_Closed_Text.style.display='none'; Codehighlighter1_739_768_Open_Image.style.display='inline'; Codehighlighter1_739_768_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_739_768_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_739_768_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_handler&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_h;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;handler&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_handler;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_809_824_Open_Image onclick="this.style.display='none'; Codehighlighter1_809_824_Open_Text.style.display='none'; Codehighlighter1_809_824_Closed_Image.style.display='inline'; Codehighlighter1_809_824_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_809_824_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_809_824_Closed_Text.style.display='none'; Codehighlighter1_809_824_Open_Image.style.display='inline'; Codehighlighter1_809_824_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_809_824_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_809_824_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;application</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyHandler&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;handler<br><img id=Codehighlighter1_858_965_Open_Image onclick="this.style.display='none'; Codehighlighter1_858_965_Open_Text.style.display='none'; Codehighlighter1_858_965_Closed_Image.style.display='inline'; Codehighlighter1_858_965_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_858_965_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_858_965_Closed_Text.style.display='none'; Codehighlighter1_858_965_Open_Image.style.display='inline'; Codehighlighter1_858_965_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_858_965_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_858_965_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onRead()<br><img id=Codehighlighter1_890_896_Open_Image onclick="this.style.display='none'; Codehighlighter1_890_896_Open_Text.style.display='none'; Codehighlighter1_890_896_Closed_Image.style.display='inline'; Codehighlighter1_890_896_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_890_896_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_890_896_Closed_Text.style.display='none'; Codehighlighter1_890_896_Open_Image.style.display='inline'; Codehighlighter1_890_896_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_890_896_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_890_896_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onWrite()<br><img id=Codehighlighter1_923_929_Open_Image onclick="this.style.display='none'; Codehighlighter1_923_929_Open_Text.style.display='none'; Codehighlighter1_923_929_Closed_Image.style.display='inline'; Codehighlighter1_923_929_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_923_929_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_923_929_Closed_Text.style.display='none'; Codehighlighter1_923_929_Open_Image.style.display='inline'; Codehighlighter1_923_929_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_923_929_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_923_929_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onAccept()<br><img id=Codehighlighter1_957_963_Open_Image onclick="this.style.display='none'; Codehighlighter1_957_963_Open_Text.style.display='none'; Codehighlighter1_957_963_Closed_Image.style.display='inline'; Codehighlighter1_957_963_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_957_963_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_957_963_Closed_Text.style.display='none'; Codehighlighter1_957_963_Open_Image.style.display='inline'; Codehighlighter1_957_963_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_957_963_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_957_963_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>在网上找了份Proactor模式比较正式的<a href="http://www.cppblog.com/Files/kevinlynx/proactor2.rar" target=_blank>文档</a>，其给出了一个总体的UML类图，比较全面： </font>
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/ProactorReactor__BCB1/proactor_uml.jpg"><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=317 alt=proactor_uml src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/ProactorReactor__BCB1/proactor_uml_thumb.jpg" width=692 border=0></a>
<p><font size=2>根据这份图我随便写了个例子代码： </font>
<p><font size=2></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;AsyIOProcessor<br><img id=Codehighlighter1_21_227_Open_Image onclick="this.style.display='none'; Codehighlighter1_21_227_Open_Text.style.display='none'; Codehighlighter1_21_227_Closed_Image.style.display='inline'; Codehighlighter1_21_227_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_21_227_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_21_227_Closed_Text.style.display='none'; Codehighlighter1_21_227_Open_Image.style.display='inline'; Codehighlighter1_21_227_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_21_227_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_21_227_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;do_read()<br><img id=Codehighlighter1_54_189_Open_Image onclick="this.style.display='none'; Codehighlighter1_54_189_Open_Text.style.display='none'; Codehighlighter1_54_189_Closed_Image.style.display='inline'; Codehighlighter1_54_189_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_54_189_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_54_189_Closed_Text.style.display='none'; Codehighlighter1_54_189_Open_Image.style.display='inline'; Codehighlighter1_54_189_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_54_189_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_54_189_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/dot.gif">send&nbsp;read&nbsp;operation&nbsp;to&nbsp;OS<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;read&nbsp;io&nbsp;finished.and&nbsp;dispatch&nbsp;notification</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_proactor</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">dispatch_read();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Proactor&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_proactor;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Proactor<br><img id=Codehighlighter1_247_369_Open_Image onclick="this.style.display='none'; Codehighlighter1_247_369_Open_Text.style.display='none'; Codehighlighter1_247_369_Closed_Image.style.display='inline'; Codehighlighter1_247_369_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_247_369_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_247_369_Closed_Text.style.display='none'; Codehighlighter1_247_369_Open_Image.style.display='inline'; Codehighlighter1_247_369_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_247_369_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_247_369_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;dispatch_read()<br><img id=Codehighlighter1_286_323_Open_Image onclick="this.style.display='none'; Codehighlighter1_286_323_Open_Text.style.display='none'; Codehighlighter1_286_323_Closed_Image.style.display='inline'; Codehighlighter1_286_323_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_286_323_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_286_323_Closed_Text.style.display='none'; Codehighlighter1_286_323_Open_Image.style.display='inline'; Codehighlighter1_286_323_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_286_323_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_286_323_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_handlerMgr</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">onRead();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HandlerManager&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_handlerMgr;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;HandlerManager<br><img id=Codehighlighter1_395_634_Open_Image onclick="this.style.display='none'; Codehighlighter1_395_634_Open_Text.style.display='none'; Codehighlighter1_395_634_Closed_Image.style.display='inline'; Codehighlighter1_395_634_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_395_634_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_395_634_Closed_Text.style.display='none'; Codehighlighter1_395_634_Open_Image.style.display='inline'; Codehighlighter1_395_634_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_395_634_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_395_634_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;std::list</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Handler</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">&nbsp;HandlerList;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onRead()<br><img id=Codehighlighter1_482_593_Open_Image onclick="this.style.display='none'; Codehighlighter1_482_593_Open_Text.style.display='none'; Codehighlighter1_482_593_Closed_Image.style.display='inline'; Codehighlighter1_482_593_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_482_593_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_482_593_Closed_Text.style.display='none'; Codehighlighter1_482_593_Open_Image.style.display='inline'; Codehighlighter1_482_593_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_482_593_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_482_593_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;notify&nbsp;all&nbsp;the&nbsp;handlers.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::for_each(&nbsp;_handlers.begin(),&nbsp;_handlers.end(),&nbsp;onRead&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HandlerList&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_handlers;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Handler<br><img id=Codehighlighter1_653_694_Open_Image onclick="this.style.display='none'; Codehighlighter1_653_694_Open_Text.style.display='none'; Codehighlighter1_653_694_Closed_Image.style.display='inline'; Codehighlighter1_653_694_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_653_694_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_653_694_Closed_Text.style.display='none'; Codehighlighter1_653_694_Open_Image.style.display='inline'; Codehighlighter1_653_694_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_653_694_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_653_694_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onRead()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;application&nbsp;level&nbsp;handler.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyHandler&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Handler<br><img id=Codehighlighter1_762_815_Open_Image onclick="this.style.display='none'; Codehighlighter1_762_815_Open_Text.style.display='none'; Codehighlighter1_762_815_Closed_Image.style.display='inline'; Codehighlighter1_762_815_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_762_815_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_762_815_Closed_Text.style.display='none'; Codehighlighter1_762_815_Open_Image.style.display='inline'; Codehighlighter1_762_815_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_762_815_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_762_815_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onRead()&nbsp;<br><img id=Codehighlighter1_795_813_Open_Image onclick="this.style.display='none'; Codehighlighter1_795_813_Open_Text.style.display='none'; Codehighlighter1_795_813_Closed_Image.style.display='inline'; Codehighlighter1_795_813_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_795_813_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_795_813_Closed_Text.style.display='none'; Codehighlighter1_795_813_Open_Image.style.display='inline'; Codehighlighter1_795_813_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_795_813_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_795_813_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>Reactor通过某种变形，可以将其改装为Proactor，在某些不支持异步IO的系统上，也可以隐藏底层的实现，利于编写跨平台<br>代码。我们只需要在dispatch(也就是demultiplexor)中封装同步IO操作的代码，在上层，用户提交自己的缓冲区到这一层，<br>这一层检查到设备可操作时，不像原来立即回调handler，而是开始IO操作，然后将操作结果放到用户缓冲区(读)，然后再<br>回调handler。这样，对于上层handler而言，就像是proactor一样。详细技法参见<a href="http://www.artima.com/articles/io_design_patterns2.html" target=_blank>这篇文章</a>。 </font>
<p><font size=2>其实就设计模式而言，我个人觉得某个模式其实是没有完全固定的结构的。不能说某个模式里就肯定会有某个类，类之间的<br>关系就肯定是这样。在实际写程序过程中也很少去特别地实现某个模式，只能说模式会给你更多更好的架构方案。 </font>
<p><font size=2>最近在看spserver的代码，看到别人提各种并发系统中的模式，有点眼红，于是才来扫扫盲。知道什么是<a href="http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html" target=_blank>leader follower模式</a>，<br>reactor, proactor，multiplexing，对于心中的那个网络库也越来越清晰。 </font>
<p><font size=2>最近还干了些离谱的事，写了传说中的字节流编码，用模板的方式实现，不但保持了扩展性，还少写很多代码；处于效率考虑，<br>写了个static array容器(其实就是template &lt;typename _Tp, std::size_t size&gt; class static_array { _Tp _con[size])，<br>加了iterator，遵循STL标准，可以结合进STL的各个generic algorithm用，自我感觉不错。基础模块搭建完毕，解析了公司<br>服务器网络模块的消息，我是不是真的打算用自己的网络模块重写我的验证服务器？在另一个给公司写的工具里，因为实在厌恶<br>越来越多的重复代码，索性写了几个宏，还真的做到了代码的自动生成:D。 </font>
<p><font size=2>对优雅代码的追求真的成了种癖好.&nbsp; = =| </font></p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/52356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-06-06 13:25 <a href="http://www.cppblog.com/kevinlynx/archive/2008/06/06/52356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>半同步半异步模式以及Leader_Follwer模式</title><link>http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Wed, 04 Jun 2008 02:40:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/52127.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/52127.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/52127.html</trackback:ping><description><![CDATA[<p><font size="2">这里提到的两个设计模式都是用于高并发系统(例如一个高性能的网络服务器)的。这里我只是简单地提一下： </font> <p><font size="2"><strong>1.</strong><a href="http://www.cppblog.com/Files/kevinlynx/hh_lf.rar" target="_blank"><strong>半同步/半异步（half-sync/half-async</strong></a><strong>）：</strong> </font> <p><font size="2">在网<a href="http://www.javaeye.com/topic/60414" target="_blank">上一份资料</a>中引用了一本貌似很<a href="http://www.china-pub.com/14109" target="_blank">经典的书</a>里的比喻：<br>” <br>许多餐厅使用 半同步/半异步 模式的变体。例如，餐厅常常雇佣一个领班负责迎接顾客，并在餐厅繁忙时留意给顾客安排桌位，<br>为等待就餐的顾客按序排队是必要的。领班由所有顾客“共享”，不能被任何特定顾客占用太多时间。当顾客在一张桌子入坐后，<br>有一个侍应生专门为这张桌子服务。 <br>“ </font> <p><font size="2">按照另一份似乎比较权威的文档的描述，要实现半同步/半异步模式，需要实现三层：异步层、同步层、队列层。因为很多操作<br>采用异步方式会比较有效率(例如高效率的网络模型似乎都采用异步IO)，但是异步操作的复杂度比较高，不利于编程。而同步<br>操作相对之下编程要简单点。为了结合两者的优点，就提出了这个模式。而为了让异步层和同步层互相通信(模块间的通信)，系<br>统需要加入一个通信队列。异步层将操作结果放入队列，同步层从队列里获取操作结果。 </font> <p><font size="2">回过头来看看我之前写的那个select网络模型代码，个人认为基本上算是一个半同步半异步模式的简单例子：Buffer相当于通信<br>队列，网络底层将数据写入Buffer，上层再同步地从该队列里获取出数据。这样看来似乎也没什么难度。 = = </font> <p>关于例子代码，直接引用iunknown给的：  <p>//这就是一个典型的循环队列的定义，iget 是队列头，iput 是队列尾&lt;/STRONG&gt;&nbsp;&nbsp; <br>int clifd[MAXNCLI], iget, iput;&nbsp;&nbsp;&nbsp; <br>int main( int argc, char * argv[] )&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>&nbsp; int listenfd = Tcp_listen( NULL, argv[ 1 ], &amp;addrlen );&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>&nbsp; iget = iput = 0;&nbsp;&nbsp; <br>&nbsp; for( int i = 0; i &lt; nthreads; i++ ) {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; pthread_create( &amp;tptr[i].thread_tid, NULL, &amp;thread_main, (void*)i );&nbsp;&nbsp; <br>&nbsp; for( ; ; ) {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; connfd = accept( listenfd, cliaddr,, &amp;clilen );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; clifd[ iput ] = connfd;&nbsp;&nbsp;&nbsp;&nbsp; // 接受到的连接句柄放入队列&lt;/STRONG&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; if( ++iput == MAXNCLI ) iput = 0;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp; }&nbsp;&nbsp; <br>}&nbsp;&nbsp; <br>void * thread_main( void * arg )&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp; for( ; ; ) {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; while( iget == iput ) pthread_cond_wait( ...... );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; connfd = clifd[ iget ];&nbsp;&nbsp;&nbsp;&nbsp; // 从队列中获得连接句柄&lt;/STRONG&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; if( ++iget == MAXNCLI ) iget = 0;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; web_child( connfd );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; close( connfd );&nbsp;&nbsp; <br>&nbsp; }&nbsp;&nbsp; <br>}&nbsp; <p><font size="2"><strong>2</strong><a href="http://www.cppblog.com/Files/kevinlynx/hh_lf.rar" target="_blank"><strong>.领导者/追随者（Leader/Followers）：</strong></a> </font> <p><font size="2">同样，给出别人引用的比喻：<br>”<br>在日常生活中，领导者/追随者模式用于管理许多飞机场出租车候车台。在该用例中，出租车扮演“线程”角色，排在第一辆的出<br>租车成为领导者，剩下的出租车成为追随者。同样，到达出租车候车台的乘客构成了必须被多路分解给出租车的事件，一般以先进<br>先出排序。一般来说，如果任何出租车可以为任何顾客服务，该场景就主要相当于非绑定句柄/线程关联。然而，如果仅仅是某些<br>出租车可以为某些乘客服务，该场景就相当于绑定句柄/线程关联。 <br>“ </font> <p><font size="2">其实这个更简单，我记得&lt;unix网络编程&gt;中似乎提到过这个。总之有一种网络模型(connection-per-thread?)里，一个线程用于<br>accept连接。当接收到一个新的连接时，这个线程就转为connection thread，而这个线程后面的线程则上升为accept线程。这里，<br>accept线程就相当于领导者线程，而其他线程则属于追随者线程。 </font> <p>iunknown 的例子代码：  <p>int listenfd;&nbsp;&nbsp; <br>int main( int argc, char * argv[] )&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>&nbsp; listenfd = Tcp_listen( NULL, argv[ 1 ], &amp;addrlen );&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>&nbsp; for( int i = 0; i &lt; nthreads; i++ ){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; pthread_create( &amp;tptr[i].thread_tid, NULL, &amp;thread_main, (void*)i );&nbsp;&nbsp; <br>&nbsp; }&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>}&nbsp;&nbsp; <br>void * thread_main( void * arg )&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp; for( ; ; ){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; // 多个线程同时阻塞在这个 accept 调用上，依靠操作系统的队列&lt;/STRONG&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; connfd = accept( listenfd, cliaddr, &amp;clilen );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; web_child( connfd );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; close( connfd );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp; <br>&nbsp; }&nbsp;&nbsp; <br>}&nbsp; <p><font size="2"></font></p><img src ="http://www.cppblog.com/kevinlynx/aggbug/52127.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-06-04 10:40 <a href="http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>写了个简单的聊天服务器</title><link>http://www.cppblog.com/kevinlynx/archive/2008/05/28/51412.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Wed, 28 May 2008 09:13:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/05/28/51412.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/51412.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/05/28/51412.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/51412.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/51412.html</trackback:ping><description><![CDATA[<p><font size=2>没什么技术含量，将select模型做简单的封装，同时提供服务器端和客户端所用的接口。功能实现上对数据的发送和接收<br>都做了缓存，搞得跟异步IO一样 = =#。 </font>
<p><font size=2>这个例子聊天服务器可以使用telnet登录，服务器直接将telnet发来的字符串转发给所有客户端。我稍微写了一个小的网络<br>模块，可以用于以后写网络程序的例子代码，也算是练习下网络库的设计。 </font>
<p><font size=2>系统总体类图如下： </font>
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/d90839f5ba11_F1F6/classdiagram.jpg"><font size=2><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=233 alt=classdiagram src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/d90839f5ba11_F1F6/classdiagram_thumb.jpg" width=454 border=0></font></a><font size=2> </font>
<p><font size=2>Address用于包装sockaddr_in结构体，目的就是让系统用起来更方便。 </font>
<p><font size=2>Buffer用于封装原始内存，主要目的是拿来做发送、接收数据缓冲。 </font>
<p><font size=2>Fdset差不多和FD_SET一样，只是这里自己写一个FD_SET，可以让连接数不受FD_SETSIZE的限制。 </font>
<p><font size=2>Socket封装了基本的SOCKET操作，包括创建、销毁套接字。 </font>
<p><font size=2>Session比较有意思，按我的意思，就是代表一个网络连接。对于服务器端，可能会有很多连接，每一个连接可以用一个<br>Session对象表示。而对于客户端，只有一个连接，那么就是一个Session对象。对于Session对象来说，可以进行数据的<br>发送和接收，因此这里Session有recv、send之类的接口。为了缓冲数据，所以Session对于读写分别有一个Buffer对象。 </font>
<p><font size=2>Server代表一个服务器，直接提供创建服务器的接口。同时使用一个unsigned long作为每一个连接的ID号。 </font>
<p><font size=2>Client代表一个客户端，可以直接用于连接服务器。 </font>
<p><font size=2>下载文件提供网络模块代码，以及三个例子程序。</font><a href="http://www.cppblog.com/Files/kevinlynx/kl_net0.1.2.rar" target=_blank><font size=2>点击下载</font></a></p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/51412.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-05-28 17:13 <a href="http://www.cppblog.com/kevinlynx/archive/2008/05/28/51412.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tcp要点学习-数据发送一</title><link>http://www.cppblog.com/kevinlynx/archive/2008/05/22/50770.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Thu, 22 May 2008 07:42:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/05/22/50770.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/50770.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/05/22/50770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/50770.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/50770.html</trackback:ping><description><![CDATA[<p><font size=2>Author : Kevin Lynx</font></p>
<p><font size=2><strong>1. 什么是delayed ack algorithm</strong><br>&nbsp;&nbsp; delayed ack algorithm也就是&lt;TCP/IP详解&gt;中所谓的"经受时延的确认"(翻译得真饶舌 = =||)。在<a href="http://www.faqs.org/rfcs/rfc1122.html" target=_blank>RFC1122</a>中提到delayed ack<br>&nbsp;&nbsp; 的概念：<br>&nbsp;&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #000000">"<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;host&nbsp;that&nbsp;</span><span style="COLOR: #0000ff">is</span><span style="COLOR: #000000">&nbsp;receiving&nbsp;a&nbsp;stream&nbsp;of&nbsp;TCP&nbsp;data&nbsp;segments&nbsp;can<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;increase&nbsp;efficiency&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;both&nbsp;the&nbsp;Internet&nbsp;and&nbsp;the&nbsp;hosts&nbsp;by<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sending&nbsp;fewer&nbsp;than&nbsp;one&nbsp;ACK&nbsp;(acknowledgment)&nbsp;segment&nbsp;per&nbsp;data<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;segment&nbsp;received;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">is</span><span style="COLOR: #000000">&nbsp;known&nbsp;</span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">delayed&nbsp;ACK</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;[TCP:</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">].<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span></div>
<p><br>&nbsp;&nbsp; 我在之前提到过，TCP在收到每一个数据包时，都会发送一个ACK报文给对方，用以告诉对方"我接收到你刚才发送的数据了"。并<br>&nbsp;&nbsp; 且会在报文的确认号字段中标志希望接收到的数据包。 </font></p>
<p><font size=2>&nbsp;&nbsp; 但是，如你所想，如果为每一个接收到的报文都发送一个ACK报文，那将会增加网络的负担。于是，为了解决这个问题，delayed <br>&nbsp;&nbsp; ack被提出。也就是说，实现了delayed ack的TCP，并不见得会对每一个接收到的数据包发送ACK确认报文。 </font>
<p><font size=2>&nbsp;&nbsp; 实际情况是，TCP延迟发送这个ACK。延迟多久？&lt;TCP/IP详解&gt;中说的是200ms，在RFC1122中说的则是500ms。delayed ack有时候<br>&nbsp;&nbsp; 还会附加到数据报文段一起发送，如果在延迟时间内有报文段要发送的话，如果没有，那么当延迟时间到时，就单独发送ACK。 </font>
<p><font size=2>&nbsp;&nbsp; 在<a href="http://tangentsoft.net/wskfaq/intermediate.html#delayed-ack" target=_blank>另一份文档</a>中，作者讲到delayed ack的好处：<br>&nbsp;&nbsp; a) to avoid the silly window syndrome; <br>&nbsp;&nbsp; b) to allow ACKs to piggyback on a reply frame if one is ready to go when the stack decides to do the ACK;<br>&nbsp;&nbsp; c) to allow the stack to send one ACK for several frames, if those frames arrive within the delay period. </font>
<p><font size=2>&nbsp;&nbsp; a) 所谓的糊涂窗口综合症(别人都这样翻译的，似乎有点搞笑:D)<br>&nbsp;&nbsp; b) 将ACK与将要发送的数据报文一起发送<br>&nbsp;&nbsp; c) 一个ack确认多个报文段，如果这几个报文段在延迟时间内到达 </font>
<p><font size=2><strong>2. 什么是Nagle algoritm ?</strong><br>&nbsp;&nbsp; 简而言之，nagle算法主要目的是减少网络流量，当你发送的数据包太小时，TCP并不立即发送该数据包，而是缓存起来直到数据包<br>&nbsp;&nbsp; 到达一定大小后才发送。(improving the efficiency of TCP/IP networks by reducing the number of packets that need to <br>&nbsp;&nbsp; be sent over the network.) </font>
<p><font size=2>&nbsp;&nbsp; 关于这个算法，我觉得<a href="http://en.wikipedia.org/wiki/Nagle's_algorithm" target=_blank>wikipedia</a>上讲的比较好。具体点说，当上层提交数据给TCP时，TCP觉得你的数据太小了(套用一般的例子，<br>&nbsp;&nbsp; 如果你要发送1一个字节的数据，当附加上TCP和IP头后，数据包通常就会增加到41字节，那么这显然是低效的)，就缓存你的数据，<br>&nbsp;&nbsp; 当数据缓存到一定长度后，如果之前发送的数据得到了ACK确认且接收方有足够空间容纳数据，就发送这些数据，否则继续等待。 </font>
<p><font size=2>&nbsp;&nbsp; wikipedia上给了一段nagle的伪代码：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;there&nbsp;</span><span style="COLOR: #0000ff">is</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;data&nbsp;to&nbsp;send<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;the&nbsp;window&nbsp;size&nbsp;</span><span style="COLOR: #000000">&gt;=</span><span style="COLOR: #000000">&nbsp;MSS&nbsp;and&nbsp;available&nbsp;data&nbsp;</span><span style="COLOR: #0000ff">is</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&gt;=</span><span style="COLOR: #000000">&nbsp;MSS<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;send&nbsp;complete&nbsp;MSS&nbsp;segment&nbsp;now<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;there&nbsp;</span><span style="COLOR: #0000ff">is</span><span style="COLOR: #000000">&nbsp;unconfirmed&nbsp;data&nbsp;still&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;the&nbsp;pipe<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enqueue&nbsp;data&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;the&nbsp;buffer&nbsp;until&nbsp;an&nbsp;acknowledge&nbsp;</span><span style="COLOR: #0000ff">is</span><span style="COLOR: #000000">&nbsp;received<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;send&nbsp;data&nbsp;immediately<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;end&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp;<br></font><font size=2>&nbsp;&nbsp; TCP socket提供了关闭nagle算法的接口，你可以通过TCP_NODELAY选项决定是否开启该算法。不过MSDN上建议不要关闭此算法。如果<br>&nbsp;&nbsp; 你发送的数据不至于很小的话(&lt;40byte)，我也不建议你关闭。 </font>
<p><font size=2></font></p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/50770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-05-22 15:42 <a href="http://www.cppblog.com/kevinlynx/archive/2008/05/22/50770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剖析Etwork网络库</title><link>http://www.cppblog.com/kevinlynx/archive/2008/05/21/50687.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Wed, 21 May 2008 13:06:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/05/21/50687.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/50687.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/05/21/50687.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/50687.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/50687.html</trackback:ping><description><![CDATA[<p><font size=2>Author : Kevin Lynx</font>
<p><font size=2>从开始接触网络编程这个东西开始，我就不间断地阅读一些网络库(模块)的源代码，主要目的是为了获取别<br>人在这方面的经验，编程这东西，还是要多实践啊。 </font>
<p><font size=2>基本上，</font><a href="http://www.mindcontrol.org/~hplus/etwork/" target=_blank><font size=2>Etwork</font></a><font size=2>是一个很小巧的网络库。Etwork基于select模型，采用我之前说的技巧，理论上可以处理很<br>多连接(先不说效率)。 </font>
<p><font size=2>先看看下这个库的结构： </font>
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/Etwork_128C5/classgraph.jpg"><font size=2><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=291 alt=classgraph src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/Etwork_128C5/classgraph_thumb.jpg" width=383 border=0></font></a><font size=2> </font>
<p><font size=2>如同很多网络库一样，总会有一个类似于ISocketManager的类，用于管理所有网络连接(当用户服务器时)。<br>而ISocket则用于代表一个网络连接。在其他库中，ISocketManager对应的可能就是Server，而ISocket对应<br>的则是Session。 </font>
<p><font size=2>在接口设计上，尽管Etwork写了很多接口类(看看那些IClass)，但是事实上它抽象得并不彻底。只是暴露给<br>客户端的代码很简洁，而库本身依然臃肿。不知道为什么，现在我比较喜欢纯C这种简洁的东西，对于OO以及<br>template，渐渐地有点心累。 </font>
<p><font size=2>在功能实现上，我以TCP服务器为例，CreateEtwork根据传来的参数建立服务器，在SocketManager::open中<br>是很常规的socket, bind, listen。当建立了服务器之后，需要在程序主循环里不断地轮询状态，这里主要<br>调用poll函数完成。 </font>
<p><font size=2>poll函数主体就是调用select。当select成功返回活动的套接字数量后，Etwork依次轮询读、写、错误fdset，<br>将保存的所有网络连接(就是那些ISocket对象)对应的套接字与fdset中当前的套接字做比较。大致逻辑为： </font>
<p><font size=2></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">fd_count&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;select(&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;readset,&nbsp;writeset,&nbsp;exceptset,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">timeout&nbsp;);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(&nbsp;each&nbsp;fd&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;readset&nbsp;)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;fd&nbsp;</span><span style="COLOR: #0000ff">is</span><span style="COLOR: #000000">&nbsp;listening&nbsp;fd&nbsp;)&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accept&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;connection<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(&nbsp;each&nbsp;socket&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;all&nbsp;connections&nbsp;)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;fd&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;socket&nbsp;)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;can&nbsp;read&nbsp;data&n