﻿<?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++博客-CppExplore</title><link>http://www.cppblog.com/CppExplore/</link><description>一切像雾像雨又像风</description><language>zh-cn</language><lastBuildDate>Mon, 07 Jul 2008 02:59:12 GMT</lastBuildDate><pubDate>Mon, 07 Jul 2008 02:59:12 GMT</pubDate><ttl>60</ttl><item><title>职业之路</title><link>http://www.cppblog.com/CppExplore/archive/2008/06/18/53814.html</link><dc:creator>cppexplore</dc:creator><author>cppexplore</author><pubDate>Wed, 18 Jun 2008 02:13:00 GMT</pubDate><guid>http://www.cppblog.com/CppExplore/archive/2008/06/18/53814.html</guid><wfw:comment>http://www.cppblog.com/CppExplore/comments/53814.html</wfw:comment><comments>http://www.cppblog.com/CppExplore/archive/2008/06/18/53814.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/CppExplore/comments/commentRss/53814.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/CppExplore/services/trackbacks/53814.html</trackback:ping><description><![CDATA[<p>作者：CppExplore 网址：<a href="http://www.cppblog.com/CppExplore/"><u><font color=#800080>http://www.cppblog.com/CppExplore/</font></u></a><br>在这个blog上写了几篇技术文章，一是记录下自己对技术的一点浅显的看法，二是在自己的认知范围内揭示系统级别的核心技术，希望能对后来人能有一点帮助。从系统角度而言，技术本身只是实现业务的载体，业务才是系统的灵魂。因此除技术外，也准备写点其它方面的东西，大抵也就是写下面几个系列的文章，技术系列、业务系列、系统系列、测试系列、团队管理系列。以前本blog上起名为系统设计系列的文章，现已全部改名为技术系列了。</p>
<p><span style="COLOR: red">技术系列，</span>在本人的认知范围内，探讨系统级别的核心技术，文章描述的都是技术本身，最终目的是建立公用的模块库，比如含消息队列的线程模块、状态机模块、定时器模块、对象池模块、log模块、网络层模块、管理接口模块等等。</p>
<p>从个人的角度考虑，开发公用模块，可以加深对系统整体的了解，能有更多的时间去了解新的技术、去认识业务的重要性、去考虑系统划分的合理性，不要陷入技术繁琐细节的泥潭，技术仅仅是工具而已，它们背后的原理都很简单。</p>
<p>从团队的角度考虑，开发公有模块，可以增加系统的可维护性、减少对新员工的培训成本、使具有不同业务的系统在技术细节上呈现一致性，形成开发的可持续性，减少对个人技术的依赖，不会因为某个核心人员的离职而造成后续开发的戛然而止。</p>
<p>公有模块开发导致的后果是减少对个人的依赖，因此有的技术人员可能对开发这些模块产生抵触心理。个人认为，技术是没有边际的，单个人是永远也不会掌握所有技术，单纯的技术也不是正确的职业规划，固步自封只能导致自己技术水平的落后。以开放的心态、职业化的心态去做实际的开发、去交流沟通，最终受益的是自己。<br><br><span style="COLOR: red">业务系列</span>的文章写点本人接触过的业务，以公有协议为主线，mgcp、sip、rtsp、rtp、rtcp、加密框架等，协议本身、应用场景等，想想可写的东西也不多，和技术一样，都是很少很简单的东西。</p>
<p><span style="COLOR: red">系统系列</span>，则从业务的角度出发，描述一些通用系统，也就是纯共有协议业务系统。当然不会涉及到公司的系统，呵呵。比如说个媒体负载子系统，该子系统可以独立于信令协议，一个信令系统下可以挂载n个媒体子系统，可协同信令系统完成nat穿透、负载均衡、媒体流加解密等功能，使用私有协议和信令系统通讯，可定时比如60秒发一次负载个数信令到信令系统，一是作为心跳，二是作为负载均衡的依据。再比如一些顶层协议无关的proxy系统设计等。<br>从团队、公司的角度来考虑，开发公用系统的重要性不言而喻。开发公用系统也即开发工作由项目驱动转化为产品驱动、根据所做一系列项目的固有特点，找出事物的内在规律，合理划分子系统。<br>开发公用系统，可以降低开发的成本开销，便于公司去开发更多的业务，涉足更多的业务市场，从而形成不断扩大的业务市场，而不是以防守者的姿态，维护自己已有的甚至是逐渐萎缩的业务市场份额。<br><br><span style="COLOR: red">测试系列</span>。测试团队的开发还是集中于业务层面的测试，白盒测试、稳定性测试还是要研发自己来做。写点自己的测试心得。虽然本blog上的技术文章远多于测试，但个人认为测试的重要性大于技术，不重视测试的研发不是一个好研发，也不会成为一个好研发，顶多是一个夸夸其谈的华而不实者。</p>
<p><span style="COLOR: red">团队管理系列，</span>也或许不会写，毕竟不在管理位置，不会谋其职。但从职业发展的角度看，还是应当总结点，在不同的公司感受不同的管理，看看各个公司的相同点不同点，管理的初衷等。团队管理部分，个人看呈现下面几个部分:公司福利/公司制度、项目管理、技术培训、对员工的人文关怀、个人管理等。<br></p>
<img src ="http://www.cppblog.com/CppExplore/aggbug/53814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/CppExplore/" target="_blank">cppexplore</a> 2008-06-18 10:13 <a href="http://www.cppblog.com/CppExplore/archive/2008/06/18/53814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原创】技术系列之 必备外围功能-log</title><link>http://www.cppblog.com/CppExplore/archive/2008/06/05/52216.html</link><dc:creator>cppexplore</dc:creator><author>cppexplore</author><pubDate>Thu, 05 Jun 2008 01:54:00 GMT</pubDate><guid>http://www.cppblog.com/CppExplore/archive/2008/06/05/52216.html</guid><wfw:comment>http://www.cppblog.com/CppExplore/comments/52216.html</wfw:comment><comments>http://www.cppblog.com/CppExplore/archive/2008/06/05/52216.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/CppExplore/comments/commentRss/52216.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/CppExplore/services/trackbacks/52216.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 作者：CppExplore 网址：http://www.cppblog.com/CppExplore/log模块是一个小模块，却是每个系统必备的模块。优秀的系统一定会有优秀的log信息，也可以说全面到位的log信息在一定程度上决定了一个系统的健壮性。在linux上，log模块是跟踪程序运行，验证业务逻辑正确的唯一方法。一、功能一个优秀的log系统应该包含以下功能：（1）支持打印到屏幕、文件、soc...&nbsp;&nbsp;<a href='http://www.cppblog.com/CppExplore/archive/2008/06/05/52216.html'>阅读全文</a><img src ="http://www.cppblog.com/CppExplore/aggbug/52216.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/CppExplore/" target="_blank">cppexplore</a> 2008-06-05 09:54 <a href="http://www.cppblog.com/CppExplore/archive/2008/06/05/52216.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原创】技术系列之 网络模型（三）多路复用模型</title><link>http://www.cppblog.com/CppExplore/archive/2008/04/30/48529.html</link><dc:creator>cppexplore</dc:creator><author>cppexplore</author><pubDate>Wed, 30 Apr 2008 09:23:00 GMT</pubDate><guid>http://www.cppblog.com/CppExplore/archive/2008/04/30/48529.html</guid><wfw:comment>http://www.cppblog.com/CppExplore/comments/48529.html</wfw:comment><comments>http://www.cppblog.com/CppExplore/archive/2008/04/30/48529.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/CppExplore/comments/commentRss/48529.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/CppExplore/services/trackbacks/48529.html</trackback:ping><description><![CDATA[<p>作者：CppExplore 网址：<a href="http://www.cppblog.com/CppExplore/"><font color=#000080>http://www.cppblog.com/CppExplore/</font></a><br>多路复用的方式是真正实用的服务器程序，非多路复用的网络程序只能作为学习或着陪测的角色。本文说下个人接触过的多路复用函数：select/poll/epoll/port。kqueue的*nix系统没接触过，估计熟悉了上面四种，kqueue也只是需要熟悉一下而已。<br><strong>一、select模型</strong><br>select原型：</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">int</span><span style="COLOR: #000000">&nbsp;select(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;n,&nbsp;fd_set&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">readfds,&nbsp;fd_set&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">writefds,&nbsp;fd_set&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">exceptfds,&nbsp;struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">timeout);</span></div>
<p>其中参数n表示监控的所有fd中最大值＋1。<br>和select模型紧密结合的四个宏，含义不解释了：</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_CLR(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd,&nbsp;fd_set&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">set);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>FD_ISSET(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd,&nbsp;fd_set&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">set);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>FD_SET(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd,&nbsp;fd_set&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">set);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>FD_ZERO(fd_set&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">set);</span></div>
<p><span style="COLOR: red">理解select模型的关键在于理解fd_set</span>,为说明方便，取fd_set长度为1字节，fd_set中的每一bit可以对应一个文件描述符fd。则1字节长的fd_set最大可以对应8个fd。<br>（1）执行fd_set set; FD_ZERO(&amp;set);则set用位表示是0000,0000。<br>（2）若fd＝5,执行FD_SET(fd,&amp;set);后set变为0001,0000(第5位置为1)<br>（3）若再加入fd＝2，fd=1,则set变为0001,0011<br>（4）执行select(6,&amp;set,0,0,0)阻塞等待<br>（5）若fd=1,fd=2上都发生可读事件，则select返回，此时set变为0000,0011。注意：没有事件发生的fd=5被清空。</p>
<p>基于上面的讨论，可以轻松得出select模型的特点：<br>（1)可监控的文件描述符个数取决与sizeof(fd_set)的值。我这边服务器上sizeof(fd_set)＝512，每bit表示一个文件描述符，则我服务器上支持的最大文件描述符是512*8=4096。据说可调，另有说虽然可调，但调整上限受于编译内核时的变量值。本人对调整fd_set的大小不太感兴趣，参考<a href="http://www.cppblog.com/CppExplore/archive/2008/03/21/45061.html">http://www.cppblog.com/CppExplore/archive/2008/03/21/45061.html</a>中的模型2（1）可以有效突破select可监控的文件描述符上限。<br>（2）将fd加入select监控集的同时，还要再使用一个数据结构array保存放到select监控集中的fd，一是用于再select返回后，array作为源数据和fd_set进行FD_ISSET判断。二是select返回后会把以前加入的但并无事件发生的fd清空，则每次开始select前都要重新从array取得fd逐一加入（FD_ZERO最先），扫描array的同时取得fd最大值maxfd，用于select的第一个参数。<br>（3）可见select模型必须在select前循环array（加fd，取maxfd），select返回后循环array（FD_ISSET判断是否有时间发生）。</p>
<p>下面给一个伪码说明基本select模型的服务器模型：</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">array[slect_len];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>nSock</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>array[nSock</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">listen_fd;(之前listen&nbsp;port已绑定并listen)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>maxfd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">listen_fd;<br><img id=Codehighlighter1_100_488_Open_Image onclick="this.style.display='none'; Codehighlighter1_100_488_Open_Text.style.display='none'; Codehighlighter1_100_488_Closed_Image.style.display='inline'; Codehighlighter1_100_488_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_100_488_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_100_488_Closed_Text.style.display='none'; Codehighlighter1_100_488_Open_Image.style.display='inline'; Codehighlighter1_100_488_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">while</span><span id=Codehighlighter1_100_488_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_100_488_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;FD_ZERO(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">set);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;foreach&nbsp;(fd&nbsp;in&nbsp;array)&nbsp;<br><img id=Codehighlighter1_149_204_Open_Image onclick="this.style.display='none'; Codehighlighter1_149_204_Open_Text.style.display='none'; Codehighlighter1_149_204_Closed_Image.style.display='inline'; Codehighlighter1_149_204_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_149_204_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_149_204_Closed_Text.style.display='none'; Codehighlighter1_149_204_Open_Image.style.display='inline'; Codehighlighter1_149_204_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_149_204_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_149_204_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;fd大于maxfd，则maxfd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">fd<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FD_SET(fd,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">set)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&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;res=select(maxfd</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">set,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,</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;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(FD_ISSET(listen_fd,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">set))<br><img id=Codehighlighter1_272_338_Open_Image onclick="this.style.display='none'; Codehighlighter1_272_338_Open_Text.style.display='none'; Codehighlighter1_272_338_Closed_Image.style.display='inline'; Codehighlighter1_272_338_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_272_338_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_272_338_Closed_Text.style.display='none'; Codehighlighter1_272_338_Open_Image.style.display='inline'; Codehighlighter1_272_338_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_272_338_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_272_338_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;newfd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">accept(listen_fd);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array[nsock</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">newfd;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(--res&lt;=0) continue<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&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;foreach&nbsp;下标1开始&nbsp;(fd&nbsp;in&nbsp;array)&nbsp;<br><img id=Codehighlighter1_375_486_Open_Image onclick="this.style.display='none'; Codehighlighter1_375_486_Open_Text.style.display='none'; Codehighlighter1_375_486_Closed_Image.style.display='inline'; Codehighlighter1_375_486_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_375_486_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_375_486_Closed_Text.style.display='none'; Codehighlighter1_375_486_Open_Image.style.display='inline'; Codehighlighter1_375_486_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_375_486_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_375_486_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;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(FD_ISSET(fd,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">set))<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;执行读等相关操作<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果错误或者关闭，则要删除该fd，将array中相应位置和最后一个元素互换就好，nsock减一<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(--res&lt;=0) continue<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><strong>二、poll模型</strong><br>poll原型:</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">int</span><span style="COLOR: #000000">&nbsp;poll(struct&nbsp;pollfd&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">ufds,&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;nfds,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;timeout);<br><img id=Codehighlighter1_77_284_Open_Image onclick="this.style.display='none'; Codehighlighter1_77_284_Open_Text.style.display='none'; Codehighlighter1_77_284_Closed_Image.style.display='inline'; Codehighlighter1_77_284_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_77_284_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_77_284_Closed_Text.style.display='none'; Codehighlighter1_77_284_Open_Image.style.display='inline'; Codehighlighter1_77_284_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>struct&nbsp;pollfd&nbsp;</span><span id=Codehighlighter1_77_284_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_77_284_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_120_140_Open_Image onclick="this.style.display='none'; Codehighlighter1_120_140_Open_Text.style.display='none'; Codehighlighter1_120_140_Closed_Image.style.display='inline'; Codehighlighter1_120_140_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_120_140_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_120_140_Closed_Text.style.display='none'; Codehighlighter1_120_140_Open_Image.style.display='inline'; Codehighlighter1_120_140_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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_120_140_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_120_140_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;file&nbsp;descriptor&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_183_204_Open_Image onclick="this.style.display='none'; Codehighlighter1_183_204_Open_Text.style.display='none'; Codehighlighter1_183_204_Closed_Image.style.display='inline'; Codehighlighter1_183_204_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_183_204_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_183_204_Closed_Text.style.display='none'; Codehighlighter1_183_204_Open_Image.style.display='inline'; Codehighlighter1_183_204_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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">short</span><span style="COLOR: #000000">&nbsp;events;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_183_204_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_183_204_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;requested&nbsp;events&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_247_267_Open_Image onclick="this.style.display='none'; Codehighlighter1_247_267_Open_Text.style.display='none'; Codehighlighter1_247_267_Closed_Image.style.display='inline'; Codehighlighter1_247_267_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_247_267_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_247_267_Closed_Text.style.display='none'; Codehighlighter1_247_267_Open_Image.style.display='inline'; Codehighlighter1_247_267_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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">short</span><span style="COLOR: #000000">&nbsp;revents;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_247_267_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_247_267_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;returned&nbsp;events&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;</span></div>
<p>和select相比，两大改进：<br>（1）不再有fd个数的上限限制，可以将参数ufds想象成栈低指针，nfds是栈中元素个数，该栈可以无限制增长<br>（2）引入pollfd结构，将fd信息、需要监控的事件、返回的事件分开保存，则poll返回后不会丢失fd信息和需要监控的事件信息，也就省略了select模型中前面的循环操作，返回后的循环仍然不可避免。另每次poll阻塞操作都会自动把上次的revents清空。<br>poll的服务器模型伪码：</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">struct&nbsp;pollfd&nbsp;fds[POLL_LEN];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>unsigned&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;nfds</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>fds[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].fd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">server_sockfd;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>fds[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].events</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">POLLIN</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">POLLPRI;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>nfds</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;<br><img id=Codehighlighter1_118_249_Open_Image onclick="this.style.display='none'; Codehighlighter1_118_249_Open_Text.style.display='none'; Codehighlighter1_118_249_Closed_Image.style.display='inline'; Codehighlighter1_118_249_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_118_249_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_118_249_Closed_Text.style.display='none'; Codehighlighter1_118_249_Open_Image.style.display='inline'; Codehighlighter1_118_249_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">while</span><span id=Codehighlighter1_118_249_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_118_249_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;res=poll(fds,nfds,</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img id=Codehighlighter1_178_194_Open_Image onclick="this.style.display='none'; Codehighlighter1_178_194_Open_Text.style.display='none'; Codehighlighter1_178_194_Closed_Image.style.display='inline'; Codehighlighter1_178_194_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_178_194_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_178_194_Closed_Text.style.display='none'; Codehighlighter1_178_194_Open_Image.style.display='inline'; Codehighlighter1_178_194_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(fds[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].revents</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(POLLIN</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">POLLPRI))</span><span id=Codehighlighter1_178_194_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_178_194_Open_Text><span style="COLOR: #000000">{执行accept并加入fds中,if(--res&lt;=0)continue}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_243_247_Open_Image onclick="this.style.display='none'; Codehighlighter1_243_247_Open_Text.style.display='none'; Codehighlighter1_243_247_Closed_Image.style.display='inline'; Codehighlighter1_243_247_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_243_247_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_243_247_Closed_Text.style.display='none'; Codehighlighter1_243_247_Open_Image.style.display='inline'; Codehighlighter1_243_247_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;循环之后的fds，</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(fds[i].revents</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(POLLIN</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">POLLERR&nbsp;))</span><span id=Codehighlighter1_243_247_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_243_247_Open_Text><span style="COLOR: #000000">{操作略if(--res&lt;=0)continue}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
注意select和poll中res的检测，可有效减少循环的次数，这也是大量死连接存在时，select和poll性能下降厉害的原因。<br>
<p><strong>三、epoll模型</strong></p>
<p>epoll阻塞操作的原型：</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">int</span><span style="COLOR: #000000">&nbsp;epoll_wait(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;epfd,&nbsp;struct&nbsp;epoll_event&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;events,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;maxevents,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;timeout)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>epoll引入了新的结构epoll_event。<br><img id=Codehighlighter1_132_265_Open_Image onclick="this.style.display='none'; Codehighlighter1_132_265_Open_Text.style.display='none'; Codehighlighter1_132_265_Closed_Image.style.display='inline'; Codehighlighter1_132_265_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_132_265_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_132_265_Closed_Text.style.display='none'; Codehighlighter1_132_265_Open_Image.style.display='inline'; Codehighlighter1_132_265_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>typedef&nbsp;union&nbsp;epoll_data&nbsp;</span><span id=Codehighlighter1_132_265_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_132_265_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;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">ptr;<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;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd;<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;__uint32_t&nbsp;u32;<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;__uint64_t&nbsp;u64;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;epoll_data_t;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_313_445_Open_Image onclick="this.style.display='none'; Codehighlighter1_313_445_Open_Text.style.display='none'; Codehighlighter1_313_445_Closed_Image.style.display='inline'; Codehighlighter1_313_445_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_313_445_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_313_445_Closed_Text.style.display='none'; Codehighlighter1_313_445_Open_Image.style.display='inline'; Codehighlighter1_313_445_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;epoll_event&nbsp;</span><span id=Codehighlighter1_313_445_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_313_445_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_352_369_Open_Image onclick="this.style.display='none'; Codehighlighter1_352_369_Open_Text.style.display='none'; Codehighlighter1_352_369_Closed_Image.style.display='inline'; Codehighlighter1_352_369_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_352_369_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_352_369_Closed_Text.style.display='none'; Codehighlighter1_352_369_Open_Image.style.display='inline'; Codehighlighter1_352_369_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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__uint32_t&nbsp;events;&nbsp;&nbsp;</span><span id=Codehighlighter1_352_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">/**/</span><span id=Codehighlighter1_352_369_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Epoll&nbsp;events&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_408_431_Open_Image onclick="this.style.display='none'; Codehighlighter1_408_431_Open_Text.style.display='none'; Codehighlighter1_408_431_Closed_Image.style.display='inline'; Codehighlighter1_408_431_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_408_431_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_408_431_Closed_Text.style.display='none'; Codehighlighter1_408_431_Open_Image.style.display='inline'; Codehighlighter1_408_431_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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;epoll_data_t&nbsp;data;&nbsp;&nbsp;</span><span id=Codehighlighter1_408_431_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_408_431_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;User&nbsp;data&nbsp;variable&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;</span></div>
<p>与以上模型的优点：<br>（1）它保留了poll的两个相对与select的优点<br>（2）epoll_wait的参数events作为出参，直接返回了有事件发生的fd，epoll_wait的返回值既是发生事件的个数，省略了poll中返回之后的循环操作。<br>（3）不再象select、poll一样将标识符局限于fd，epoll中可以将标识符扩大为指针，大大增加了epoll模型下的灵活性。<br>epoll的服务器模型伪码：</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">epollfd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">epoll_create(EPOLL_LEN);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>epoll_ctl(epollfd,EPOLL_CTL_ADD,server_sockfd,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">ev)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>struct&nbsp;epoll_event&nbsp;events[EPOLL_MAX_EVENT];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_134_226_Open_Image onclick="this.style.display='none'; Codehighlighter1_134_226_Open_Text.style.display='none'; Codehighlighter1_134_226_Closed_Image.style.display='inline'; Codehighlighter1_134_226_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_134_226_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_134_226_Closed_Text.style.display='none'; Codehighlighter1_134_226_Open_Image.style.display='inline'; Codehighlighter1_134_226_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_134_226_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_134_226_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>nfds</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">epoll_wait(epollfd,events,EPOLL_MAX_EVENT,</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>循环nfds，是server_sockfd则accept，否则执行响应操作<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p>epoll使用中的问题：<br>（1）epoll_ctl的EPOLL_CTL_DEL操作中，最后一个参数是无意义的，但是在小版本号过低的2.6内核下要求最后一个参数一定非NULL，否则返回失败，并且返回的errno在man epoll_ctl中不存在，因此安全期间，保证epoll_ctl的最后一个参数总非NULLL。<br>（2）如果一个fd（比如管道）的事件导致了另一个fd2的删除，则必须扫描返回结果集中是否有fd2，有则在结果集中删除，避免冲突。<br>（3）有文章说epoll在G网环境下性能会低于poll/select，看有些测试，给出的拐点在2w/s并发之后，我本人的工作范围不可能达到这么高的并发，个人在测试性能的时候最大也是取的1w/s的并发，一个是因为系统单进程允许打开的文件描述符最大值，4w的数字太高了，另一个就是我这边服务器的性能达不到那么高的性能，极限1.7w/s的响应，那测试的数据竟然在2w并发的时候还有2w的响应，不知道是什么硬件配置。或许等有了G网的环境，会关注epoll高并发下的性能下降</p>
<p>。<br>（4）epoll的LT和ET性能的差异，我测试的数据表明两者性能相当，&#8220;使用epoll就是为了高性能，就是要使用ET模式&#8221;这个说法是站不住脚的。个人倾向于使用LT模式，编程简单、安全。</p>
<p><strong>四、port模型</strong><br>port则和epoll非常接近，不需要前后的两次扫描，直接返回有事件的结果，可以象epoll一样绑定指针，不同点是<br>（1）epoll可以返回多个事件，而port一次只返回一个（port_getn可以返回多个，但是在不到指定的n值时，等待直到达到n个）<br>（2）port返回的结果会自动port_dissociate，如果要再次监控，需要重新port_associate<br>这个就不多说了。</p>
<p><span style="COLOR: red">可以看出select--&gt;poll--&gt;epoll/port的演化路线：</span><br>（1）从readset、writeset等分离到 将读写事件集中到统一的结构<br>（2）从阻塞操作前后的两次循环 到 之后的一次循环&nbsp; 到精确返回有事件发生的fd<br>（3）从只能绑定fd信息，到可以绑定指针结构信息</p>
<p><strong>五、抽象接口</strong><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: #000000">&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;init()</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;wait()</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;next_result()</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;delete_from_results(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;data)</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;get_data(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;event)</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;get_event(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;event)</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;add_data(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd,XPollData&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;data)</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;delete_data(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd,XPollData&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">data)</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;change_data(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd,XPollData&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">data)</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;reset_data(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd,XPollData&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">data)</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;</span></div>
<p>使用的时候就是先init，再wait，再循环执行next_result直到空，每个result，使用get_data和get_event挨个处理，如果某个fd引起另一个fd关闭，调delete_from_results（除epoll，其它都直接return），处理完reset_data（select和port用，poll/epoll直接return）。<br></p>
<img src ="http://www.cppblog.com/CppExplore/aggbug/48529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/CppExplore/" target="_blank">cppexplore</a> 2008-04-30 17:23 <a href="http://www.cppblog.com/CppExplore/archive/2008/04/30/48529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原创】技术系列之 定时器（二）</title><link>http://www.cppblog.com/CppExplore/archive/2008/04/03/46211.html</link><dc:creator>cppexplore</dc:creator><author>cppexplore</author><pubDate>Thu, 03 Apr 2008 13:49:00 GMT</pubDate><guid>http://www.cppblog.com/CppExplore/archive/2008/04/03/46211.html</guid><wfw:comment>http://www.cppblog.com/CppExplore/comments/46211.html</wfw:comment><comments>http://www.cppblog.com/CppExplore/archive/2008/04/03/46211.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/CppExplore/comments/commentRss/46211.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/CppExplore/services/trackbacks/46211.html</trackback:ping><description><![CDATA[<p>作者：CppExplore 网址：<a href="http://www.cppblog.com/CppExplore/"><font color=#000080>http://www.cppblog.com/CppExplore/</font></a><br><strong>一、上篇文章描述。</strong>文章《定时器（一）》<a href="http://www.cppblog.com/CppExplore/archive/2008/04/02/46111.html">http://www.cppblog.com/CppExplore/archive/2008/04/02/46111.html</a>实现了一个定时器模块，这个实现每次延时时间到都要扫描所有的定时器对象，效率低下。开始设想的时候，LIST中的定时器对象保存间隔时间段的毫秒值，导致每次延时时间到都要做&#8220;时间减少操作&#8221;直到减少到零，并且得出不需排序的结论。<br><strong>二、改进。</strong>如果其中保存超时的精确时间点，而不是保存时间段，则可以在LIST中根据超时时间点对定时器对象排序，延时时间到，则从链表头扫描定时器对象，取其超时时间点与当前时间点对比，如果小于等于当前时间点，则进行超时处理，否则终止继续扫描，避免不必要的扫描操作。同时插入对象的时候插入到合适的位置，以保持链表的顺序化。<br><strong>三、主要数据结构。</strong>此次容器结构选择内核数据结构中的TAILQ，因为LIST没有插入尾部操作（当要插入的定时器对象超时时间点大于所有队列中的对象的时候）。<br><strong>四、新的时间类型操作</strong>。另一方面很多地方涉及到对struct timeval结构的操作，这里介绍几个对该结构进行操作的宏，都已经在系统头文件中定义，可以使用函数原型的方式理解就是如下：</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">timeradd(struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p1,struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p2,struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">result);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>timersub(struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p1,struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p2,struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">result);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>timercmp(struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p1,struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p2,operator&nbsp;op);</span></div>
<p>对struct timespec同样有timespecadd/timespecsub/timespeccmp，另外还有两者的转换宏，使用函数原型的方式理解就是：</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">TIMEVAL_TO_TIMESPEC(struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p1,struct&nbsp;timespec&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">result);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>TIMESPEC_TO_TIMEVAL(struct&nbsp;timespec&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p1,struct&nbsp;timeval&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">result);</span></div>
<p>如果系统的头文件中找不到，也可以自己实现下，明白这两个结构的细节结构，实现也很简单，这里拿timeradd举例，其它不说了。</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">#define&nbsp;&nbsp;&nbsp;&nbsp;timeradd(tvp,&nbsp;uvp,&nbsp;vvp)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br><img id=Codehighlighter1_44_279_Open_Image onclick="this.style.display='none'; Codehighlighter1_44_279_Open_Text.style.display='none'; Codehighlighter1_44_279_Closed_Image.style.display='inline'; Codehighlighter1_44_279_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_44_279_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_44_279_Closed_Text.style.display='none'; Codehighlighter1_44_279_Open_Image.style.display='inline'; Codehighlighter1_44_279_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_44_279_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_44_279_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vvp)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tv_sec&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(tvp)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tv_sec&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;(uvp)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tv_sec;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vvp)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tv_usec&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(tvp)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tv_usec&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;(uvp)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tv_usec;&nbsp;&nbsp;&nbsp;&nbsp;\<br><img id=Codehighlighter1_197_267_Open_Image onclick="this.style.display='none'; Codehighlighter1_197_267_Open_Text.style.display='none'; Codehighlighter1_197_267_Closed_Image.style.display='inline'; Codehighlighter1_197_267_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_197_267_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_197_267_Closed_Text.style.display='none'; Codehighlighter1_197_267_Open_Image.style.display='inline'; Codehighlighter1_197_267_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 style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;((vvp)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tv_usec&nbsp;</span><span style="COLOR: #000000">&gt;=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1000000</span><span style="COLOR: #000000">)&nbsp;</span><span id=Codehighlighter1_197_267_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_197_267_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<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;(vvp)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tv_sec</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<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;(vvp)</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tv_usec&nbsp;</span><span style="COLOR: #000000">-=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1000000</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<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">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span></div>
<strong>五、实现。</strong>和上篇文章相比，改动比较的在add_timer_和process方法。当前add_timer_操作需要顺序扫描插入到合适的位置以保持链表的顺序。当前process的主要代码如下：
<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_44_907_Open_Image onclick="this.style.display='none'; Codehighlighter1_44_907_Open_Text.style.display='none'; Codehighlighter1_44_907_Closed_Image.style.display='inline'; Codehighlighter1_44_907_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_44_907_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_44_907_Closed_Text.style.display='none'; Codehighlighter1_44_907_Open_Image.style.display='inline'; Codehighlighter1_44_907_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(manager</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_state</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">TIMER_MANAGER_START)</span><span id=Codehighlighter1_44_907_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_44_907_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;tm.tv_sec</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">manager</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_interval.tv_sec;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;tm.tv_usec</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">manager</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_interval.tv_usec;<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">(select(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">tm)</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">errno</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">EINTR);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;gettimeofday(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">now,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br><img id=Codehighlighter1_194_205_Open_Image onclick="this.style.display='none'; Codehighlighter1_194_205_Open_Text.style.display='none'; Codehighlighter1_194_205_Closed_Image.style.display='inline'; Codehighlighter1_194_205_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_194_205_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_194_205_Closed_Text.style.display='none'; Codehighlighter1_194_205_Open_Image.style.display='inline'; Codehighlighter1_194_205_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span id=Codehighlighter1_194_205_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_194_205_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">加上误差补偿时间</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;timeradd(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">now,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">manager－</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">m_repair,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">stand);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pthread_mutex_lock(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">manager</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_mutex);<br><img id=Codehighlighter1_337_861_Open_Image onclick="this.style.display='none'; Codehighlighter1_337_861_Open_Text.style.display='none'; Codehighlighter1_337_861_Closed_Image.style.display='inline'; Codehighlighter1_337_861_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_337_861_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_337_861_Closed_Text.style.display='none'; Codehighlighter1_337_861_Open_Image.style.display='inline'; Codehighlighter1_337_861_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;TAILQ_FOREACH(item,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(manager</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">list_),&nbsp;entry_)</span><span id=Codehighlighter1_337_861_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_337_861_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_339_377_Open_Image onclick="this.style.display='none'; Codehighlighter1_339_377_Open_Text.style.display='none'; Codehighlighter1_339_377_Closed_Image.style.display='inline'; Codehighlighter1_339_377_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_339_377_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_339_377_Closed_Text.style.display='none'; Codehighlighter1_339_377_Open_Image.style.display='inline'; Codehighlighter1_339_377_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span id=Codehighlighter1_339_377_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_339_377_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">取修正后的时间逐个和定时器中的超时时间点相比，遇到不超时对象则退出扫描</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_420_840_Open_Image onclick="this.style.display='none'; Codehighlighter1_420_840_Open_Text.style.display='none'; Codehighlighter1_420_840_Closed_Image.style.display='inline'; Codehighlighter1_420_840_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_420_840_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_420_840_Closed_Text.style.display='none'; Codehighlighter1_420_840_Open_Image.style.display='inline'; Codehighlighter1_420_840_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 style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(timercmp(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">item</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_endtime,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">stand,</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">))</span><span id=Codehighlighter1_420_840_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_420_840_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">(item</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_func)<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;&nbsp;&nbsp; &nbsp;item</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_func(item,item</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_data);<br><img id=Codehighlighter1_518_611_Open_Image onclick="this.style.display='none'; Codehighlighter1_518_611_Open_Text.style.display='none'; Codehighlighter1_518_611_Closed_Image.style.display='inline'; Codehighlighter1_518_611_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_518_611_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_518_611_Closed_Text.style.display='none'; Codehighlighter1_518_611_Open_Image.style.display='inline'; Codehighlighter1_518_611_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 style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(item</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_type</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">CTimer::TIMER_ONCE)</span><span id=Codehighlighter1_518_611_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_518_611_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;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; manager</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">remove_timer_(item);<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; &nbsp;item</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_state</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CTimer::TIMER_TIMEOUT;<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;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_659_836_Open_Image onclick="this.style.display='none'; Codehighlighter1_659_836_Open_Text.style.display='none'; Codehighlighter1_659_836_Closed_Image.style.display='inline'; Codehighlighter1_659_836_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_659_836_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_659_836_Closed_Text.style.display='none'; Codehighlighter1_659_836_Open_Image.style.display='inline'; Codehighlighter1_659_836_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 style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(item</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_type</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">CTimer::TIMER_CIRCLE)</span><span id=Codehighlighter1_659_836_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_659_836_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_661_716_Open_Image onclick="this.style.display='none'; Codehighlighter1_661_716_Open_Text.style.display='none'; Codehighlighter1_661_716_Closed_Image.style.display='inline'; Codehighlighter1_661_716_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_661_716_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_661_716_Closed_Text.style.display='none'; Codehighlighter1_661_716_Open_Image.style.display='inline'; Codehighlighter1_661_716_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span id=Codehighlighter1_661_716_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_661_716_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">循环性的要保证链表的顺序性，如要重新插入，保存entry_的原因，是执行新的插入后不要影响当前进行的循环</span><span style="COLOR: #008000">*/</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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmpTimer.entry_</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">item</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">entry_;<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; manager</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">remove_timer_(item);<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;manager</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">add_timer_(item);<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; item</span><span style="COLOR: #000000">=&amp;</span><span style="COLOR: #000000">tmpTimer;}<br></span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&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/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0000ff">else </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;pthread_mutex_unlock(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">manager</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_mutex);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br><strong>六、源码</strong><br>写了个简单的makefile，执行make就可以生成测试程序:test，执行./test可以看运行效果。make由make so和make test组成，make so在lib目录下生成libtimer.a。make clean清空。<br>源代码下载<a href="http://www.cppblog.com/Files/CppExplore/timer.tar.gz">这里</a>： <a style="COLOR: #0000ff" href="http://www.cppblog.com/Files/CppExplore/timer.tar.gz">http://www.cppblog.com/<span style="COLOR: #0000ff">Files/CppExplore/timer.tar.gz</a></span> <br><strong>七、后记</strong><br>与上一版本相比，该文中的定时器实现要求在定时器模块运行期间不能修改系统实际，上一版本实现则无此限制。<br>定时器模块的锁初始化为fastmutex方式，因此在回调函数里注意不能再调用CTimer的start stop reset等方法，以免死锁，如果有调用的需求，可以把锁修改为循环锁recmutex方式。<br>&nbsp;<br><strong>2008/4/8补记：</strong>本文是timer的v2实现，定时器timer在业务线程中执行start的时候，要执行扫描排序操作，导致返回时间延长。新的v3版本实现，定时器timer的start操作不再执行扫描操作，而是简单插入队列头同时置一变量表示尚未排序。定时器线程延迟时间到，首先扫描未排序对象，执行排序（从尾部逆向对比，根据实际使用，越晚插入的对象，超时的时间点越靠后，逆向则尽可能减少对比操作），再扫描判断是否超时。详细的代码不发了，如果需要，可以发邮件索取。<br>修改的出发点：尽量减少定时器对象操作对业务线程的影响。 
<img src ="http://www.cppblog.com/CppExplore/aggbug/46211.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/CppExplore/" target="_blank">cppexplore</a> 2008-04-03 21:49 <a href="http://www.cppblog.com/CppExplore/archive/2008/04/03/46211.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原创】技术系列之 定时器（一）</title><link>http://www.cppblog.com/CppExplore/archive/2008/04/02/46111.html</link><dc:creator>cppexplore</dc:creator><author>cppexplore</author><pubDate>Wed, 02 Apr 2008 15:19:00 GMT</pubDate><guid>http://www.cppblog.com/CppExplore/archive/2008/04/02/46111.html</guid><wfw:comment>http://www.cppblog.com/CppExplore/comments/46111.html</wfw:comment><comments>http://www.cppblog.com/CppExplore/archive/2008/04/02/46111.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/CppExplore/comments/commentRss/46111.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/CppExplore/services/trackbacks/46111.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 作者：CppExplore 网址：http://www.cppblog.com/CppExplore/一、&nbsp;基础知识1、时间类型。Linux下常用的时间类型有4个：time_t，struct timeval，struct timespec，struct tm。（1）time_t是一个长整型，一般用来表示用1970年以来的秒数。（2）Struct timeval有两个成员，一个是秒，一个是...&nbsp;&nbsp;<a href='http://www.cppblog.com/CppExplore/archive/2008/04/02/46111.html'>阅读全文</a><img src ="http://www.cppblog.com/CppExplore/aggbug/46111.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/CppExplore/" target="_blank">cppexplore</a> 2008-04-02 23:19 <a href="http://www.cppblog.com/CppExplore/archive/2008/04/02/46111.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原创】技术系列之 网络模型（二）</title><link>http://www.cppblog.com/CppExplore/archive/2008/03/21/45061.html</link><dc:creator>cppexplore</dc:creator><author>cppexplore</author><pubDate>Fri, 21 Mar 2008 09:16:00 GMT</pubDate><guid>http://www.cppblog.com/CppExplore/archive/2008/03/21/45061.html</guid><wfw:comment>http://www.cppblog.com/CppExplore/comments/45061.html</wfw:comment><comments>http://www.cppblog.com/CppExplore/archive/2008/03/21/45061.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.cppblog.com/CppExplore/comments/commentRss/45061.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/CppExplore/services/trackbacks/45061.html</trackback:ping><description><![CDATA[<p>作者：CppExplore 网址：<a href="http://www.cppblog.com/CppExplore/">http://www.cppblog.com/CppExplore/</a><br>本章主要列举服务器程序的各种网络模型，示例程序以及性能对比后面再写。<br><strong>一、分类依据。</strong>服务器的网络模型分类主要依据以下几点<br>（1）是否阻塞方式处理请求，是否多路复用，使用哪种多路复用函数<br>（2）是否多线程，多线程间如何组织<br>（3）是否多进程，多进程的切入点一般都是accept函数前<br><strong>二、分类。</strong>首先根据是否多路复用分为三大类：<br>（1）阻塞式模型<br>（2）多路复用模型<br>（3）实时信号模型<br><strong>三、详细分类。</strong><br><strong>1、阻塞式模型根据是否多线程分四类：<br></strong><span style="COLOR: red">（1）单线程处理。</span>实现可以参见<a href="http://www.cppblog.com/CppExplore/archive/2008/03/14/44509.html">http://www.cppblog.com/CppExplore/archive/2008/03/14/44509.html</a>后面的示例代码。<br><span style="COLOR: red">（2）一个请求一个线程。</span><br>主线程阻塞在accept处，新连接到来，实时生成线程处理新连接。受限于进程的线程数，以及实时创建线程的开销，过多线程后上下文切换的开销，该模型也就是有学习上价值。<br><span style="COLOR: red">（3）预派生一定数量线程，并且所有线程阻塞在accept处。<br></span>该模型与下面的（4）类似与线程的领导者/追随者模型。<br>传统的看法认为多进程（linux上线程仍然是进程方式）同时阻塞在accept处，当新连接到来时会有&#8220;惊群&#8221;现象发生，即所有都被激活，之后有一个获取连接描述符返回，其它再次转为睡眠。linux从2.2.9版本开始就不再存在这个问题，只会有一个被激活，其它平台依旧可能有这个问题，甚至是不支持所有进程直接在accept阻塞。<br><span style="COLOR: red">（4）预派生一定数量线程，并且所有线程阻塞在accept前的线程锁处。<br></span>一次只有一个线程能阻塞在accept处。避免不支持所有线程直接阻塞在accept，并且避免惊群问题。特别是当前linux2.6的线程库下，模型（3）没有存在的价值了。另有文件锁方式，不具有通用性，并且效率也不高，不再单独列举。<br><span style="COLOR: red">（5）主线程处理accept，预派生多个线程（线程池）处理连接。<br></span>类似与线程的半同步/半异步模型。<br>主线程的accept返回后，将clientfd放入预派生线程的线程消息队列，线程池读取线程消息队列处理clientfd。主线程只处理accept，可以快速返回继续调用accept，可以避免连接爆发情况的拒绝连接问题，另加大线程消息队列的长度，可以有效减少线程消息队列处的系统调用次数。<br><span style="COLOR: red">（6）预派生多线程阻塞在accept处，每个线程又有预派生线程专门处理连接。<br><span style="COLOR: #000000">（</span></span>3）和（4）/（5）的复合体。<br>经测试，（5）中的accept线程处理能力非常强，远远大于业务线程，并发10000的连接数也毫无影响，因此该模型没有实际意义。<br><span style="COLOR: #ff0000">总结</span>：就前五模型而言，性能最好的是模型（5）。模型（3）/(4)可以一定程度上改善模型（1）的处理性能，处理爆发繁忙的连接，仍然不理想。。阻塞式模型因为读的阻塞性，容易受到攻击，一个死连接（建立连接但是不发送数据的连接）就可以导致业务线程死掉。因此内部服务器的交互可以采用这类模型，对外的服务不适合。优先（5），然后是（4），然后是（1），其它不考虑。<br><strong>2、多路复用模型根据多路复用点、是否多线程分类：</strong><br>以下各个模型依据选用select/poll/epoll又都细分为3类。下面个别术语采用select中的，仅为说明。<br><span style="COLOR: #ff0000">（1）accept函数在多路复用函数之前，主线程在accept处阻塞，多个从线程在多路复用函数处阻塞。</span>主线程和从线程通过管道通讯，主线程通过管道依次将连接的clientfd写入对应从线程管道，从线程把管道的读端pipefd作为fd_set的第一个描述符，如pipefd可读，则读数据，根据预定义格式分解出clientfd放入fd_set，如果clientfd可读，则read之后处理业务。<br>此方法可以避免select的fd_set上限限制，具体机器上select可以支持多少个描述符，可以通过打印sizeof(fd_set)查看，我机器上是512字节，则支持512&#215;8＝4096个。为了支持多余4096的连接数，此模型下就可以创建多个从线程分别多路复用，主线程accept后平均放入（顺序循环）各个线程的管道中。创建5个从线程以其对应管道，就可以支持2w的连接，足够了。另一方面相对与单线程的select，单一连接可读的时候，还可以减少循环扫描fd_set的次数。单线程下要扫描所有fd_set（如果再最后），该模型下，只需要扫描所在线程的fd_set就可。<br><span style="COLOR: red">（2）accept函数在多路复用函数之前，与（1）的差别在于，主线程不直接与从线程通过管道通讯，而是将获取的fd放入另一缓存线程的线程消息队列，缓存线程读消息队列，然后通过管道与从线程通讯。<br></span>目的在主线程中减少系统调用，加快accept的处理，避免连接爆发情况下的拒绝连接。<br><span style="COLOR: red">（3）多路复用函数在accept之前</span><span style="COLOR: red">。</span>多路复用函数返回，如果可读的是serverfd，则accept，其它则read，后处理业务，这是多路复用通用的模型，也是经典的reactor模型。<br><span style="COLOR: red">（</span><span style="COLOR: red">4）连接在单独线程中处理。<br><span style="COLOR: #000000">以上（1）（2）（3）都可以在检测到cliendfd可读的时候，把描述符写入另一线程（也可以是线程池）的线程消息队列，另一线程（或线程池）负责read，后处理业务。</span></span><br><span style="COLOR: #ff0000">（5）业务线程独立，下面的网络层读取结束后通知业务线程。</span><br>以上（1）（2）（3）（4）中都可以将业务线程（可以是线程池）独立，事先告之（1）、（2）、（3）、（4）中read所在线程（上面1、2、4都可以是线程池），需要读取的字符串结束标志或者需要读取的字符串个数，读取结束，则将clientfd/buffer指针放入业务线程的线程消息队列，业务线程读取消息队列处理业务。这也就是经典的proactor模拟。<br><span style="COLOR: #ff0000">总结：</span>模型（1）是拓展select处理能力不错选择；模型（2）是模型（1）在爆发连接下的调整版本；模型（3）是经典的reactor，epoll在该模型下性能就已经很好，而select/poll仍然存在爆发连接的拒绝连接情况；模型（4）（5）则是方便业务处理，对模型（3）进行多线程调整的版本。带有复杂业务处理的情况下推荐模型（5）。根据测试显示，使用epoll的时候，模型（1）（2）相对（3）没有明显的性能优势，（1）由于主线程两次的系统调用，反而性能下降。<br><strong>3、实时信号模型：</strong><br>使用fcntl的F_SETSIG操作，把描述符可读的信号由不可靠的SIGIO(SYSTEM V)或者SIGPOLL(BSD)换成可靠信号。即可成为替代多路复用的方式。优于select/poll，特别是在大量死连接存在的情况下，但不及epoll。<br><strong>四、多进程的参与的方式</strong><br><span style="COLOR: red">（1）fork模型。fork后所有进程直接在accept阻塞。</span>以上主线程在accept阻塞的都可以在accept前fork为多进程。同样面临惊群问题。<br><span style="COLOR: red">（2）fork模型。fork后所有进程阻塞在accept前的线程锁处。</span>同线程中一样避免不支持所有进程直接阻塞在accept或者惊群问题，所有进程阻塞在共享内存上实现的线程互斥锁。<br><span style="COLOR: red">（3）业务和网络层分离为不同进程模型。</span>这个模型可能是受unix简单哲学的影响，一个进程完成一件事情，复杂的事情通过多个进程结合管道完成。我见过进程方式的商业协议栈实现。自己暂时还没有写该模型的示例程序测试对比性能。<br><span style="COLOR: red">（4）均衡负载模型。</span>起多个进程绑定到不同的服务端口，前端部署lvs等均衡负载系统，暴露一个网络地址，后端映射到不同的进程，实现可扩展的多进程方案。<br><span style="COLOR: red">总结：</span>个人认为（1）（2）没什么意义。（3）暂不评价。（4）则是均衡负载方案，和以上所有方案不冲突。<br>以上模型的代码示例以及性能对比后面给出。<br></p>
<img src ="http://www.cppblog.com/CppExplore/aggbug/45061.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/CppExplore/" target="_blank">cppexplore</a> 2008-03-21 17:16 <a href="http://www.cppblog.com/CppExplore/archive/2008/03/21/45061.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原创】技术系列之 线程（二）</title><link>http://www.cppblog.com/CppExplore/archive/2008/03/20/44949.html</link><dc:creator>cppexplore</dc:creator><author>cppexplore</author><pubDate>Thu, 20 Mar 2008 06:33:00 GMT</pubDate><guid>http://www.cppblog.com/CppExplore/archive/2008/03/20/44949.html</guid><wfw:comment>http://www.cppblog.com/CppExplore/comments/44949.html</wfw:comment><comments>http://www.cppblog.com/CppExplore/archive/2008/03/20/44949.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/CppExplore/comments/commentRss/44949.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/CppExplore/services/trackbacks/44949.html</trackback:ping><description><![CDATA[<p>作者：CppExplore&nbsp; 网址：<a href="http://www.cppblog.com/CppExplore/">http://www.cppblog.com/CppExplore/</a><br>为了后面写的《网络模型（二）》，多写一篇关于线程的。线程使用涉及的主要数据结构以及应用框架可以参考<a href="http://www.cppblog.com/CppExplore/archive/2008/01/15/41175.html">http://www.cppblog.com/CppExplore/archive/2008/01/15/41175.html</a>。本文的主要目的是给出linux下实用的线程消息队列实现。<br><strong>一、linux上线程相关的操作有下面几种：</strong><br>（1）pthread_t类型的创建、属性创建设置等。<br>这类具体可以:man pthread_creat; man pthread_attr_init;man pthread_detach;man pthread_join;等查看<br>（2）pthread_mutex_t类型的操作。<br>这类具体可以: man pthread_mutex_init可以看到所有相关的操作。<br>（3）pthread_cond_t类型的操作。同样：man pthread_cond_init。pthread_cond_t的wait和signal操作一定要和pthread_mutex_t的lock、unlock配合使用。类似于此：</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">pthread_mutex_t&nbsp;mux</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">PTHREAD_MUTEX_INITIALIZER;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>pthread_cond_t&nbsp;cond</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">PTHREAD_COND_INITIALIZER;<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">wait操作：</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">pthread_mutex_lock(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>pthread_cond_wait(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">cond,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">睡眠前将内部会执行pthread_mutex_unlock，醒来时内部会执行pthread_mutex_lock</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">pthread_mutex_unlock(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);<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">signal操作</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">pthread_mutex_lock(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>pthread_cond_signal(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">cond);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>pthread_mutex_unlock(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>（4）sem_t类型的操作。同样:man sem_init 这个系列一般是用不到的，太重量级了，也是最强大的一种。</p>
<p><strong>二、linux2.6内核的线程库。</strong>2.6内核的默认安装的是redhat公司的NPTL（原生posix线程库），以前内核安装的是LinuxThreads库，两者的简单介绍可以看<a href="http://www.ibm.com/developerworks/cn/linux/l-threading.html">http://www.ibm.com/developerworks/cn/linux/l-threading.html</a>。不过对于应用者，分析两者的区别和优劣也没什么大意义。这里特别提下NPTL的futex机制。借助该机制，pthread_mutex的性能大大提高，只要不进入竞争态，进程就不会陷入内核态，则意味着可以放心使用pthread_mutex，只要不进入竞争态，就象int i;i++之类的语句一样高效。这点可以自己写示例程序，通过strace -c 跟踪进程的系统调用得以证实，另外还可以证实总是进入内核态的操作有pthread_cond_signal和sem_post。</p>
<p><strong>三、实用的线程消息队列实现。</strong>下面设计一个具有线程消息队列的线程封装类。通过上面的分析，我们可以有如下结论：<br>（1）减少pthread_cond_signal和sem_post的调用，只在有必要的时候调用； <br>（2）尽量避免pthread_mutex进入竞争态。增大消息队列的大小，可以有效减少竞态条件的出现。</p>
<p>下面给出一个实用的线程消息队列的实现类，这个类也将是以后《网络模型》文章中用到的线程消息队列类，代码注释请看对私有属性的注释：</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;CThreadQueue<br><img id=Codehighlighter1_19_1863_Open_Image onclick="this.style.display='none'; Codehighlighter1_19_1863_Open_Text.style.display='none'; Codehighlighter1_19_1863_Closed_Image.style.display='inline'; Codehighlighter1_19_1863_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_19_1863_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_19_1863_Closed_Text.style.display='none'; Codehighlighter1_19_1863_Open_Image.style.display='inline'; Codehighlighter1_19_1863_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_19_1863_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_19_1863_Open_Text><span style="COLOR: #000000">{<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;CThreadQueue(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;queueSize</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">1024</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;sizeQueue(queueSize),lput(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">),lget(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">),nFullThread(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">),nEmptyThread(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">),nData(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_157_317_Open_Image onclick="this.style.display='none'; Codehighlighter1_157_317_Open_Text.style.display='none'; Codehighlighter1_157_317_Closed_Image.style.display='inline'; Codehighlighter1_157_317_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_157_317_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_157_317_Closed_Text.style.display='none'; Codehighlighter1_157_317_Open_Image.style.display='inline'; Codehighlighter1_157_317_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_157_317_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_157_317_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;pthread_mutex_init(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux,</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;pthread_cond_init(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">condGet,</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;pthread_cond_init(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">condPut,</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;buffer</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)[sizeQueue];<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/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">CThreadQueue()<br><img id=Codehighlighter1_351_382_Open_Image onclick="this.style.display='none'; Codehighlighter1_351_382_Open_Text.style.display='none'; Codehighlighter1_351_382_Closed_Image.style.display='inline'; Codehighlighter1_351_382_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_351_382_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_351_382_Closed_Text.style.display='none'; Codehighlighter1_351_382_Open_Image.style.display='inline'; Codehighlighter1_351_382_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_351_382_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_351_382_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;delete[]&nbsp;buffer;<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/InBlock.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">&nbsp;getq()<br><img id=Codehighlighter1_406_1015_Open_Image onclick="this.style.display='none'; Codehighlighter1_406_1015_Open_Text.style.display='none'; Codehighlighter1_406_1015_Closed_Image.style.display='inline'; Codehighlighter1_406_1015_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_406_1015_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_406_1015_Closed_Text.style.display='none'; Codehighlighter1_406_1015_Open_Image.style.display='inline'; Codehighlighter1_406_1015_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_406_1015_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_406_1015_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: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">data;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pthread_mutex_lock(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);<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">while</span><span style="COLOR: #000000">(lget</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">lput</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">nData</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">此处循环判断的原因如下：假设2个线程在getq阻塞，然后两者都被激活，而其中一个线程运行比较块，快速消耗了2个数据，另一个线程醒来的时候已经没有新数据可以消耗了。另一点，man pthread_cond_wait可以看到，该函数可以被信号中断返回，此时返回EINTR。为避免以上任何一点，都必须醒来后再次判断睡眠条件。</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_590_707_Open_Image onclick="this.style.display='none'; Codehighlighter1_590_707_Open_Text.style.display='none'; Codehighlighter1_590_707_Closed_Image.style.display='inline'; Codehighlighter1_590_707_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_590_707_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_590_707_Closed_Text.style.display='none'; Codehighlighter1_590_707_Open_Image.style.display='inline'; Codehighlighter1_590_707_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_590_707_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_590_707_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;nEmptyThread</span><span style="COLOR: #000000">++</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;pthread_cond_wait(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">condGet,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);<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;nEmptyThread</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<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;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">buffer[lget</span><span style="COLOR: #000000">++</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;nData</span><span style="COLOR: #000000">--</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">if</span><span style="COLOR: #000000">(lget</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">sizeQueue)<br><img id=Codehighlighter1_804_834_Open_Image onclick="this.style.display='none'; Codehighlighter1_804_834_Open_Text.style.display='none'; Codehighlighter1_804_834_Closed_Image.style.display='inline'; Codehighlighter1_804_834_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_804_834_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_804_834_Closed_Text.style.display='none'; Codehighlighter1_804_834_Open_Image.style.display='inline'; Codehighlighter1_804_834_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_804_834_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_804_834_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;lget</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</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">if</span><span style="COLOR: #000000">(nFullThread)&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">必要时才进行signal操作，勿总是signal</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_895_952_Open_Image onclick="this.style.display='none'; Codehighlighter1_895_952_Open_Text.style.display='none'; Codehighlighter1_895_952_Closed_Image.style.display='inline'; Codehighlighter1_895_952_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_895_952_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_895_952_Closed_Text.style.display='none'; Codehighlighter1_895_952_Open_Image.style.display='inline'; Codehighlighter1_895_952_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_895_952_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_895_952_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;pthread_cond_signal(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">condPut);&nbsp;&nbsp;&nbsp;&nbsp;<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;pthread_mutex_unlock(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);<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">return</span><span style="COLOR: #000000">&nbsp;data;<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/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;putq(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">data)<br><img id=Codehighlighter1_1047_1479_Open_Image onclick="this.style.display='none'; Codehighlighter1_1047_1479_Open_Text.style.display='none'; Codehighlighter1_1047_1479_Closed_Image.style.display='inline'; Codehighlighter1_1047_1479_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1047_1479_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1047_1479_Closed_Text.style.display='none'; Codehighlighter1_1047_1479_Open_Image.style.display='inline'; Codehighlighter1_1047_1479_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1047_1479_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_1047_1479_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;pthread_mutex_lock(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);<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">while</span><span style="COLOR: #000000">(lput</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">lget</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">nData)<br><img id=Codehighlighter1_1124_1235_Open_Image onclick="this.style.display='none'; Codehighlighter1_1124_1235_Open_Text.style.display='none'; Codehighlighter1_1124_1235_Closed_Image.style.display='inline'; Codehighlighter1_1124_1235_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1124_1235_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1124_1235_Closed_Text.style.display='none'; Codehighlighter1_1124_1235_Open_Image.style.display='inline'; Codehighlighter1_1124_1235_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_1124_1235_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_1124_1235_Open_Text><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;&nbsp;&nbsp;&nbsp;&nbsp;nFullThread</span><span style="COLOR: #000000">++</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;pthread_cond_wait(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">condPut,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mux);<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;nFullThread</span><span style="COLOR: #000000">--</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;buffer[lput</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">data;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nData</span><span style="COLOR: #000000">++</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">if</span><span style="COLOR: #000000">(lput</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">sizeQueue)<br><img id=Codehighlighter1_1319_1349_Open_Image onclick="this.style.display='none'; Codehighlighter1_1319_1349_Open_Text.style.display='none'; Codehighlighter1_1319_1349_Closed_Image.style.display='inline'; Codehighlighter1_1319_1349_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1319_1349_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1319_1349_Closed_Text.style.display='none'; Codehighlighter1_1319_1349_Open_Image.style.display='inline'; Codehighlighter1_1319_1349_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_1319_1349_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_1319_1349_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;lput</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</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">if</span><span style="COLOR: #000000">(nEmptyThread)<br><img id=Codehighlighter1_1384_1437_Open_Image onclick="this.style.display='none'; Codehighlighter1_1384_1437_Open_Text.style.display='none'; Codehighlighter1_1384_1437_Closed_Image.style.display='inline'; Codehighlighter1_1384_1437_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1384_1437_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1384_1437_Closed_Text.style.display='none'; Codehighlighter1_1384_1437_Open_Image.style.display='inline'; Codehighlighter1_1384_1437_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_1384_1437_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_1384_1437_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;pthread_cond_signal(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">condGet);<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><