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

<channel>
	<title>Soft Binary</title>
	<atom:link href="http://www.soft-bin.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.soft-bin.com</link>
	<description>http://www.soft-bin.com</description>
	<lastBuildDate>Sun, 08 Jan 2012 14:49:36 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>map hash_map unordered_map 性能测试</title>
		<link>http://www.soft-bin.com/html/2012/01/08/map-hash_map-unordered_map-performance-test.html</link>
		<comments>http://www.soft-bin.com/html/2012/01/08/map-hash_map-unordered_map-performance-test.html#comments</comments>
		<pubDate>Sun, 08 Jan 2012 14:49:35 +0000</pubDate>
		<dc:creator>zieckey</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[hash_map]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[STL]]></category>
		<category><![CDATA[unordered_map]]></category>
		<category><![CDATA[关联容器]]></category>
		<category><![CDATA[性能比较]]></category>
		<category><![CDATA[用法示例]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=454</guid>
		<description><![CDATA[1. std::tr1::unordered_map 与 std::ext/hash_map 
     任何情况下，如果要在这两个容器之间选择的话，我们毫不犹豫应该选择 unordered_map。因为他的性能在上述4中操作中均优于 hash_map，甚至可以说远远优于 hash_map。

2. std::tr1::unordered_map 与 std::map 
     map的性能总体来说是最差的。但是，当我们需要一个有序的关联容器的时候，我们必须选择std::map，因为 unordered_map 内部元素不是有序的，这一点从名字都可以看出来。除此之外都应该选择 unordered_map 。]]></description>
			<content:encoded><![CDATA[<p><font face="Tahoma" size="3"><span class="Apple-style-span" style="line-height: normal">by zieckey<br /></span></font>
<div><span style="border-collapse: separate;font-family: Tahoma;line-height: normal;font-size: medium"><br /></span></div>
<div><span style="border-collapse: separate;font-family: Tahoma;line-height: normal;font-size: medium"><span style="border-collapse: separate">测试条件：</span></span></div>
<div>gcc version 4.2.1 20070719&nbsp; [FreeBSD]</div>
<div>FreeBSD &nbsp;7.2-RELEASE #0: Fri May&nbsp; 1 07:18:07 UTC 2009&nbsp;&nbsp;&nbsp;&nbsp; root@driscoll.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC&nbsp; amd64<br />
Intel(R) Xeon(R) CPU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; E5620&nbsp; @ 2.40GHz 16核</div>
<div></div>
<div>测试程序说明：</div>
<div>先准备好n个字符串随机的MD5字符串做为key，然后分别对3个容器进行插入、遍历、查找、删除操作。</div>
<div>例如，n=100的时候，插入是指插入100个随机MD5 key；遍历是指对容器遍历一次；查找是指分别对这个100个随机的MD5 key做查找操作（即查找100次）；删除是指挨个删除这个100个随机MD5 key。</div>
<div></div>
<div>测试数据如下表：</div>
<div>
<div>
<div>
<table border="1" cellpadding="2" cellspacing="0" width="100%">
<tbody>
<tr>
<td valign="top">插入，单位us</td>
<td valign="top">100</td>
<td valign="top">1K</td>
<td valign="top">10K</td>
<td valign="top">100K</td>
<td valign="top">1M</td>
<td valign="top">10M</td>
</tr>
<tr>
<td valign="top">std::map</td>
<td valign="top">241</td>
<td valign="top">2833</td>
<td valign="top">35888</td>
<td valign="top">381214</td>
<td valign="top">4439088</td>
<td valign="top">62233380</td>
</tr>
<tr>
<td valign="top">std::ext/hash_map</td>
<td valign="top">97</td>
<td valign="top">1667</td>
<td valign="top">16466</td>
<td valign="top">146025</td>
<td valign="top">1788446</td>
<td valign="top">18512639</td>
</tr>
<tr>
<td valign="top">std::tr1::unordered_map</td>
<td valign="top">77</td>
<td valign="top">772</td>
<td valign="top">8052</td>
<td valign="top">53094</td>
<td valign="top">658312</td>
<td valign="top">7429297</td>
</tr>
</tbody>
</table>
<div></div>
</div>
</div>
<div>
<table border="1" cellpadding="2" cellspacing="0" width="100%">
<tbody>
<tr>
<td valign="top">遍历，单位us</td>
<td valign="top">100</td>
<td valign="top">1K</td>
<td valign="top">10K</td>
<td valign="top">100K</td>
<td valign="top">1M</td>
<td valign="top">10M</td>
</tr>
<tr>
<td valign="top">std::map</td>
<td valign="top">11</td>
<td valign="top">76</td>
<td valign="top">842</td>
<td valign="top">11603</td>
<td valign="top">155700</td>
<td valign="top">1771906</td>
</tr>
<tr>
<td valign="top">std::ext/hash_map</td>
<td valign="top">47</td>
<td valign="top">430</td>
<td valign="top">4218</td>
<td valign="top">39880</td>
<td valign="top">470344</td>
<td valign="top">4781575</td>
</tr>
<tr>
<td valign="top">std::tr1::unordered_map</td>
<td valign="top">1</td>
<td valign="top">1</td>
<td valign="top">2</td>
<td valign="top">1</td>
<td valign="top">2</td>
<td valign="top">1</td>
</tr>
</tbody>
</table>
<p></div>
<div>
<table border="1" cellpadding="2" cellspacing="0" width="100%">
<tbody>
<tr>
<td valign="top">查找，单位us</td>
<td valign="top">100</td>
<td valign="top">1K</td>
<td valign="top">10K</td>
<td valign="top">100K</td>
<td valign="top">1M</td>
<td valign="top">10M</td>
</tr>
<tr>
<td valign="top">std::map</td>
<td valign="top">156</td>
<td valign="top">2111</td>
<td valign="top">30456</td>
<td valign="top">258709</td>
<td valign="top">4100260</td>
<td valign="top">59064394</td>
</tr>
<tr>
<td valign="top">std::ext/hash_map</td>
<td valign="top">77</td>
<td valign="top">774</td>
<td valign="top">8056</td>
<td valign="top">56974</td>
<td valign="top">660231</td>
<td valign="top">7705527</td>
</tr>
<tr>
<td valign="top">std::tr1::unordered_map</td>
<td valign="top">77</td>
<td valign="top">772</td>
<td valign="top">8051</td>
<td valign="top">54456</td>
<td valign="top">659537</td>
<td valign="top">7600263</td>
</tr>
</tbody>
</table>
<p></div>
<div>
<table border="1" cellpadding="2" cellspacing="0" width="100%">
<tbody>
<tr>
<td valign="top">删除，单位us</td>
<td valign="top">100</td>
<td valign="top">1K</td>
<td valign="top">10K</td>
<td valign="top">100K</td>
<td valign="top">1M</td>
<td valign="top">10M</td>
</tr>
<tr>
<td valign="top">std::map</td>
<td valign="top"><span style="border-collapse: separate;font-family: Tahoma">291</span></td>
<td valign="top">3641</td>
<td valign="top">49584</td>
<td valign="top">472414</td>
<td valign="top">6675897</td>
<td valign="top">92491113</td>
</tr>
<tr>
<td valign="top">std::ext/hash_map</td>
<td valign="top"><span style="border-collapse: separate;font-family: Tahoma">89</span></td>
<td valign="top">869</td>
<td valign="top">9068</td>
<td valign="top">86524</td>
<td valign="top">964767</td>
<td valign="top">10372650</td>
</tr>
<tr>
<td valign="top">std::tr1::unordered_map</td>
<td valign="top"><span style="border-collapse: separate;font-family: Tahoma">49</span></td>
<td valign="top">480</td>
<td valign="top">4879</td>
<td valign="top">33087</td>
<td valign="top">395098</td>
<td valign="top">4369617</td>
</tr>
</tbody>
</table>
<p></div>
<div>结论：</div>
<div><span style="border-collapse: separate;font-family: Tahoma;line-height: normal;font-size: medium">1. std::tr1::unordered_map 与&nbsp;</span>std::ext/hash_map&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp;任何情况下，如果要在这两个容器之间选择的话，<b>我们毫不犹豫应该选择 unordered_map</b>。因为他的性能在上述4中操作中均优于 hash_map，甚至可以说远远优于 hash_map。</div>
<div></div>
<div>2.&nbsp;<span style="border-collapse: separate;font-family: Tahoma;line-height: normal;font-size: medium">std::tr1::unordered_map 与&nbsp;</span>std::map&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp;map的性能总体来说是最差的。但是，<b>当我们需要一个有序的关联容器的时候，我们必须选择std::map</b>，因为&nbsp;unordered_map&nbsp;内部元素不是有序的，这一点从名字都可以看出来。除此之外都应该选择&nbsp;unordered_map&nbsp;。</div>
<div></div>
<div>3. 上述测试中，unordered_map&nbsp;的遍历性能几乎是常数级别的，与常识不太相符，需要再研究研究。</div>
</div>
<div></div>
<div>附录：贴上源代码</div>
<div>说明：与测试程序稍有区别，这里的源码里没有MD5相关的代码以确保其他人能比较方便的直接拿去编译运行。</div>
<div></div>
<div>如有错误还请跟帖指出，非常感谢。</div>
<div></div>
<div></div>
<div>
<div class="codeText">
<ol start="1" class="dp-css">
<li>#include <span style="color:#0000CC">&lt;</span>iostream<span style="color:#0000CC">&gt;</span></li>
<li>
#include <span style="color:#0000CC">&lt;</span><span style="color:#FF0000">string</span><span style="color:#0000CC">&gt;</span></li>
<li>
#include <span style="color:#0000CC">&lt;</span>sstream<span style="color:#0000CC">&gt;</span></li>
<li>
#include <span style="color:#0000CC">&lt;</span>list<span style="color:#0000CC">&gt;</span></li>
<li>
#include <span style="color:#0000CC">&lt;</span>map<span style="color:#0000CC">&gt;</span></li>
<li>
#include <span style="color:#0000CC">&lt;</span>sys<span style="color:#0000CC">/</span><span style="color:#FF0000">time</span><span style="color:#0000CC">.</span>h<span style="color:#0000CC">&gt;</span></li>
<li>
#include <span style="color:#0000CC">&lt;</span>ext<span style="color:#0000CC">/</span>hash_map<span style="color:#0000CC">&gt;</span></li>
<li>
#include <span style="color:#0000CC">&lt;</span>tr1<span style="color:#0000CC">/</span>unordered_map<span style="color:#0000CC">&gt;</span></li>
<li>
</li>
<li>
namespace zl</li>
<li>
<span style="color:#0000CC">{</span> <span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;struct equal_to</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool operator<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">(</span><span style="color:#0000FF">const</span> char<span style="color:#0000CC">*</span> s1<span style="color:#0000CC">,</span> <span style="color:#0000FF">const</span> char<span style="color:#0000CC">*</span> s2<span style="color:#0000CC">)</span> <span style="color:#0000FF">const</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return strcmp<span style="color:#0000CC">(</span>s1<span style="color:#0000CC">,</span> s2<span style="color:#0000CC">)</span> <span style="color:#0000CC">=</span><span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;struct hash_string</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">:</span> <span style="color:#0000FF">public</span> std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>unary_function<span style="color:#0000CC">&lt;</span>std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span><span style="color:#FF0000">string</span><span style="color:#0000CC">,</span> std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>size_t<span style="color:#0000CC">&gt;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>size_t</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;operator<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">(</span><span style="color:#0000FF">const</span> std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span><span style="color:#FF0000">string</span><span style="color:#0000CC">&amp;</span> __s<span style="color:#0000CC">)</span> <span style="color:#0000FF">const</span></li>
<li>
#ifdef __linux__</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span> return std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>tr1<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>Fnv_hash<span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&gt;</span><span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>hash<span style="color:#0000CC">(</span>__s<span style="color:#0000CC">.</span>data<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">,</span> __s<span style="color:#0000CC">.</span>length<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span> <span style="color:#0000CC">}</span></li>
<li>
#<span style="color:#0000FF">else</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span> return std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>tr1<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>_Fnv_hash<span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&gt;</span><span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>hash<span style="color:#0000CC">(</span>__s<span style="color:#0000CC">.</span>data<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">,</span> __s<span style="color:#0000CC">.</span>length<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span> <span style="color:#0000CC">}</span></li>
<li>
#endif</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;struct hash_charptr</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">:</span> <span style="color:#0000FF">public</span> std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>unary_function<span style="color:#0000CC">&lt;</span><span style="color:#0000FF">const</span> char<span style="color:#0000CC">*</span><span style="color:#0000CC">,</span> std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>size_t<span style="color:#0000CC">&gt;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>size_t</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;operator<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">(</span><span style="color:#0000FF">const</span> char<span style="color:#0000CC">*</span> __s<span style="color:#0000CC">)</span> <span style="color:#0000FF">const</span></li>
<li>
#ifdef __linux__</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span> return std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>tr1<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>Fnv_hash<span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&gt;</span><span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>hash<span style="color:#0000CC">(</span>__s<span style="color:#0000CC">,</span> strlen<span style="color:#0000CC">(</span>__s<span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span> <span style="color:#0000CC">}</span></li>
<li>
#<span style="color:#0000FF">else</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span> return std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>tr1<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>_Fnv_hash<span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&gt;</span><span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>hash<span style="color:#0000CC">(</span>__s<span style="color:#0000CC">,</span> strlen<span style="color:#0000CC">(</span>__s<span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span> <span style="color:#0000CC">}</span></li>
<li>
#endif</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span><span style="color:#0000CC">;</span></li>
<li>
<span style="color:#0000CC">}</span><span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
typedef std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>list<span style="color:#0000CC">&lt;</span>std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span><span style="color:#FF0000">string</span><span style="color:#0000CC">&gt;</span> string_list<span style="color:#0000CC">;</span></li>
<li>
typedef std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>map<span style="color:#0000CC">&lt;</span>std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span><span style="color:#FF0000">string</span><span style="color:#0000CC">,</span> <span style="color:#FF0000">int</span><span style="color:#0000CC">&gt;</span> string_map<span style="color:#0000CC">;</span></li>
<li>
typedef __gnu_cxx<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>hash_map<span style="color:#0000CC">&lt;</span>std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span><span style="color:#FF0000">string</span><span style="color:#0000CC">,</span> <span style="color:#FF0000">int</span><span style="color:#0000CC">,</span> zl<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>hash_string<span style="color:#0000CC">&gt;</span> string_hash_map<span style="color:#0000CC">;</span></li>
<li>
typedef std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>tr1<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>unordered_map<span style="color:#0000CC">&lt;</span>std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span><span style="color:#FF0000">string</span><span style="color:#0000CC">,</span> <span style="color:#FF0000">int</span><span style="color:#0000CC">&gt;</span> string_unordered_map<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
void fill_list<span style="color:#0000CC">(</span>string_list<span style="color:#0000CC">&amp;</span> slist<span style="color:#0000CC">,</span> size_t count<span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
uint64_t current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
<span style="color:#FF0000">int</span> main<span style="color:#0000CC">(</span> <span style="color:#FF0000">int</span> argc<span style="color:#0000CC">,</span> char<span style="color:#0000CC">*</span> argv<span style="color:#0000CC">[</span><span style="color:#0000CC">]</span> <span style="color:#0000CC">)</span></li>
<li>
<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">if</span> <span style="color:#0000CC">(</span>argc <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> 2 <span style="color:#0000CC">&amp;</span><span style="color:#0000CC">&amp;</span> argc <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> 3<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf<span style="color:#0000CC">(</span>stderr<span style="color:#0000CC">,</span> <span style="color:#FF00FF">&#8220;Usage:%s test_count rehash\n&#8221;</span><span style="color:#0000CC">,</span> argv<span style="color:#0000CC">[</span>0<span style="color:#0000CC">]</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf<span style="color:#0000CC">(</span>stderr<span style="color:#0000CC">,</span> <span style="color:#FF00FF">&#8220;For example:%s 10000 rehash\n&#8221;</span><span style="color:#0000CC">,</span> argv<span style="color:#0000CC">[</span>0<span style="color:#0000CC">]</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return <span style="color:#0000CC">-</span>1<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;size_t count <span style="color:#0000CC">=</span> atoi<span style="color:#0000CC">(</span>argv<span style="color:#0000CC">[</span>1<span style="color:#0000CC">]</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;bool rehash <span style="color:#0000CC">=</span> <span style="color:#0000FF">false</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">if</span> <span style="color:#0000CC">(</span>argc <span style="color:#0000CC">=</span><span style="color:#0000CC">=</span> 3<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rehash <span style="color:#0000CC">=</span> <span style="color:#0000FF">true</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;string_map smap<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;string_hash_map shash_map<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;string_unordered_map sunordered_map<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">if</span> <span style="color:#0000CC">(</span>rehash<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sunordered_map<span style="color:#0000CC">.</span>rehash<span style="color:#0000CC">(</span>count<span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;string_list slist<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;fill_list<span style="color:#0000CC">(</span>slist<span style="color:#0000CC">,</span> count<span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t start <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t <span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t map_insert_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t hash_map_insert_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t unordered_map_insert_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t map_traverse_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t hash_map_traverse_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t unordered_map_traverse_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t map_find_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t hash_map_find_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t unordered_map_find_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t map_delete_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t hash_map_delete_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;uint64_t unordered_map_delete_us <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span> Insert test</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span><span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_list<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator it<span style="color:#0000CC">(</span>slist<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_list<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator ite<span style="color:#0000CC">(</span>slist<span style="color:#0000CC">.</span><span style="color:#0000FF">end</span><span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>map insert</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">,</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;smap<span style="color:#0000CC">[</span><span style="color:#0000CC">*</span>it<span style="color:#0000CC">]</span> <span style="color:#0000CC">=</span> i<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map_insert_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>hash_map insert</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it <span style="color:#0000CC">=</span> slist<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">,</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shash_map<span style="color:#0000CC">[</span><span style="color:#0000CC">*</span>it<span style="color:#0000CC">]</span> <span style="color:#0000CC">=</span> i<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash_map_insert_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>unordered_map insert</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it <span style="color:#0000CC">=</span> slist<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">,</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shash_map<span style="color:#0000CC">[</span><span style="color:#0000CC">*</span>it<span style="color:#0000CC">]</span> <span style="color:#0000CC">=</span> i<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unordered_map_insert_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span><span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span> Traverse test</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span><span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>map traverse </li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_map<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator it<span style="color:#0000CC">(</span>smap<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_map<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator ite<span style="color:#0000CC">(</span>smap<span style="color:#0000CC">.</span><span style="color:#0000FF">end</span><span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i<span style="color:#0000CC">+</span><span style="color:#0000CC">+</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map_traverse_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>hash_map traverse </li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_hash_map<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator it<span style="color:#0000CC">(</span>shash_map<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_hash_map<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator ite<span style="color:#0000CC">(</span>shash_map<span style="color:#0000CC">.</span><span style="color:#0000FF">end</span><span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i<span style="color:#0000CC">+</span><span style="color:#0000CC">+</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash_map_traverse_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>unordered_map traverse </li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_unordered_map<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator it<span style="color:#0000CC">(</span>sunordered_map<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_unordered_map<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator ite<span style="color:#0000CC">(</span>sunordered_map<span style="color:#0000CC">.</span><span style="color:#0000FF">end</span><span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i<span style="color:#0000CC">+</span><span style="color:#0000CC">+</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unordered_map_traverse_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span><span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span> Find test</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span><span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_list<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator it<span style="color:#0000CC">(</span>slist<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_list<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator ite<span style="color:#0000CC">(</span>slist<span style="color:#0000CC">.</span><span style="color:#0000FF">end</span><span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>map find</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">,</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;smap<span style="color:#0000CC">[</span><span style="color:#0000CC">*</span>it<span style="color:#0000CC">]</span> <span style="color:#0000CC">=</span> i<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map_find_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>hash_map find</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it <span style="color:#0000CC">=</span> slist<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">,</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shash_map<span style="color:#0000CC">[</span><span style="color:#0000CC">*</span>it<span style="color:#0000CC">]</span> <span style="color:#0000CC">=</span> i<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash_map_find_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>unordered_map find</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it <span style="color:#0000CC">=</span> slist<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">,</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shash_map<span style="color:#0000CC">[</span><span style="color:#0000CC">*</span>it<span style="color:#0000CC">]</span> <span style="color:#0000CC">=</span> i<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unordered_map_find_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span><span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span> Delete test</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span><span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span><span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_list<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator it<span style="color:#0000CC">(</span>slist<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string_list<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>iterator ite<span style="color:#0000CC">(</span>slist<span style="color:#0000CC">.</span><span style="color:#0000FF">end</span><span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>map delete</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">,</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;smap<span style="color:#0000CC">.</span><span style="color:#0000FF">erase</span><span style="color:#0000CC">(</span><span style="color:#0000CC">*</span>it<span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map_delete_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>hash_map delete</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it <span style="color:#0000CC">=</span> slist<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">,</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shash_map<span style="color:#0000CC">.</span><span style="color:#0000FF">erase</span><span style="color:#0000CC">(</span><span style="color:#0000CC">*</span>it<span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash_map_delete_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>unordered_map delete</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it <span style="color:#0000CC">=</span> slist<span style="color:#0000CC">.</span>begin<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span><span style="color:#FF0000">int</span> i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> it <span style="color:#0000CC">!</span><span style="color:#0000CC">=</span> ite<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>it<span style="color:#0000CC">,</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shash_map<span style="color:#0000CC">.</span><span style="color:#0000FF">erase</span><span style="color:#0000CC">(</span><span style="color:#0000CC">*</span>it<span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">end</span> <span style="color:#0000CC">=</span> current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unordered_map_delete_us <span style="color:#0000CC">=</span> <span style="color:#0000FF">end</span> <span style="color:#0000CC">-</span> start<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span><span style="color:#0000CC">/</span><span style="color:#0000CC">/</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span><span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>stat output</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;          insert, count &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> count <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>endl<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;               std::map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> map_insert_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;      std::ext/hash_map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> hash_map_insert_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8220;std::tr1::unordered_map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> unordered_map_insert_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8220;\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;        traverse, count &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> count <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>endl<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;               std::map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> map_traverse_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;      std::ext/hash_map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> hash_map_traverse_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8220;std::tr1::unordered_map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> unordered_map_traverse_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8220;\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;            find, count &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> count <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>endl<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;               std::map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> map_find_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;      std::ext/hash_map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> hash_map_find_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8220;std::tr1::unordered_map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> unordered_map_find_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8220;\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;          delete, count &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> count <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>endl<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;               std::map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> map_delete_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221;      std::ext/hash_map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> hash_map_delete_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>cout <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8220;std::tr1::unordered_map &#8220;</span> <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> unordered_map_delete_us <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> <span style="color:#FF00FF">&#8221; us\n&#8221;</span><span style="color:#0000CC">;</span></li>
<li>
</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;return 0<span style="color:#0000CC">;</span></li>
<li>
<span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
void fill_list<span style="color:#0000CC">(</span>string_list<span style="color:#0000CC">&amp;</span> slist<span style="color:#0000CC">,</span> size_t count<span style="color:#0000CC">)</span></li>
<li>
<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000FF">for</span> <span style="color:#0000CC">(</span>size_t i <span style="color:#0000CC">=</span> 0<span style="color:#0000CC">;</span> i <span style="color:#0000CC">&lt;</span> count<span style="color:#0000CC">;</span> <span style="color:#0000CC">+</span><span style="color:#0000CC">+</span>i<span style="color:#0000CC">)</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>ostringstream oss<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oss <span style="color:#0000CC">&lt;</span><span style="color:#0000CC">&lt;</span> i<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">/</span><span style="color:#0000CC">/</span>slist<span style="color:#0000CC">.</span>push_back<span style="color:#0000CC">(</span>MD5<span style="color:#0000CC">:</span><span style="color:#0000CC">:</span>getHexMD5<span style="color:#0000CC">(</span>oss<span style="color:#0000CC">.</span>str<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">.</span>c_str<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">,</span> oss<span style="color:#0000CC">.</span>str<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">.</span>length<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slist<span style="color:#0000CC">.</span>push_back<span style="color:#0000CC">(</span>oss<span style="color:#0000CC">.</span>str<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span><span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000CC">}</span></li>
<li>
<span style="color:#0000CC">}</span></li>
<li>
</li>
<li>
</li>
<li>
uint64_t current_usec<span style="color:#0000CC">(</span><span style="color:#0000CC">)</span></li>
<li>
<span style="color:#0000CC">{</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;struct timeval tv<span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;gettimeofday<span style="color:#0000CC">(</span> <span style="color:#0000CC">&amp;</span>tv<span style="color:#0000CC">,</span> <span style="color:#0000FF">NULL</span> <span style="color:#0000CC">)</span><span style="color:#0000CC">;</span></li>
<li>
&nbsp;&nbsp;&nbsp;&nbsp;return tv<span style="color:#0000CC">.</span>tv_sec <span style="color:#0000CC">*</span> 1000 <span style="color:#0000CC">*</span> 1000 <span style="color:#0000CC">+</span> tv<span style="color:#0000CC">.</span>tv_usec<span style="color:#0000CC">;</span></li>
<li>
<span style="color:#0000CC">}</span></li>
</ol>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2012/01/08/map-hash_map-unordered_map-performance-test.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UI技术简介</title>
		<link>http://www.soft-bin.com/html/2011/10/20/ui_tech_intro.html</link>
		<comments>http://www.soft-bin.com/html/2011/10/20/ui_tech_intro.html#comments</comments>
		<pubDate>Thu, 20 Oct 2011 10:24:13 +0000</pubDate>
		<dc:creator>luckzj</dc:creator>
				<category><![CDATA[未分类]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=450</guid>
		<description><![CDATA[1. 本文简介
        开发一款桌面应用软件，界面设计往往需要占据较大部分的工作量。界面设计的好坏，直接决定了软件的客户体验。然而界面设计是一门专业的技术，需要对Windows界面绘制技术有较深的理解，才可以制作出美观大方的界面效果。
       本文主要介绍当前主流的界面设计技术DirectUI，将DirectUI技术与传统的界面设计技术进行比较，最后介绍当前DirectUI技术在国内的发展现状。
2. 传统的UI设计模式
2.1 Windows窗体
        Windows界面程序中，最重要的概念是窗体的概念。窗体是Windows程序中，消息派发的单位，每个窗体都有自己的窗口过程，用于处理Windows派发来的消息，这些消息中，比较容易让人理解的，即是WM_ERASEBKGND消息和WM_PAINT消息。
        当窗体需要重新绘制背景时，系统就会向窗体发送WM_ERASEBKGND消息，窗体接收到这个消息以后，将会调用OnEraseBkgnd函数，刷新窗体的背景。
       当窗体需要被重新绘制时，系统会向窗体发送WM_PAINT消息，则窗体的OnPaint函数将会被调用，以达到重新绘制整个窗体的作用。
        我们不需要纠结于绘制背景和绘制窗体的区别，只需要知道窗体大概就是这样展现出来的即可，而两个消息的响应函数，也并非一定是OnEraseBkgnd和OnPaint，我们可以根据需要自行决定函数名称。
       我们将某个窗体从后台移动到前台时，则该窗体将会依次收到WM_ERASEBKGND和WM_PAINT消息。
2.2 使用Windows API来制作界面
如果纯粹使用Windows API来开发程序界面，则我们需要做的工作大致如下：
1. 设置一个WNDCLASSEX结构，使用这个结构来注册一个新的窗体类别。
2. 创建刚注册的窗口类别的一个窗体实例。
3. 编写一个窗体过程函数，响应第2步中创建的窗体的各种消息。对于不需要特殊处理的消息，则直接调用DefWindowProc处理。
后续的界面处理，有两种选择，一种是再创建子窗体，放在主窗体上，而后子窗体可以有自己的窗体过程函数，以此实现将界面划分不同模块，分开处理。另外一种选择则是将主窗体划分为不同的区域，在OnPaint函数中，根据不同的区域，调用不同的绘制模块，来实现复杂的界面处理。前者可以认为是MFC的雏形，而后者则是DirectUI的思想。
2.3 MFC框架
      MFC是微软提供的一套界面开发工具库，其全称是Microsoft Foundation Classes。早期的界面开发很多是基于MFC框架。
      MFC将对窗体操作的一系列Windows API函数封装成一个CWnd类。封装窗口过程处理函数，提供消息映射机制。即不再需要编写窗口过程，而是直接使用消息映射宏ON_MESSAGE(msg, handler)来映射msg与handler。
      框架提供从CWnd类派生的诸多其他控件类，例如CButton, CStatic, CListCtrl, CCombox, CProgressCtrl等等。每一个界面控件的实例，都包含一个窗体，可以响应发送给该窗体的消息，多个界面控件，以父子控件的层级关系，搭建在一起，就组成了复杂的界面。
MFC框架中提供的基础控件，往往难以满足复杂界面的需求，通常情况下，软件公司会对MFC库进行扩展，并建造自己的界面控件库，以满足不同的需求。

3. DirectUI技术
       MFC的框架经过多年的发展，已经比较完善，但仍然难以使用MFC开发出复杂炫丽的客户界面。很多情况下，界面开发人员都需要根据自己的界面需求，定制开发新的MFC控件，使得界面开发仍然苦难。此外，在MFC框架中，每一个控件都是一个窗体，系统对于窗体的维护需要付出较大的代价，使得程序运行效率低下。
      在这种情况下，出现了DirectUI的思想。
2.1 DirectUI简介
      DirectUI技术的精髓在于整个程序只有一个窗体，在主窗体上绘制出不同的控件。DirectUI中也有界面控件的概念，但此处的控件，仅仅保存控件区域，并负责对此区域进行自定义的绘制。
      采用DirectUI设计界面和MFC设计界面的一大不同之处在于，在MFC中，界面的设计需要通过使用MFC的资源编辑器或者手工编写代码实现。而在DirectUI技术中，界面的设计则是采用xml配置文件的形式。界面xml的配置类似于使用html编写网页。
2.2 DirectUI的实现
DirectUI的实现有多种方式，但基本上大体分为以下几个部分：
1. DirectUI框架：封装窗体功能，消息分发功能，控件基类，皮肤基类，皮肤解析等等
2. 工具封装：封装常用工具，例如字符串处理，XML文件处理等
3. 界面解析引擎：用于解析界面xml配置
4. 界面库： 封装常用的界面库，使得DirectUI可以运行起来
      DirectUI框架负责将xml界面配置转换成用户界面，并提供一系列常用界面控件。DirectUI库的使用者，可以使用xml快速配置界面，并通过响应界面控件向外发出的消息，来实现自身的业务逻辑。
      不同的公司对DirectUI的实现略有不同，但总体思路大体相当。国内有一些公司，在DirectUI的基础上进行了扩展，使得其功能更加强大。
3. 国内DirectUI的发展
3.1 UIPower公司
      提到国内DirectUI技术的发展，就不能不说UIPower公司，其中文名位上海勇进公司。UIPower公司是目前国内最大的DirectUI技术提供厂商之一，发展迅速，有比较多的成功案例。
      UIPower对DirectUI技术进行了扩展，这些扩展主要包括以下几个方面：
1. 在DirectUI的核心基础上，封装一层COM，使得其核心控件能够被多种语言访问到。其中最突出的是使用javascript语言访问DirectUI核心控件的接口，使得UIPower公司提供的DirectUI库可以支持使用javascript对界面进行控制。
2. 提供强大的界面设计工具，利用所见即所得的模式，设计用户界面，并自动生成界面xml文档。设计工具中，还提供使用javascript脚本对界面效果进行控制。
3.2 DUILib
DUILib是国内的开业DirectUI项目。DUILib项目基于几千年一个老外写的DirectUI论文中的一个例子。DUILib的发起者基于该例子，创建了完整的DirectUI库，并与2010年发布了第一版开源软件。
DUILib支持DirectUI的所有特性，也提供界面设计器，但由于开发人手不足，界面设计器功能简单，且不完善。目前，该项目仍在继续发展当中。
3.3 bkwin
Bkwin是金山软件公司的界面库，随着金山公司将金山卫士项目源码公开，并建立金山开源社区，bkwin作为金山公司界面库也被开放出来。
Bkwin基于wtl编写，源码小巧，功能强大，支持皮肤设置，语言设置等。实现了DirectUI技术的全部功能。Bkwin不提供界面设计器，只支持纯手工编写界面配置文件。开发者在配置了界面描述、皮肤描述、风格描述以及语言描述四个xml文件后，即可生成用户界面。
Bkwin界面库已经成功应用在金山卫士软件上，且其背后有金山软件公司的支持，因此相对于DUILib更加稳定可靠。
]]></description>
			<content:encoded><![CDATA[<p><strong>1. 本文简介<br />
</strong>        开发一款桌面应用软件，界面设计往往需要占据较大部分的工作量。界面设计的好坏，直接决定了软件的客户体验。然而界面设计是一门专业的技术，需要对Windows界面绘制技术有较深的理解，才可以制作出美观大方的界面效果。<br />
       本文主要介绍当前主流的界面设计技术DirectUI，将DirectUI技术与传统的界面设计技术进行比较，最后介绍当前DirectUI技术在国内的发展现状。</p>
<p><strong>2. 传统的UI设计模式<br />
</strong>2.1 Windows窗体<br />
        Windows界面程序中，最重要的概念是窗体的概念。窗体是Windows程序中，消息派发的单位，每个窗体都有自己的窗口过程，用于处理Windows派发来的消息，这些消息中，比较容易让人理解的，即是WM_ERASEBKGND消息和WM_PAINT消息。<br />
        当窗体需要重新绘制背景时，系统就会向窗体发送WM_ERASEBKGND消息，窗体接收到这个消息以后，将会调用OnEraseBkgnd函数，刷新窗体的背景。<br />
       当窗体需要被重新绘制时，系统会向窗体发送WM_PAINT消息，则窗体的OnPaint函数将会被调用，以达到重新绘制整个窗体的作用。<br />
        我们不需要纠结于绘制背景和绘制窗体的区别，只需要知道窗体大概就是这样展现出来的即可，而两个消息的响应函数，也并非一定是OnEraseBkgnd和OnPaint，我们可以根据需要自行决定函数名称。<br />
       我们将某个窗体从后台移动到前台时，则该窗体将会依次收到WM_ERASEBKGND和WM_PAINT消息。</p>
<p>2.2 使用Windows API来制作界面<br />
如果纯粹使用Windows API来开发程序界面，则我们需要做的工作大致如下：<br />
1. 设置一个WNDCLASSEX结构，使用这个结构来注册一个新的窗体类别。<br />
2. 创建刚注册的窗口类别的一个窗体实例。<br />
3. 编写一个窗体过程函数，响应第2步中创建的窗体的各种消息。对于不需要特殊处理的消息，则直接调用DefWindowProc处理。<br />
后续的界面处理，有两种选择，一种是再创建子窗体，放在主窗体上，而后子窗体可以有自己的窗体过程函数，以此实现将界面划分不同模块，分开处理。另外一种选择则是将主窗体划分为不同的区域，在OnPaint函数中，根据不同的区域，调用不同的绘制模块，来实现复杂的界面处理。前者可以认为是MFC的雏形，而后者则是DirectUI的思想。</p>
<p>2.3 MFC框架<br />
      MFC是微软提供的一套界面开发工具库，其全称是Microsoft Foundation Classes。早期的界面开发很多是基于MFC框架。<br />
      MFC将对窗体操作的一系列Windows API函数封装成一个CWnd类。封装窗口过程处理函数，提供消息映射机制。即不再需要编写窗口过程，而是直接使用消息映射宏ON_MESSAGE(msg, handler)来映射msg与handler。<br />
      框架提供从CWnd类派生的诸多其他控件类，例如CButton, CStatic, CListCtrl, CCombox, CProgressCtrl等等。每一个界面控件的实例，都包含一个窗体，可以响应发送给该窗体的消息，多个界面控件，以父子控件的层级关系，搭建在一起，就组成了复杂的界面。<br />
MFC框架中提供的基础控件，往往难以满足复杂界面的需求，通常情况下，软件公司会对MFC库进行扩展，并建造自己的界面控件库，以满足不同的需求。<br />
<span id="more-450"></span></p>
<p><strong>3. DirectUI技术<br />
</strong>       MFC的框架经过多年的发展，已经比较完善，但仍然难以使用MFC开发出复杂炫丽的客户界面。很多情况下，界面开发人员都需要根据自己的界面需求，定制开发新的MFC控件，使得界面开发仍然苦难。此外，在MFC框架中，每一个控件都是一个窗体，系统对于窗体的维护需要付出较大的代价，使得程序运行效率低下。<br />
      在这种情况下，出现了DirectUI的思想。<br />
2.1 DirectUI简介<br />
      DirectUI技术的精髓在于整个程序只有一个窗体，在主窗体上绘制出不同的控件。DirectUI中也有界面控件的概念，但此处的控件，仅仅保存控件区域，并负责对此区域进行自定义的绘制。<br />
      采用DirectUI设计界面和MFC设计界面的一大不同之处在于，在MFC中，界面的设计需要通过使用MFC的资源编辑器或者手工编写代码实现。而在DirectUI技术中，界面的设计则是采用xml配置文件的形式。界面xml的配置类似于使用html编写网页。</p>
<p>2.2 DirectUI的实现<br />
DirectUI的实现有多种方式，但基本上大体分为以下几个部分：<br />
1. DirectUI框架：封装窗体功能，消息分发功能，控件基类，皮肤基类，皮肤解析等等<br />
2. 工具封装：封装常用工具，例如字符串处理，XML文件处理等<br />
3. 界面解析引擎：用于解析界面xml配置<br />
4. 界面库： 封装常用的界面库，使得DirectUI可以运行起来</p>
<p>      DirectUI框架负责将xml界面配置转换成用户界面，并提供一系列常用界面控件。DirectUI库的使用者，可以使用xml快速配置界面，并通过响应界面控件向外发出的消息，来实现自身的业务逻辑。<br />
      不同的公司对DirectUI的实现略有不同，但总体思路大体相当。国内有一些公司，在DirectUI的基础上进行了扩展，使得其功能更加强大。</p>
<p><strong>3. 国内DirectUI的发展<br />
</strong>3.1 UIPower公司<br />
      提到国内DirectUI技术的发展，就不能不说UIPower公司，其中文名位上海勇进公司。UIPower公司是目前国内最大的DirectUI技术提供厂商之一，发展迅速，有比较多的成功案例。<br />
      UIPower对DirectUI技术进行了扩展，这些扩展主要包括以下几个方面：<br />
1. 在DirectUI的核心基础上，封装一层COM，使得其核心控件能够被多种语言访问到。其中最突出的是使用javascript语言访问DirectUI核心控件的接口，使得UIPower公司提供的DirectUI库可以支持使用javascript对界面进行控制。<br />
2. 提供强大的界面设计工具，利用所见即所得的模式，设计用户界面，并自动生成界面xml文档。设计工具中，还提供使用javascript脚本对界面效果进行控制。</p>
<p>3.2 DUILib<br />
DUILib是国内的开业DirectUI项目。DUILib项目基于几千年一个老外写的DirectUI论文中的一个例子。DUILib的发起者基于该例子，创建了完整的DirectUI库，并与2010年发布了第一版开源软件。<br />
DUILib支持DirectUI的所有特性，也提供界面设计器，但由于开发人手不足，界面设计器功能简单，且不完善。目前，该项目仍在继续发展当中。</p>
<p>3.3 bkwin<br />
Bkwin是金山软件公司的界面库，随着金山公司将金山卫士项目源码公开，并建立金山开源社区，bkwin作为金山公司界面库也被开放出来。<br />
Bkwin基于wtl编写，源码小巧，功能强大，支持皮肤设置，语言设置等。实现了DirectUI技术的全部功能。Bkwin不提供界面设计器，只支持纯手工编写界面配置文件。开发者在配置了界面描述、皮肤描述、风格描述以及语言描述四个xml文件后，即可生成用户界面。<br />
Bkwin界面库已经成功应用在金山卫士软件上，且其背后有金山软件公司的支持，因此相对于DUILib更加稳定可靠。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2011/10/20/ui_tech_intro.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++ STL 学习 ：自己写仿函数(functor)（三）</title>
		<link>http://www.soft-bin.com/html/2011/10/11/c-stl-compose-for_each.html</link>
		<comments>http://www.soft-bin.com/html/2011/10/11/c-stl-compose-for_each.html#comments</comments>
		<pubDate>Tue, 11 Oct 2011 11:10:51 +0000</pubDate>
		<dc:creator>zieckey</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[STL]]></category>
		<category><![CDATA[compose]]></category>
		<category><![CDATA[for_each]]></category>
		<category><![CDATA[functor]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=447</guid>
		<description><![CDATA[本文介绍了for_each的用法，进而更深入的介绍了如何写一个复杂点的组合仿函数:遍历一个map，对每一个key/value对中value调用visitor仿函数。]]></description>
			<content:encoded><![CDATA[<div>
<p>C++ STL 学习 ：自己写仿函数(functor)（三）</p>
<div></div>
<div>我们从最简单的visitor入手，看下面的定义：</div>
<div></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    </span></font><font color="#008000" face="Consolas" size="2"><span style="font-size:10pt">// TEMPLATE STRUCT unary_function</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">   </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">template</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">class</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Arg</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">class</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Result</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">   </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">struct</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">unary_function</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    {     </span></font> <font color="#008000" face="Consolas" size="2"><span style="font-size:10pt">// base class for unary functions</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typedef</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Arg</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">argument_type</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typedef</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Result</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">result_type</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    };</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    </span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">template</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">class</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Ty</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">   </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">struct</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">visitor</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">:</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">public</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">std</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">unary_function</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Ty</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">void</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    {</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">void</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">operator</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">()(</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">const</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Ty</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&amp;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">x</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">)</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        {</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">           </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">std</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">cout</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;&lt;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">x</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;&lt;</span></font> <font color="#A31515" face="Consolas" size="2"><span style="font-size:10pt">&quot;\t&quot;</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        }</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    };</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">这个visitor定义足够简单，我们就不多说了。前文说过for_each的定义，这里再给出来：</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></div>
<div align="left">
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    </span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">template</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">InputIterator</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">Function</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font></span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">   </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">Function</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">for_each</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">InputIterator</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">beg</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">InputIterator</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">end</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">Function</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">f</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">) {</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">while</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">beg</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">!=</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">end</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">)</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">           </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">f</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">( *</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">beg</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">++ );</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    }</span></font></font></div>
</div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">看下面的测试代码:</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></div>
<div align="left">
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    </span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">void</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">test_for_each</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">()</span></font></span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    {   </span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typedef</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">std</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">list</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">int</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">intlist</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">intlist</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">il</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">for</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">int</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">i</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">= 0;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">i</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt; 10;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">i</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">++ )</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        {</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">           </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">il</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">.</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">push_back</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">i</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">);</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        }</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">std</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">for_each</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">il</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">.</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">begin</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(),</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">il</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">.</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">end</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(),</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">visitor</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">int</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;() );</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    }</span></font></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></font></div>
<div align="left"><font color="#010101"><span style="font-size: 13px">这里对一个list进行遍历，对每一个元素调用</span></font><span>visitor仿函数。</span></div>
<div align="left"><span><br /></span></div>
<div align="left"><span><br /></span></div>
<div align="left"><span>下面，我们来实现一个复杂点的任务，遍历一个map，对每一个key/value对中value调用</span><span>visitor仿函数。</span></div>
<div align="left"><span><br /></span></div>
<div align="left"><font color="#010001"><span style="font-size: 13px">首先我们需要一个选择器仿函数</span></font><span>select2nd_t来选择</span><span>key/value对的value：</span></div>
<div align="left"><span><br /></span></div>
<div align="left">
<div align="left"><span><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    </span></font><font color="#008000" face="Consolas" size="2"><span style="font-size:10pt">/**</span></font></span></div>
<div align="left"><font color="#008000" face="Consolas" size="2"><span style="font-size:10pt">     *  select the second parameter from a std::pair</span></font></div>
<div align="left"><font color="#008000" face="Consolas" size="2"><span style="font-size:10pt">     */</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">   </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">template</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">class</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Pair</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">   </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">struct</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">select2nd_t</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        :</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">public</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">std</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">unary_function</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Pair</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Pair</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">second_type</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    {</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">const</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Pair</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">second_type</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&amp;</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">operator</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">()(</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">const</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Pair</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&amp;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_x</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">)</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        {</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">           </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">return</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_x</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">.</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">second</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        }</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    };</span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></div>
<p><span><span><span>在遍历过程中，通过</span></span>select2nd_t把value选出来，然后调用visitor。</span></div>
<div align="left"><font color="#010001"><span style="font-size: 13px">为了实现这个功能，我们需要下面这个组合仿函数：</span></font></div>
<div align="left"><font color="#010001"><span style="font-size: 13px"><br /></span></font></div>
<div align="left">
<div align="left">
<div align="left"><font color="#010101"><span style="font-size: 13px"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    </span></font><font color="#008000" face="Consolas" size="2"><span style="font-size:10pt">/**</span></font></span></font></div>
<div align="left"><font color="#010101"><font color="#008000" face="Consolas" size="2"><span style="font-size:10pt">     *  compose _Func1 and _Func2</span></font></font></div>
<div align="left"><font color="#010101"><font color="#008000" face="Consolas" size="2"><span style="font-size:10pt">     *  use the return value of _Func1 as the parameter of the _Func2 and return the return value of _Func2</span></font></font></div>
<div align="left"><font color="#010101"><font color="#008000" face="Consolas" size="2"><span style="font-size:10pt">     */</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">   </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">template</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">class</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func1</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">class</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func2</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">   </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">struct</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">compose_t</span></font> </font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        :</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">public</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">std</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">unary_function</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func1</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">argument_type</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func2</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">result_type</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    {</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func1</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">__func1</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func2</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">__func2</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">compose_t</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">const</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func1</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&amp;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">f1</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">const</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func2</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&amp;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">f2</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">) :</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">__func1</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">f1</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">),</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">__func2</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">f2</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">) {}</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func2</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">result_type</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">operator</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">()(</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">const</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func1</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">argument_type</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&amp;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_x</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">)</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        {</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">           </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">return</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">__func2</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">__func1</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_x</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">) );</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        }</span></font></font></div>
<div align="left"><font color="#010101"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    };</span></font></font></div>
</div>
<div align="left"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></div>
<p><font color="#010001"><span style="font-size: 13px"><br /></span></font><span><span><span>func1是</span></span>select2nd_t，func2是visitor。</span></div>
<div align="left"><span style="font-size: 13px"><span style="border-collapse: separate;font-family: Consolas;font-variant: normal;letter-spacing: normal;line-height: normal;text-align: -webkit-auto;text-indent: 0px;font-size: medium"><span style="font-size: 13px;text-align: -webkit-left"><b><font face="Consolas" size="2"><span style="font-size: 10pt">__func2</span></font><font face="Consolas" size="2"><span style="font-size: 10pt">(<span> </span></span></font><font face="Consolas" size="2"><span style="font-size: 10pt">__func1</span></font><font face="Consolas" size="2"><span style="font-size: 10pt">(<span> </span></span></font><font face="Consolas" size="2"><span style="font-size: 10pt">_x</span></font><font face="Consolas" size="2"><span style="font-size: 10pt"><font color="#3665EE"> ) )</font> </span></font></b></span></span></span><span>可以知道，如果 _x 是map里面的单个元素（key/value对，std::pair类型），</span></div>
<div align="left"><span>先用</span><span><span>select2nd_t作用于这个pair得到value,然后做参数传入visitor。</span></span></div>
<div align="left"><font color="#010001"><span style="font-size: 13px"><br /></span></font></div>
<div align="left"><font color="#010001"><span style="font-size: 13px">最后，看我们的遍历map中value的函数：</span></font></div>
<div align="left"><font color="#010001"><span style="font-size: 13px"><br /></span></font></div>
<div align="left">
<div align="left"><font color="#010001"><span style="font-size: 13px"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    </span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">template</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">class</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Map</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">class</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font></span></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">   </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">void</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">for_each_2nd</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">const</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Map</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&amp;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_map</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">const</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&amp;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_func</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">)</span></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    {</span></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">compose_t</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">select2nd_t</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Map</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">value_type</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;,</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Func</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_f</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">select2nd_t</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typename</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_Map</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">value_type</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;(),</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_func</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">);</span></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">std</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">for_each</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_map</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">.</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">begin</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(),</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_map</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">.</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">end</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(),</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">_f</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">);</span></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    };</span></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">通过前面的铺垫，这个函数就比较容易理解了，直接给出使用示例：</span></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></font></div>
<div align="left">
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    </span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">void</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">tset_for_each_2nd</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">()</span></font></span></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    {</span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">typedef</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">std</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">map</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">int</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">int</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">intmap</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">intmap</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">im</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">;</span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">for</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">int</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">i</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">= 0;</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">i</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt; 10; ++</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">i</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">)</span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        {</span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">           </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">im</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">.</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">insert</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">intmap</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">::</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">value_type</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font><font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">i</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">i</span></font> <font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">* 100) );</span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">        }</span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    </span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">       </span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">for_each_2nd</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">(</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">im</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">,</span></font> <font color="#010001" face="Consolas" size="2"><span style="font-size:10pt">visitor</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&lt;</span></font><font color="#0000FF" face="Consolas" size="2"><span style="font-size:10pt">int</span></font><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">&gt;() );</span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt">    }</span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><font color="#010101" face="Consolas" size="2"><span style="font-size:10pt"><br /></span></font></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2"><br /></font></font></div>
<div align="left"><font color="#010001"><font color="#010101" face="Consolas" size="2">总结：本文介绍了for_each的用法，进而更深入的介绍了如何写一个复杂点的组合仿函数。</font></font></div>
</div>
</div>
<div align="left">
<div align="left" style="font-size: 13px"><font color="#010101"><br /></font></div>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2011/10/11/c-stl-compose-for_each.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MFC中用配置文件实现界面布局的方式</title>
		<link>http://www.soft-bin.com/html/2011/07/03/config_button_response_dynamically_in_mfc.html</link>
		<comments>http://www.soft-bin.com/html/2011/07/03/config_button_response_dynamically_in_mfc.html#comments</comments>
		<pubDate>Sun, 03 Jul 2011 13:04:46 +0000</pubDate>
		<dc:creator>luckzj</dc:creator>
				<category><![CDATA[Windows平台编程]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=445</guid>
		<description><![CDATA[最近看了下android程序设计，发现其界面布局是采用一个layout配置文件，以xml的形式配置UI，然后通过android框架对这个layout进行解析，动态生成界面控件。 这种界面设计模式，简化了UI的编码，使得我们可以像写HTML页面一样，设计应用程序的UI。
这种UI设计的方式，实际上在CSharp中也比较容易做到。我们可以轻易设计出一种控制器，来读入界面配置文件，并动态生成界面布局配置扎文件中定义的各种控件，最典型的如Button, Label之类。而后在控制器中添加控件事件响应函数，实现应用程序的业务逻辑。
采用CSharp语言实现这种动态UI配置比较容易，控件的生成，可以通过反射来实现。从配置文件指定的dll中，寻找到指定名称的控件，并动态生成即可。
那么使用C++语言进行界面设计时，可以实现这种动态界面布局么？ 答案是可以的，只是会有一些麻烦。下面我将对在MFC中实现动态界面布局的问题以及解决方案作出分析。
动态界面布局有两大基础要素，一个是动态创建控件，一个是动态的为控件指定事件响应函数。
1. 动态创建控件
我们知道在CSharp中，可以使用反射的方式，通过类名动态创建类的实例。而在C++中，并没有反射的概念。这个问题可以通过巧妙的方式来解决，在MFC中有运行时类的概念，我们可以通过RUNTIME_CLASS(classname)获取一个CRuntimeClass的指针，进而通过CRuntimeClass类来动态地创建。对于需要使用CRuntimeClass动态创建的类，需要在类的定义中添加DECLARE_DYNCREATE的声明，并在实现文件中，添加 IMPLEMENT_DYCREATE。
我们使用CRuntimeClass动态创建一个类的实例时，首先需要使用宏 RUNTIME_CLASS来获取到CRuntimeClass的实例，RUNTIME_CLASS宏的定义如下：
  #define RUNTIME_CLASS(class_name) (class_name::GetThisClass())
而 class_name::GetThisClass() 已经在IMPLEMENT_DYNCREATE中定义，最终定义为返回如下成员：
AFX_COMDAT CRuntimeClass class_name::class##class_name = {
		#class_name, sizeof(class class_name), wSchema, pfnNew,
			&#38;class_name::_GetBaseClass, NULL, class_init };
通过查看CRuntimeClass，发现其为一个结构体，声明如下：
struct CRuntimeClass
{
// Attributes
	LPCSTR m_lpszClassName;
	int m_nObjectSize;
	UINT m_wSchema; // schema number of the loaded class
	CObject* (PASCAL* m_pfnCreateObject)(); // NULL =&#62; abstract class
#ifdef _AFXDLL
	CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
#else
	CRuntimeClass* m_pBaseClass;
#endif

// Operations
	CObject* CreateObject();
	BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;

	// dynamic name [...]]]></description>
			<content:encoded><![CDATA[<p>最近看了下android程序设计，发现其界面布局是采用一个layout配置文件，以xml的形式配置UI，然后通过android框架对这个layout进行解析，动态生成界面控件。 这种界面设计模式，简化了UI的编码，使得我们可以像写HTML页面一样，设计应用程序的UI。</p>
<p>这种UI设计的方式，实际上在CSharp中也比较容易做到。我们可以轻易设计出一种控制器，来读入界面配置文件，并动态生成界面布局配置扎文件中定义的各种控件，最典型的如Button, Label之类。而后在控制器中添加控件事件响应函数，实现应用程序的业务逻辑。</p>
<p>采用CSharp语言实现这种动态UI配置比较容易，控件的生成，可以通过反射来实现。从配置文件指定的dll中，寻找到指定名称的控件，并动态生成即可。</p>
<p>那么使用C++语言进行界面设计时，可以实现这种动态界面布局么？ 答案是可以的，只是会有一些麻烦。下面我将对在MFC中实现动态界面布局的问题以及解决方案作出分析。</p>
<p>动态界面布局有两大基础要素，一个是动态创建控件，一个是动态的为控件指定事件响应函数。</p>
<p><strong>1. 动态创建控件</strong><br />
我们知道在CSharp中，可以使用反射的方式，通过类名动态创建类的实例。而在C++中，并没有反射的概念。这个问题可以通过巧妙的方式来解决，在MFC中有运行时类的概念，我们可以通过RUNTIME_CLASS(classname)获取一个CRuntimeClass的指针，进而通过CRuntimeClass类来动态地创建。对于需要使用CRuntimeClass动态创建的类，需要在类的定义中添加DECLARE_DYNCREATE的声明，并在实现文件中，添加 IMPLEMENT_DYCREATE。</p>
<p>我们使用CRuntimeClass动态创建一个类的实例时，首先需要使用宏 RUNTIME_CLASS来获取到CRuntimeClass的实例，RUNTIME_CLASS宏的定义如下：</p>
<pre>  #define RUNTIME_CLASS(class_name) (class_name::GetThisClass())</pre>
<p>而 class_name::GetThisClass() 已经在IMPLEMENT_DYNCREATE中定义，最终定义为返回如下成员：</p>
<pre>AFX_COMDAT CRuntimeClass class_name::class##class_name = {
		#class_name, sizeof(class class_name), wSchema, pfnNew,
			&amp;class_name::_GetBaseClass, NULL, class_init };</pre>
<p>通过查看CRuntimeClass，发现其为一个结构体，声明如下：</p>
<pre>struct CRuntimeClass
{
// Attributes
	LPCSTR m_lpszClassName;
	int m_nObjectSize;
	UINT m_wSchema; // schema number of the loaded class
	CObject* (PASCAL* m_pfnCreateObject)(); // NULL =&gt; abstract class
#ifdef _AFXDLL
	CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
#else
	CRuntimeClass* m_pBaseClass;
#endif

// Operations
	CObject* CreateObject();
	BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;

	// dynamic name lookup and creation
	static CRuntimeClass* PASCAL FromName(LPCSTR lpszClassName);
	static CRuntimeClass* PASCAL FromName(LPCWSTR lpszClassName);
	static CObject* PASCAL CreateObject(LPCSTR lpszClassName);
	static CObject* PASCAL CreateObject(LPCWSTR lpszClassName);

// Implementation
	void Store(CArchive&amp; ar) const;
	static CRuntimeClass* PASCAL Load(CArchive&amp; ar, UINT* pwSchemaNum);

	// CRuntimeClass objects linked together in simple list
	CRuntimeClass* m_pNextClass;       // linked list of registered classes
	const AFX_CLASSINIT* m_pClassInit;
};</pre>
<p>由此我们知道RUNTIME_CLASS宏实际上最后获取到了一个CRuntimeClass结构体，并对结构体中的各个域进行了赋值。之后我们即可以调用获取到的CRuntimeClass实例的成员函数CreateObject来创建实例。</p>
<p><span id="more-445"></span><br />
CreateObject是如何实现的呢？我们注意到CRuntimeClass结构中有一个域叫做 m_pfnCreateObject， 大胆猜测CreateObject函数就是调用此函数指针来创建新的对象。 而我们在RUNTIME_CLASS宏获取到CRuntimeClass时，对m_pfnCreateObject域的赋值是pfnNew。pfnNew实际是由IMPLEMENT_DYNCREATE宏传入IMPLEMENT_RUNTIMECLASS宏的一个宏参数，这个定义如下：</p>
<pre>#define IMPLEMENT_DYNCREATE(class_name, base_class_name) \
	CObject* PASCAL class_name::CreateObject() \
		{ return new class_name; } \
	IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \
		class_name::CreateObject, NULL)</pre>
<p>其中 class_name::CreateObject即是pfnNew，这个宏定义了创建对象的方法，即是 new class_name</p>
<p>至此，我们已经了解了使用CRuntimeClass来动态创建一个类的方法。即在类中首先生命DECLEAR_DYNCREATE，在实现文件中加入宏 IMPLEMENT_DYNCREATE。</p>
<p>在需要动态创建实例时，如下代码即可实现：</p>
<pre>     CRuntimeClass* pRuntimeClass = RUNTIME_CLASS("MyCtrl");
     CObject* pCtrl = pRuntimeClass-&gt;CreateObject();</pre>
<p><strong>2. 动态为控件指定事件响应函数</strong></p>
<p>控件的事件响应函数比较多，我们以按钮的点击事件为例。在CSharp中，为控件指定事件响应函数很简单，可以直接订阅一个按钮对象的点击事件。 然而在C++中却不是这样。 一方面，C++中没有事件的概念，只有设置回调函数的概念。 MFC的CButton控件中，并没有提供设置回调函数的接口。</p>
<p>MFC中使用消息机制来控制控件的事件，我们以在代码中添加消息响应的方式，来指定按钮的响应函数，例如：</p>
<pre>    ON_BN_CLICKED(IDC_BTN_TEST, OnBtnTest)</pre>
<p>上述代码将IDC_BTN_TEST按钮的点击事件，关联到OnBtnTest函数上。这种方式是在编译期就进行了事件和处理函数之间的绑定，无法实现根据配置文件对按钮响应事件进行动态绑定的需求。</p>
<p>如果我们能够使用一个函数处理所有的按钮点击的事件，切这个函数能获取到被点击的按钮的ID，那么我们可以在此函数中，自行根据按钮ID来分发事件，实现动态控制按钮点击响应函数的目的。</p>
<p>在这个想法的指导下，首先试试看能不能把所有的按钮ID设置为同一个，然后在OnBtnTest函数中，根据ID分发事件。很可惜，OnBtnTest函数的参数为void，无法获取到具体的按钮ID。</p>
<p>转而一想，按钮点击的本质是系统消息，系统消息是带有wParam和lParam参数的，ON_BN_CLICKED只是在系统消息上的一层封装，这一层封装就直接将控件ID给过滤掉了，因此我们可以分析ON_BN_CLICKED，依次追踪此宏定义：</p>
<pre>#define ON_BN_CLICKED(id, memberFxn) \
	ON_CONTROL(BN_CLICKED, id, memberFxn)

#define ON_CONTROL(wNotifyCode, id, memberFxn) \
	{ WM_COMMAND, (WORD)wNotifyCode, (WORD)id, (WORD)id, AfxSigCmd_v, \
		(static_cast&lt; AFX_PMSG &gt; (memberFxn)) },</pre>
<p>通过上述定义，我们发现实际上ON_BN_CLICKED宏是定义了WM_COMMAND消息的响应函数，且其wNodifyCode被定义为了BN_CLICKED。 在MSDN中查询 WM_COMMAND 的消息参数可知：<br />
wParam：高字节表示wNotifyCode，低字节表示控件ID<br />
lParam：  表示控件的句柄</p>
<p>因此，我们可以在窗体的消息处理函数WndProc中，拦截ON_COMMAND消息，获取到按钮点击事件，并进行动态分发：</p>
<pre>LRESULT CDynamicButtonTestDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_COMMAND)
	{
		int wNodify = (wParam &gt;&gt; 16);
		int wID = (wParam &amp; 0xffff);

		HWND hWnd = reinterpret_cast(lParam);
		CWnd* pWnd = CWnd::FromHandle(hWnd);

		// 此处可以开始动态分发事件
		switch (wNodify)
		{
		case BN_CLICKED:
			Dispatch_BN_Clicked(wID, hWnd);
			break;
		}
	}

	return CDialog::WindowProc(message, wParam, lParam);
}</pre>
<p>在上述代码中，我们已经可以对所有的按钮的Click事件作出分发，这个分发动作在Dispatch_BN_Clicked中实现。除了按钮以外，其他所有的控件事件，都可以在WndProc函数中截获，并在分析之后，根据配置文件中的配置进行手工重新分发。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2011/07/03/config_button_response_dynamically_in_mfc.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nginx 模块开发（1）—— 一个稍稍能说明问题模块开发 Step By Step 过程</title>
		<link>http://www.soft-bin.com/html/2011/04/23/nginx-module-dev-helloworld-stepbystep.html</link>
		<comments>http://www.soft-bin.com/html/2011/04/23/nginx-module-dev-helloworld-stepbystep.html#comments</comments>
		<pubDate>Sat, 23 Apr 2011 10:40:23 +0000</pubDate>
		<dc:creator>zieckey</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[Web技术]]></category>
		<category><![CDATA[构建高性能网络服务器]]></category>
		<category><![CDATA[网络技术]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[高性能服务器]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=441</guid>
		<description><![CDATA[本文完成了一个很简单的Nginx模块的开发和调试工作，对一些函数调用，配置文件关系等等比较含糊的地方做了详细说明。]]></description>
			<content:encoded><![CDATA[<p>By zieckey</p>
<p>1. Nginx 介绍</p>
<p>     Nginx 是俄罗斯人编写的十分轻量级的HTTP服务器,它的发音为“engine X”， 是一个高性能的HTTP和反向代理服务器，同时也是一个IMAP/POP3/SMTP 代理服务器．Nginx是由俄罗斯人 Igor Sysoev为俄罗斯访问量第二的 Rambler.ru站点开发的，从2004年开始它已经在该站点运行了七八年了。Igor Sysoev在建立的项目时,使用基于BSD许可。<br />
     英文主页：http://nginx.org.<br />
<span id="more-441"></span><br />
     Nginx以事件驱动的方式编写，所以有非常好的性能，同时也是一个非常高效的反向代理、负载平衡。<br />
     现 在，Igor将源代码以类BSD许可证的形式发布。Nginx因为它的稳定性、丰富的模块库、灵活的配置和低系统资源的消耗而闻名．业界一致认为它是 Apache＋mod_proxy_balancer的轻量级代替者，不仅是因为响应静态页面的速度非常快，而且它的模块数量也非常非常丰富。对 proxy 和 rewrite模块的支持很彻底，还支持mod_fcgi、ssl、vhosts ，适合用来做mongrel clusters的前端HTTP响应。<br />
  nginx做为HTTP服务器，有以下几项基本特性：<br />
处理静态文件，索引文件以及自动索引；打开文件描述符缓冲．<br />
无缓存的反向代理加速，简单的负载均衡和容错．<br />
FastCGI，简单的负载均衡和容错．<br />
模块化的结构。包括gzipping, byte ranges, chunked responses,以及 SSI-filter等filter。如果由FastCGI或其它代理服务器处理单页中存在的多个SSI，则这项处理可以并行运行，而不需要相互等待。<br />
支持SSL 和 TLSSNI．<br />
  Nginx专为性能优化而开发，性能是其最重要的考量,实现上非常注重效率。它支持内核 epoll、kqueue 等高性能并发模型，能经受高负载的考验。<br />
  Nginx具有很高的稳定性。其它HTTP服务器，当遇到访问的峰值，或者有人恶意发起慢速连接时，也很可能会导致服务器物理内存耗尽频繁交换，失去响 应，只能重启服务器。例如当前apache一旦上到200个以上进程，web响应速度就明显非常缓慢了。而Nginx采取了分阶段资源分配技术，使得它的 CPU与内存占用率非常低。nginx官方表示保持10,000个没有活动的连接，它只占2.5M内存，所以类似DOS这样的攻击对nginx来说基本上 是毫无用处的。就稳定性而言,nginx比lighthttpd更胜一筹。<br />
  Nginx支持热部署。它的启动特别容易, 并且几乎可以做到7*24不间断运行，即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下，对软件版本进行进行升级。<br />
  Nginx采用master-slave模型,能够充分利用SMP的优势，且能够减少工作进程在磁盘I/O的阻塞延迟。当采用select()/poll()调用时，还可以限制每个进程的连接数。<br />
  Nginx代码质量非常高，代码很规范，手法成熟， 模块扩展也很容易。特别值得一提的是强大的Upstream与Filter链。 Upstream为诸如reverse proxy,与其他服务器通信模块的编写奠定了很好的基础。而Filter链最酷的部分就是各个filter不必等待前一个filter执行完毕。它可以 把前一个filter的输出做为当前filter的输入，这有点像Unix的管线。这意味着，一个模块可以开始压缩从后端服务器发送过来的请求，且可以在 模块接收完后端服务器的整个请求之前把压缩流转向客户端。<br />
  当然，nginx还很年轻，多多少少存在一些问题，比如：Nginx是俄罗斯人创建，目前文档方面还不是很完善．因为文档大多是俄语，所以文档方面这也是个障碍．尽管nignx的模块比较多，但它们还不够完善。对脚本的支持力度不够。<br />
  这些问题，nginx的作者和社区都在努力解决，我们有理由相信nginx将继续以高速的增长率来分享轻量级HTTP服务器市场，会有一个更美好的未来。</p>
<p>2. 准备工作<br />
      去官方主页 http://nginx.org/ 下载最新的Nginx源码包，这里给出目前最新的源码包的直接连接： http://nginx.org/download/nginx-1.0.0.tar.gz<br />
<code><br />
[zieckey@freebsd7.2 ~]$ mkdir nginx<br />
[zieckey@freebsd7.2 ~]$ cd nginx<br />
[zieckey@freebsd7.2 ~/nginx]$ wget http://nginx.org/download/nginx-1.0.0.tar.gz<br />
[zieckey@freebsd7.2 ~/nginx]$ tar zxf nginx-1.0.0.tar.gz<br />
[zieckey@freebsd7.2 ~/nginx]$ mkdir module_dev_urlquery<br />
[zieckey@freebsd7.2 ~/nginx]$ cd module_dev_urlquery/<br />
[zieckey@freebsd7.2 module_dev_urlquery]$<br />
</code><br />
这里我们下载了 nginx-1.0.0 的源码，然后准备开发一个 module_dev_urlquery 的module嵌入到nginx中</p>
<p>3. 准备好 module_dev_urlquery 模块的配置文件<br />
一个 nginx module 一般都以个文件夹的方式存在，module源文件和该module的配置文件都在这个文件下面。<br />
这里我们的module叫 module_dev_urlquery，其路径为 /home/zieckey/nginx/module_dev_urlquery 。<br />
其配置文件名为：config ，其路径为 /home/zieckey/nginx/module_dev_urlquery/config<br />
[zieckey@freebsd7.2 module_dev_urlquery]$ vim config<br />
然后输入以下内容：<br />
<code><br />
[zieckey@freebsd7.2 module_dev_urlquery]$ vim config<br />
ngx_addon_name=ngx_http_p2s_module<br />
HTTP_MODULES="$HTTP_MODULES ngx_http_p2s_module"<br />
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_p2s_module.c"<br />
</code><br />
这里三行内容稍稍解释下：<br />
第一行是表示这个 nginx module 在程序中名字<br />
第二行表示这是一个HTTP module，后面的名字与第一个行保存一致<br />
第 三是这个module的源文件路径，值得说明的是 $ngx_addon_dir 这个变量是 nginx 的内置脚本的内置变量，代表了这个 module 的文件夹的绝对路径，这里就是 /home/zieckey/nginx/module_dev_urlquery</p>
<p>4. 准备源代码文件 ngx_http_p2s_module.c<br />
这里的文件名和路径必须与上面 config 文件中的一致<br />
[zieckey@freebsd7.2 module_dev_urlquery]$ vim ngx_http_p2s_module.c<br />
输入以下源程序内容：</p>
<p><code><br />
#include "ngx_core.h"<br />
#include "ngx_http.h"<br />
#include "nginx.h"</p>
<p>typedef struct {<br />
    unsigned long consume;<br />
    char* ini_buf;<br />
    size_t buflen;//the lenght of the ini_buf</p>
<p>} ngx_http_p2s_conf_t;</p>
<p>static char *ngx_http_p2s_urlquery_set(ngx_conf_t *cf, ngx_command_t *cmd, void*conf);</p>
<p>static void *ngx_http_p2s_create_conf(ngx_conf_t *cf);</p>
<p>static uint8_t* get_raw_http_body( ngx_http_request_t* r, size_t* body_len );</p>
<p>static ngx_command_t ngx_http_p2s_commands[] =<br />
{/*{{{*/</p>
<p>    { ngx_string("p2s_urlquery"), //The command name, it MUST BE the same as nginx.conf location block's command</p>
<p>    NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,<br />
    ngx_http_p2s_urlquery_set,<br />
    0,<br />
    0,<br />
    NULL },</p>
<p>    ngx_null_command<br />
};/*}}}*/</p>
<p>static ngx_http_module_t ngx_http_p2s_module_ctx =<br />
{/*{{{*/<br />
    NULL, /* preconfiguration */<br />
    NULL, /* postconfiguration */</p>
<p>    NULL, /* create main configuration */<br />
    NULL, /* init main configuration */</p>
<p>    NULL, /* create server configuration */<br />
    NULL, /* merge server configuration */</p>
<p>    ngx_http_p2s_create_conf, /* create location configration */<br />
    NULL /* merge location configration */<br />
};/*}}}*/</p>
<p>ngx_module_t ngx_http_p2s_module =<br />
{/*{{{*/<br />
    NGX_MODULE_V1,<br />
    &amp;ngx_http_p2s_module_ctx, /* module context */<br />
    ngx_http_p2s_commands, /* module directives */<br />
    NGX_HTTP_MODULE, /* module type */<br />
    NULL, /* init master */<br />
    NULL, /* init module */<br />
    NULL, /* init process */<br />
    NULL, /* init thread */<br />
    NULL, /* exit thread */<br />
    NULL, /* exit process */<br />
    NULL, /* exit master */<br />
    NGX_MODULE_V1_PADDING<br />
};/*}}}*/</p>
<p>/**<br />
* @brief Get the HTTP body data from the ngx_http_request_t struct.<br />
* @warning DONNOT release the return pointer.<br />
* @param[in] ngx_http_request_t * r -<br />
* The HTTP request of NGINX struct which holds the HTTP data.<br />
* @param[out] size_t * body_len - The body data length will stored here.<br />
* @return uint8_t* - A pointer to a memory where<br />
* stored the HTTP body raw binary data.<br />
* The memory is allocated from nginx memory pool,<br />
* so the caller don't need to warry about the memory release work.<br />
*/<br />
static uint8_t* get_raw_http_body( ngx_http_request_t* r, size_t* body_len )<br />
{/*{{{*/<br />
    printf( "%s\n", __PRETTY_FUNCTION__ );<br />
    ngx_chain_t* bufs = r-&gt;request_body-&gt;bufs;<br />
    *body_len = 0;</p>
<p>    ngx_buf_t* buf = NULL;<br />
    uint8_t* data_buf = NULL;<br />
    size_t content_length = 0;</p>
<p>    if ( r-&gt;headers_in.content_length == NULL )<br />
    {<br />
        return NULL;<br />
    }</p>
<p>    // malloc space for data_buf</p>
<p>    content_length = atoi( (char*)(r-&gt;headers_in.content_length-&gt;value.data) );</p>
<p>    data_buf = ( uint8_t* )ngx_palloc( r-&gt;pool , content_length + 1 );</p>
<p>    size_t buf_length = 0;</p>
<p>    while ( bufs )<br />
    {<br />
        buf = bufs-&gt;buf;</p>
<p>        bufs = bufs-&gt;next;</p>
<p>        buf_length = buf-&gt;last - buf-&gt;pos ;</p>
<p>        if( *body_len + buf_length &gt; content_length )<br />
        {</p>
<p>            memcpy( data_buf + *body_len, buf-&gt;pos, content_length - *body_len);<br />
            *body_len = content_length ;</p>
<p>            break;<br />
        }</p>
<p>        memcpy( data_buf + *body_len, buf-&gt;pos, buf-&gt;last - buf-&gt;pos );<br />
        *body_len += buf-&gt;last - buf-&gt;pos;<br />
    }</p>
<p>    if ( *body_len )<br />
    {<br />
        data_buf[*body_len] = '';<br />
    }</p>
<p>    return data_buf;<br />
}/*}}}*/</p>
<p>/**<br />
* Process the client request.<br />
* The client post data has stored in <code>r</code><br />
*/<br />
static void p2s_urlquery_process_handler(ngx_http_request_t *r)<br />
{/*{{{*/<br />
    printf( "%s\n", __PRETTY_FUNCTION__ );<br />
    ngx_int_t rc = NGX_OK;<br />
    ngx_buf_t *b = NULL;<br />
    ngx_chain_t out;</p>
<p>    ngx_http_p2s_conf_t *conf = NULL;<br />
    conf = (ngx_http_p2s_conf_t *)ngx_http_get_module_loc_conf(r,ngx_http_p2s_module);<br />
    if (conf == NULL)<br />
    {<br />
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);<br />
        return ;<br />
    }</p>
<p>    struct timeval tv;<br />
    gettimeofday(&amp;tv, NULL);<br />
    size_t bodylen = 0;<br />
    uint8_t* contents = get_raw_http_body( r, &amp;bodylen );<br />
    printf( "time=%f http body data len=%d:\n%s\n", (tv.tv_sec +tv.tv_usec/1000000.0f ), (int)bodylen, (char*)contents );<br />
    printf("----------------------http body data end-------------------\n");</p>
<p>    /* Prepare for output, 128 is preserved for robust */<br />
    b = ngx_create_temp_buf( r-&gt;pool, 128 + conf-&gt;buflen );<br />
    if (b == NULL)<br />
    {<br />
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);<br />
        return ;<br />
    }<br />
    out.buf = b;<br />
    out.next = NULL;</p>
<p>    b-&gt;last = ngx_sprintf(b-&gt;pos, "%s", conf-&gt;ini_buf);</p>
<p>    r-&gt;headers_out.status = NGX_HTTP_OK;<br />
    r-&gt;headers_out.content_length_n = b-&gt;last - b-&gt;pos;<br />
    r-&gt;headers_out.content_type.len = sizeof("text/plain") - 1;<br />
    r-&gt;headers_out.content_type.data = (u_char *) "text/plain";</p>
<p>    b-&gt;last_buf = 1;/* there will be no more buffers in the request */</p>
<p>    rc = ngx_http_send_header(r);</p>
<p>    if (rc == NGX_ERROR || rc &gt; NGX_OK || r-&gt;header_only)<br />
    {<br />
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);<br />
        return ;<br />
    }</p>
<p>    ngx_http_output_filter(r, &amp;out);<br />
    ngx_http_finalize_request(r, 0);<br />
}/*}}}*/</p>
<p>/**<br />
* Reading data handler<br />
* After read all the data from client we set a process handler<br />
*/<br />
static ngx_int_t<br />
ngx_http_p2s_urlquery_handler(ngx_http_request_t *r)<br />
{/*{{{*/<br />
    printf( "%s\n", __PRETTY_FUNCTION__ );<br />
    ngx_int_t rc = NGX_DONE;<br />
    rc = ngx_http_read_client_request_body( r, p2s_urlquery_process_handler );<br />
    if (rc &gt;= NGX_HTTP_SPECIAL_RESPONSE) {<br />
        return rc;<br />
    }</p>
<p>    return NGX_DONE;<br />
}/*}}}*/</p>
<p>/**<br />
* set the request reading data handler<br />
*/<br />
static char *<br />
ngx_http_p2s_urlquery_set( ngx_conf_t *cf, ngx_command_t *cmd, void *conf )<br />
{/*{{{*/<br />
    printf( "%s\n", __PRETTY_FUNCTION__ );<br />
    ngx_http_core_loc_conf_t *clcf;</p>
<p>    clcf = (ngx_http_core_loc_conf_t *)ngx_http_conf_get_module_loc_conf(cf,ngx_http_core_module);<br />
    clcf-&gt;handler = ngx_http_p2s_urlquery_handler;</p>
<p>    return NGX_CONF_OK;<br />
}/*}}}*/</p>
<p>static void *<br />
ngx_http_p2s_create_conf(ngx_conf_t *cf)<br />
{/*{{{*/<br />
    printf( "%s\n", __PRETTY_FUNCTION__ );<br />
    ngx_http_p2s_conf_t *conf;</p>
<p>    conf = (ngx_http_p2s_conf_t *)ngx_pcalloc(cf-&gt;pool,sizeof(ngx_http_p2s_conf_t));<br />
    if (conf == NULL) {<br />
        return NGX_CONF_ERROR;<br />
    }</p>
<p>    conf-&gt;consume = 0;</p>
<p>    /* we open the nginx config file and send it back to client*/<br />
    FILE *fp = fopen( "../conf/nginx.conf", "r");<br />
    if( fp == NULL )<br />
    {<br />
        return NGX_CONF_ERROR;<br />
    }</p>
<p>    fseek(fp, 0, SEEK_END);<br />
    long len = ftell( fp );<br />
    if ( len buflen = (size_t)(len + 1);<br />
    conf-&gt;ini_buf = (char *)ngx_palloc( cf-&gt;pool, len + 1 );<br />
    fseek(fp, 0, SEEK_SET);<br />
    fread(conf-&gt;ini_buf, 1, len, fp);<br />
    conf-&gt;ini_buf[len] = 0;<br />
    fclose(fp);</p>
<p>    return conf;<br />
}/*}}}*/<br />
</code></p>
<p>5. 编译运行<br />
现在可以编译nginx和我们刚刚写好的模块了。<br />
<code><br />
[zieckey@freebsd7.2 ~/nginx]$ cd<br />
[zieckey@freebsd7.2 ~]$ cd nginx/<br />
[zieckey@freebsd7.2 ~/nginx]$ mkdir bininstalled<br />
[zieckey@freebsd7.2 ~/nginx]$ cd nginx-1.0.0<br />
[zieckey@freebsd7.2 nginx-1.0.0]$ ./configure--add-module=/home/zieckey/nginx/module_dev_urlquery--prefix=/home/zieckey/nginx/bininstalled<br />
./configure: error: the HTTP rewrite module requires the PCRE library.<br />
You can either disable the module by using --without-http_rewrite_module<br />
option, or install the PCRE library into the system, or build the PCRE library<br />
statically from the source with nginx by using --with-pcre= option.<br />
</code><br />
第一次错误，我们现在这个freebsd系统上没有pcre库，太悲催了，不过还好，这里给出了提示，说可以通过 &#8211;without-http_rewrite_module 来禁用使用pcre库的 HTTP rewrite 模块，我们试一试：<br />
<code><br />
[zieckey@freebsd7.2 nginx-1.0.0]$ ./configure--add-module=/home/zieckey/nginx/module_dev_urlquery--prefix=/home/zieckey/nginx/bininstalled --without-http_rewrite_module<br />
adding module in /home/zieckey/nginx/module_dev_urlquery<br />
+ ngx_http_p2s_module was configured<br />
</code><br />
重点看到上面几行信息，说明我们自己写的模块module_dev_urlquery已经被nginx接纳，生成makefile成功。<br />
<code><br />
[zieckey@freebsd7.2 nginx-1.0.0]$ make<br />
[zieckey@freebsd7.2 nginx-1.0.0]$ make install<br />
[zieckey@freebsd7.2 nginx-1.0.0]$ cd /home/zieckey/nginx/bininstalled/<br />
[zieckey@freebsd7.2 bininstalled]$ ls<br />
conf html logs sbin<br />
[zieckey@freebsd7.2 bininstalled]$ cd conf<br />
[zieckey@freebsd7.2 conf]$ vim ngi<br />
nginx.conf nginx.conf.default<br />
[zieckey@freebsd7.2 conf]$ vim nginx.conf<br />
</code><br />
默认的配置文件是下面（将‘#’开头的注释行删除之后）<br />
<code><br />
worker_processes 1;<br />
events {<br />
    worker_connections 1024;<br />
}<br />
http {<br />
    include mime.types;<br />
    default_type application/octet-stream;<br />
    sendfile on;<br />
    keepalive_timeout 65;<br />
    server {<br />
        listen 80;<br />
        server_name localhost;<br />
        location / {<br />
            root html;<br />
            index index.html index.htm;<br />
        }<br />
   }<br />
}<br />
</code><br />
我们在最上面添加如下选项：daemon off;  可以让程序不以daemon的方式运行，这样我们可以看到一些调试的打印信息。<br />
另外，在 server 里面添加一个 URI ：<br />
<code><br />
location /urlquery {<br />
    p2s_urlquery;<br />
}<br />
</code><br />
最后，我们修改下http监听的端口号，从默认的80改为8088，因为有些时候，我们并没有权限在80端口上监听连接。<br />
修改之后的配置文件全文如下：<br />
<code><br />
daemon off;<br />
worker_processes 1;<br />
events {<br />
    worker_connections 1024;<br />
}<br />
http {<br />
    include mime.types;<br />
    default_type application/octet-stream;<br />
    sendfile on;<br />
    keepalive_timeout 65;<br />
    server {<br />
        listen 8088;<br />
        server_name localhost;<br />
        location / {<br />
            root html;<br />
            index index.html index.htm;<br />
        }<br />
        location /urlquery {<br />
            p2s_urlquery;<br />
        }<br />
    }<br />
}<br />
</code><br />
好了，到此为止，我们的所有工作就都准备好了，可以启动nginx<br />
<code><br />
[zieckey@freebsd7.2 conf]$ cd /home/zieckey/nginx/bininstalled/sbin/<br />
[zieckey@freebsd7.2 sbin]$ ./nginx<br />
ngx_http_p2s_create_conf<br />
ngx_http_p2s_create_conf<br />
ngx_http_p2s_create_conf<br />
ngx_http_p2s_create_conf<br />
ngx_http_p2s_urlquery_set<br />
</code></p>
<p>新开一个终端，用curl来发起一个http post请求，post数据由-d参数指定：<br />
<code><br />
[zieckey@freebsd7.2 ~]$ curl -d "user=zieckey&amp;verifykey=123456"http://localhost:8088/urlquery<br />
daemon off;<br />
worker_processes 1;<br />
events {<br />
    worker_connections 1024;<br />
}<br />
http {<br />
    include mime.types;<br />
    default_type application/octet-stream;<br />
    sendfile on;<br />
    keepalive_timeout 65;<br />
    server {<br />
        listen 8088;<br />
        server_name localhost;<br />
        location / {<br />
            root html;<br />
            index index.html index.htm;<br />
                }<br />
                location /urlquery {<br />
                        p2s_urlquery;<br />
                }<br />
        }<br />
}<br />
[zieckey@freebsd7.2 ~]$<br />
</code><br />
然后可以看看nginx服务器的一些输出信息：<br />
<code><br />
[zieckey@freebsd7.2 sbin]$ ./nginx<br />
ngx_http_p2s_create_conf<br />
ngx_http_p2s_create_conf<br />
ngx_http_p2s_create_conf<br />
ngx_http_p2s_create_conf<br />
ngx_http_p2s_urlquery_set<br />
ngx_http_p2s_urlquery_handler<br />
p2s_urlquery_process_handler<br />
get_raw_http_body<br />
time=1303552000.000000 http body data len=29:<br />
user=zieckey&amp;verifykey=123456<br />
----------------------http body data end-------------------<br />
</code><br />
6. 其他说明<br />
6.1 配置文件和ngx_command_t的对应关系：<br />
<code><br />
static ngx_command_t ngx_http_p2s_commands[] =<br />
{/*{{{*/<br />
    { ngx_string("p2s_urlquery"), // 命令名，请对照 nginx.conf 看这个<br />
      NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,<br />
      ngx_http_p2s_urlquery_set,<br />
      0,<br />
      0,<br />
      NULL },</p>
<p>      ngx_null_command<br />
};/*}}}*/<br />
</code><br />
nginx.conf 中的 location 字段的配置是这样的：<br />
<code><br />
        location /urlquery {<br />
            p2s_urlquer;<br />
        }<br />
</code><br />
这里的 /urlquery 是 URL 请求里的 URI 部分，<br />
例如 http://localhost/urlquery 这条URL的请求会被这条配置项处理，<br />
这条配置项，会去找命令名为“p2s_urlquery”的 ngx_command 去处理。</p>
<p>6.2 模块名<br />
代码中的模块变量名必须与config配置文件的名字一致<br />
config 配置文件的内容：ngx_addon_name=ngx_http_p2s_module<br />
代码中的内容：<br />
<code><br />
ngx_module_t ngx_http_p2s_module =<br />
{/*{{{*/<br />
    NGX_MODULE_V1,<br />
    &amp;ngx_http_p2s_module_ctx, /* module context */<br />
    ngx_http_p2s_commands, /* module directives */<br />
    NGX_HTTP_MODULE, /* module type */<br />
    NULL, /* init master */<br />
    NULL, /* init module */<br />
    NULL, /* init process */<br />
    NULL, /* init thread */<br />
    NULL, /* exit thread */<br />
    NULL, /* exit process */<br />
    NULL, /* exit master */<br />
    NGX_MODULE_V1_PADDING<br />
};/*}}}*/<br />
</code></p>
<p>模 块的config配置文件会帮助 configure 生成一个ngx_modules.c文件，该文件里会引用 ngx_module_t  ngx_http_p2s_module 这个外部定义的变量，所以必须保持一致。在执行 ./configure 完后，在nginx-1.0.0源码的根目录会多出来一个文件夹objs，在这里可以找到ngx_modules.c文件。</p>
<p>6.3 代码调用关系<br />
nginx程序启动的时候，会去读配置文件 conf/nginx.conf ，每读到一个配置项，就会调用 module 注册的回调函数，所以这里可以看到nginx启动的时候调用 ngx_http_p2s_create_conf 函数好几次。 这个函数是由<br />
<code><br />
static ngx_http_module_t ngx_http_p2s_module_ctx =<br />
{/*{{{*/<br />
    NULL, /* preconfiguration */<br />
    NULL, /* postconfiguration */</p>
<p>    NULL, /* create main configuration */<br />
    NULL, /* init main configuration */</p>
<p>    NULL, /* create server configuration */<br />
    NULL, /* merge server configuration */</p>
<p>    ngx_http_p2s_create_conf, /* create location configration */<br />
    NULL /* merge location configration */<br />
};/*}}}*/<br />
</code><br />
指定的。</p>
<p>然 后，在一个客户端发起http请求的时候，例如我们这里的 “curl http://localhost:8088/urlquery” 命令实际上是发起一个 http 请求，URI 是 urlquery，所以，nginx 根据配置文件的配置项，找到  urlquery 对应的处理模块名 p2s_urlquery， 然后调用 p2s_urlquery 这个名字关联的 ngx_http_p2s_urlquery_set 回调函数。<br />
ngx_http_p2s_urlquery_set 回调函数又会设置一个 ngx_http_p2s_urlquery_handler 回调函数，ngx_http_p2s_urlquery_handler 回调函数会在 nginx 读取客户端发过来的http数据的时候被调用。<br />
ngx_http_p2s_urlquery_handler 又会设置一个 p2s_urlquery_process_handler 回调函数，<br />
p2s_urlquery_process_handler 会在 nginx 读取完客户端发过来的http数据之后的时候被调用，<br />
不难发现，p2s_urlquery_process_handler函数是我们真正的处理逻辑，因为这个时候已经收完了客户端的http数据。</p>
<p>p2s_urlquery_process_handler 函数先调用 get_raw_http_body 这个我们自己封装的函数将客户端发送过来的 http data 读取到一个缓冲区中，然后处理（这里我们只是简单的printf）。然后，我们准备好数据，发送会客户端。</p>
<p>到此，我们完成了一个很简单的模块的开发和调试工作，也不是那么困难。<br />
同时对一些函数调用，配置文件关系等等比较含糊的地方做了详细说明。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2011/04/23/nginx-module-dev-helloworld-stepbystep.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一句话解说内存屏障 Memory barrier</title>
		<link>http://www.soft-bin.com/html/2011/03/17/simply-expai-memory-barrier.html</link>
		<comments>http://www.soft-bin.com/html/2011/03/17/simply-expai-memory-barrier.html#comments</comments>
		<pubDate>Thu, 17 Mar 2011 08:45:35 +0000</pubDate>
		<dc:creator>zieckey</dc:creator>
				<category><![CDATA[多线程]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=439</guid>
		<description><![CDATA[内存屏障，可以保证在此之前的代码全部执行完才开始执行在此之后的代码
参考wikipedia的定义：
Memory barrier, also known as membar or memory fence or fence instruction, is a type of barrier and a class of instruction which causes a central processing unit (CPU) or compiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction.

http://en.wikipedia.org/wiki/Memory_barrier
一个例子：
Processor #1:
     x = f = [...]]]></description>
			<content:encoded><![CDATA[<p>内存屏障，可以保证在此之前的代码全部执行完才开始执行在此之后的代码</p>
<p>参考wikipedia的定义：<br />
Memory barrier, also known as membar or memory fence or fence instruction, is a type of barrier and a class of instruction which causes a central processing unit (CPU) or compiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction.</p>
<p><span id="more-439"></span></p>
<p>http://en.wikipedia.org/wiki/Memory_barrier</p>
<p>一个例子：<br />
Processor #1:<br />
     x = f = 0<br />
     loop:<br />
            load the value in location f, if it is 0 goto loop<br />
     print the value in location x</p>
<p>Processor #2:<br />
     store the value 42 into location x<br />
     store the value 1 into location f</p>
<p>上面的例子中，变量 x f 初始化值都是0。我们期望输出“42”。但是结果并不总是这样。<br />
如果 Processor #2 的执行顺序是乱序的（out-of-order execution），也就是说，对f赋值的语句先于对x赋值的语句，那么就有可能输出“0”<br />
对于大多数的程序来说，这种特例情况是不能容忍的。<br />
如果将内存屏障置于对f赋值的语句之前，那么就能保证 Processor #2 先对x赋值，然后才对f赋值。这样就能得到我们期望的结果，输出“42”</p>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2011/03/17/simply-expai-memory-barrier.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转载]Windows路径探究</title>
		<link>http://www.soft-bin.com/html/2010/11/03/windows_file_path.html</link>
		<comments>http://www.soft-bin.com/html/2010/11/03/windows_file_path.html#comments</comments>
		<pubDate>Wed, 03 Nov 2010 14:33:16 +0000</pubDate>
		<dc:creator>luckzj</dc:creator>
				<category><![CDATA[未分类]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=433</guid>
		<description><![CDATA[原文地址： http://www.cnblogs.com/zplutor/archive/2010/08/21/1805335.html
Windows路径是我们经常使用的东西，它看似简单，实际上隐含许多细节，这些都是在平常的使用过程中注意不到的。下面让我们来看看各种各样的Windows路径。
提起路径，我们都会想到“绝对路径”和“相对路径”，实际上绝对路径是一个广泛的概念，它表示的是可以唯一定位一个文件或文件夹的路径，有多种形式的路径都属于绝对路径的范畴，例如：
完整路径（Full path）
我们平时所说的“绝对路径”通常就是指完整路径，它的格式如下：
C:\Windows\System32\calc.exe
UNC（Universal Naming Convention通用命名规范）路径
UNC路径用于在局域网上定位文件或文件夹，在通过网上邻居访问其它系统上的共享文件时使用的就是UNC路径。UNC路径的格式如下：
\\PC101\ShareFiles\job.doc
其中PC101是目标系统的计算机名，ShareFiles是目标系统上的共享文件夹名称。
以\\?\开头的路径
在某些手工辅助杀毒的工具中可以看到以\\?\开头的路径，这种路径我还找不到正式的名称。完整路径和UNC路径都可以以\\?\开头：
\\?\C:\Windows\System32\calc.exe
\\?\UNC\PC101\ShareFiles\job.doc
相对路径（Relative path）
上面四种路径都可以在本地或网络上绝对定位一个文件，因此属于绝对路径。另一种我们常常使用的是相对路径，这种路径需要与进程的当前文件夹（Current directory）一起合作才可以定位一个文件或文件夹。进程的当前文件夹并不是指EXE文件所在的文件夹，它是每个进程都有的一个属性。例如在命令提示符中显示的路径就是这个cmd.exe进程的当前文件夹，使用cd命令可以改变当前文件夹，无论当前文件夹如何改变，cmd.exe文件所在的文件夹总是不变的。在进程启动的时候可以指定它的当前文件夹，例如在快捷方式的属性中有一个“起始位置”输入框，这个就是进程启动后的当前文件夹。如果在启动时不指定进程的当前文件夹（直接双击EXE文件的情况），那么EXE文件的所在文件夹就会作为它的当前文件夹。
纯粹的相对路径格式如下：
Windows\System32\calc.exe
要注意的是相对路径的开头不能有\，很多人以为有没有\都是一样的，其实不然，以\开头的路径是另外一种路径，下文会详细介绍这种路径。
如果在进程中操作文件时传递一个相对路径，那么进程会将当前文件夹的路径与这个相对路径合并，得到一个完整路径。例如命令提示符的当前文件夹是C:\Windows，如果执行start System32\calc.exe命令，程序就会将两个路径合并得到C:\Windows\System32\calc.exe。
由于这样的特性，当前文件夹又称为工作文件夹，因为进程使用相对路径时都是针对该文件夹的。
除了上面所说的纯粹的相对路径，还有两种特殊的相对路径，为了不至于混淆，不再将它们称为相对路径。
以\开头的路径
上面说过相对路径不能以\开头，一旦如此，它就表示相对于当前文件夹根目录的路径。例如进程的当前文件夹是C:\Windows，那么\System32\calc.exe就表示C:\System32\calc.exe。不论当前文件夹的路径有多深，只取根目录进行合并。可以在命令提示符中进行验证：首先将C:\Windows设置为当前文件夹，然后执行start \System32\calc.exe命令，将会提示错误，所找不到文件。再执行start \Windows\System32\calc.exe命令，这时计算器程序成功启动了，证明了上面的说法。
以盘符和冒号开头的路径
这种路径就像是拼写错误的完整路径，它的格式如下：
C:System32\calc.exe
盘符加冒号是一种特殊的表示法，表示的是进程在“该分区上的当前文件夹”。这里又蹦出来了一个当前文件夹，这与上文的当前文件夹是不同的。简单来说，对于每一个分区，进程都会保存在这个分区上最后使用的当前文件夹。可能解析的不够好，那么可以使用命令提示符来操作一遍以加深理解。

运行cmd，执行cd /d C:\Windows\System32命令进入该文件夹，然后切换到其它的分区，再执行C:calc.exe命令，可以看到计算器程序启动了。
我们在执行cd命令进入C:\Windows\System32文件夹后，进程便以此为当前文件夹，当切换到其余的分区时，进程先将这个文件夹的路径保存起来，再进行切换。使用盘符和冒号的形式读取指定分区上的当前文件夹。
路径中的限制
除了路径格式上的限制，还有很多字符上的限制，下面一一来看看各种路径有什么限制。
除了以\\?\开头的路径之外，其它路径的长度都不能超过260个字符（包括结尾的\0字符），而\\?\开头的路径长度可以达到约32000个字符（系统在处理\\?\前缀的时候可能将它扩展成更长的字符串）。网络上流传的一则技巧：文件路径太长而不能被删除，可以在执行del命令时在路径前加上\\?\前缀。
文件或文件夹名称的最后一个字符不能为空格或句点。但在路径中，最后一个字符可以为句点，因为路径中的句点表示的是当期文件夹（这与上文的当前文件夹完全不同），两个句点表示的是上一级文件夹。以\\?\开头的路径中不能使用句点表示当前文件夹或上一级文件夹，在资源管理器的地址栏中虽然可以这么做，那是因为资源管理器对其作了处理。
文件或文件夹名称不能包含的字符 ：
&#60; &#62; : &#8221; / \ &#124; ? *
在路径中可以使用 : \ ?，冒号是与盘符一起使用的，问号是\\?\前缀中特有的，除此之外不能出现这两个字符；而\是文件夹分割符。虽然我们也能使用/作为分隔符，实际上这是不允许的，系统在处理路径时会将/替换成\。另外，如果路径最后一个字符是\，那么该路径表示的是文件夹；否则表示的是一个文件。
UNC路径的计算机名部分不能出现以下字符：
` ~ ! @ # $ % ^ &#38; * ( ) = + _ [ ] { } \ &#124; ; : . ‘ “ , &#60; &#62; / ?
确实是够多的了，实际上标准的计算机名推荐只使用26个英文字母、10个数字以及-（连字符），否则可能会出现找不到计算机的情况。在更改计算机名的时候如果出现非标准字符，系统会作出提示。
]]></description>
			<content:encoded><![CDATA[<p>原文地址： <a href="http://www.cnblogs.com/zplutor/archive/2010/08/21/1805335.html">http://www.cnblogs.com/zplutor/archive/2010/08/21/1805335.html</a></p>
<p>Windows路径是我们经常使用的东西，它看似简单，实际上隐含许多细节，这些都是在平常的使用过程中注意不到的。下面让我们来看看各种各样的Windows路径。</p>
<p>提起路径，我们都会想到“绝对路径”和“相对路径”，实际上绝对路径是一个广泛的概念，它表示的是可以唯一定位一个文件或文件夹的路径，有多种形式的路径都属于绝对路径的范畴，例如：</p>
<h5>完整路径（Full path）</h5>
<p>我们平时所说的“绝对路径”通常就是指完整路径，它的格式如下：<br />
C:\Windows\System32\calc.exe</p>
<h5>UNC（Universal Naming Convention通用命名规范）路径</h5>
<p>UNC路径用于在局域网上定位文件或文件夹，在通过网上邻居访问其它系统上的共享文件时使用的就是UNC路径。UNC路径的格式如下：<br />
\\PC101\ShareFiles<a href="file://pc101/ShareFiles/">\</a>job.doc<br />
其中PC101是目标系统的计算机名，ShareFiles是目标系统上的共享文件夹名称。</p>
<h5>以\\?\开头的路径</h5>
<p>在某些手工辅助杀毒的工具中可以看到以\\?\开头的路径，这种路径我还找不到正式的名称。完整路径和UNC路径都可以以\\?\开头：<br />
\\?\C:\Windows\System32\calc.exe<br />
\\?\UNC\PC101\ShareFiles\job.doc</p>
<h5>相对路径（Relative path）</h5>
<p>上面四种路径都可以在本地或网络上绝对定位一个文件，因此属于绝对路径。另一种我们常常使用的是相对路径，这种路径需要与进程的当前文件夹（Current directory）一起合作才可以定位一个文件或文件夹。进程的当前文件夹并不是指EXE文件所在的文件夹，它是每个进程都有的一个属性。例如在命令提示符中显示的路径就是这个cmd.exe进程的当前文件夹，使用cd命令可以改变当前文件夹，无论当前文件夹如何改变，cmd.exe文件所在的文件夹总是不变的。在进程启动的时候可以指定它的当前文件夹，例如在快捷方式的属性中有一个“起始位置”输入框，这个就是进程启动后的当前文件夹。如果在启动时不指定进程的当前文件夹（直接双击EXE文件的情况），那么EXE文件的所在文件夹就会作为它的当前文件夹。</p>
<p>纯粹的相对路径格式如下：</p>
<p>Windows\System32\calc.exe<br />
要注意的是相对路径的开头不能有\，很多人以为有没有\都是一样的，其实不然，以\开头的路径是另外一种路径，下文会详细介绍这种路径。</p>
<p>如果在进程中操作文件时传递一个相对路径，那么进程会将当前文件夹的路径与这个相对路径合并，得到一个完整路径。例如命令提示符的当前文件夹是C:\Windows，如果执行start System32\calc.exe命令，程序就会将两个路径合并得到C:\Windows\System32\calc.exe。<br />
由于这样的特性，当前文件夹又称为工作文件夹，因为进程使用相对路径时都是针对该文件夹的。</p>
<p>除了上面所说的纯粹的相对路径，还有两种特殊的相对路径，为了不至于混淆，不再将它们称为相对路径。</p>
<h5>以\开头的路径</h5>
<p>上面说过相对路径不能以\开头，一旦如此，它就表示相对于当前文件夹根目录的路径。例如进程的当前文件夹是C:\Windows，那么\System32\calc.exe就表示C:\System32\calc.exe。不论当前文件夹的路径有多深，只取根目录进行合并。可以在命令提示符中进行验证：首先将C:\Windows设置为当前文件夹，然后执行start \System32\calc.exe命令，将会提示错误，所找不到文件。再执行start \Windows\System32\calc.exe命令，这时计算器程序成功启动了，证明了上面的说法。</p>
<h5>以盘符和冒号开头的路径</h5>
<p>这种路径就像是拼写错误的完整路径，它的格式如下：<br />
C:System32\calc.exe</p>
<p>盘符加冒号是一种特殊的表示法，表示的是进程在“该分区上的当前文件夹”。这里又蹦出来了一个当前文件夹，这与上文的当前文件夹是不同的。简单来说，对于每一个分区，进程都会保存在这个分区上最后使用的当前文件夹。可能解析的不够好，那么可以使用命令提示符来操作一遍以加深理解。<br />
<span id="more-433"></span><br />
运行cmd，执行cd /d C:\Windows\System32命令进入该文件夹，然后切换到其它的分区，再执行C:calc.exe命令，可以看到计算器程序启动了。</p>
<p>我们在执行cd命令进入C:\Windows\System32文件夹后，进程便以此为当前文件夹，当切换到其余的分区时，进程先将这个文件夹的路径保存起来，再进行切换。使用盘符和冒号的形式读取指定分区上的当前文件夹。</p>
<h5>路径中的限制</h5>
<p>除了路径格式上的限制，还有很多字符上的限制，下面一一来看看各种路径有什么限制。</p>
<p>除了以\\?\开头的路径之外，其它路径的长度都不能超过260个字符（包括结尾的\0字符），而\\?\开头的路径长度可以达到约32000个字符（系统在处理\\?\前缀的时候可能将它扩展成更长的字符串）。网络上流传的一则技巧：文件路径太长而不能被删除，可以在执行del命令时在路径前加上\\?\前缀。</p>
<p>文件或文件夹名称的最后一个字符不能为空格或句点。但在路径中，最后一个字符可以为句点，因为路径中的句点表示的是当期文件夹（这与上文的当前文件夹完全不同），两个句点表示的是上一级文件夹。以\\?\开头的路径中不能使用句点表示当前文件夹或上一级文件夹，在资源管理器的地址栏中虽然可以这么做，那是因为资源管理器对其作了处理。</p>
<p>文件或文件夹名称不能包含的字符 ：<br />
&lt; &gt; : &#8221; / \ | ? *<br />
在路径中可以使用 : \ ?，冒号是与盘符一起使用的，问号是\\?\前缀中特有的，除此之外不能出现这两个字符；而\是文件夹分割符。虽然我们也能使用/作为分隔符，实际上这是不允许的，系统在处理路径时会将/替换成\。另外，如果路径最后一个字符是\，那么该路径表示的是文件夹；否则表示的是一个文件。</p>
<p>UNC路径的计算机名部分不能出现以下字符：<br />
` ~ ! @ # $ % ^ &amp; * ( ) = + _ [ ] { } \ | ; : . ‘ “ , &lt; &gt; / ?<br />
确实是够多的了，实际上标准的计算机名推荐只使用26个英文字母、10个数字以及-（连字符），否则可能会出现找不到计算机的情况。在更改计算机名的时候如果出现非标准字符，系统会作出提示。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2010/11/03/windows_file_path.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>pinvoke中的字符串</title>
		<link>http://www.soft-bin.com/html/2010/09/01/pinvoke_string.html</link>
		<comments>http://www.soft-bin.com/html/2010/09/01/pinvoke_string.html#comments</comments>
		<pubDate>Wed, 01 Sep 2010 02:54:21 +0000</pubDate>
		<dc:creator>luckzj</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=427</guid>
		<description><![CDATA[介绍字符串在pinvoke中的使用方法]]></description>
			<content:encoded><![CDATA[<p>我们编写C#程序时，有时候会用到一些C封装的函数，例如Windows API之类。我们可以使用IntPtr解决几乎所有参数封送的问题，但毕竟使用IntPtr读写内存非常麻烦，实际上微软为我们提供了许多简易的操作方式，这篇文章要介绍的就是字符串在pinvoke中的使用方式。</p>
<p><strong>建立测试环境</strong></p>
<p>测试环境的建立，请参考<a href="http://soft-bin.com">soft-bin.com</a>上之前的文章 &#8220;P/INVOKE使用方法万惊油&#8221;，查看C#文章分类即可找到这篇文章。</p>
<p>在建立了测试环境以后，我们可以编写C的程序供C#调用，我们还可以开启 Unmanaged Code Debugging来对C#传入到C中的参数进行调试查看。</p>
<p><strong>字符串作为传入参数</strong></p>
<p>很多函数要求将字符串传入其中，例如FindWindow函数。我们可以编写自己的C++测试函数：</p>
<pre class="brush: cpp;">
void TestString(char* strIn)
{
    cout &lt;&lt; strIn &lt;&lt; endl;
}
</pre>
<p>这几乎是最简单的字符串测试了，在C#中作如下声明即可使用这个函数：</p>
<pre class="brush: csharp;">
public static extern TestString(
    [MarshalAs(UnmanagedType.LPStr)]
    string strIn
);
</pre>
<p>为了简便起见，我将函数声明前的DllImport属性省去不写。</p>
<p><span id="more-427"></span><br />
PINVOKE中使用字符串的关键在于为参数加上 MarshalAs属性，并指明其封送的格式，这里我指定的是 UnmanagedType.LPStr，也就是字符串。</p>
<p>我们知道，在C++中，字符串可能是较为原始的单字节字符串，也可能是宽字节的字符串。而UnmagedType中对应地也提供了： LPStr, LPTStr和LPWStr三种数据格式，分别对应C++中的 CHAR, TCHAR和WCHAR。</p>
<p>CHAR即表示ANSI字符，TCHAR则表示到底是ANSI还是UNICODE根据编译选项来决定，WCHAR则表示UNICODE字符。</p>
<p>三种对应使用的方式如下：</p>
<pre class="brush: cpp;">
void TestString(TCHAR* strIn)
{
    cout &lt;&lt; strIn &lt;&lt; endl;
}

public static extern TestString(
    [MarshalAs(UnmanagedType.LPTStr)]
    string strIn
);
</pre>
<pre class="brush: cpp;">
void TestString(WCHAR* strIn)
{
    cout &lt;&lt; strIn &lt;&lt; endl;
}

public static extern TestString(
    [MarshalAs(UnmanagedType.LPWStr)]
    string strIn
);
</pre>
<p>我们知道在C#中，字符串有两种表示方法，一种是string，另一种则是 StringBuilder。在字符串作为参数传入C函数时，我们即可以用string，也可以用StringBuilder。使用StringBuilder只需要将上例中的string替换为StringBuilder即可。</p>
<p><strong>字符串作为函数返回值的情况</strong></p>
<p>字符串作为返回值的情况与作为参数时是完全一样的，如下：</p>
<pre class="brush: cpp;">
char* Greeting()
{
    static char* p = &quot;Hello&quot;;
    return p;
}

[DllImport(&quot;Target.dll&quot;)]
[return:MarshalAs(UnmanagedType.LPStr)]
public static extern string Greeting();
</pre>
<p>对于TCHAR和WCHAR的处理，也同上，且我们同样可以使用 StringBuilder接受返回值。</p>
<p><strong>字符串作为参数返回值的情况</strong></p>
<p>这种情况的典型例子如下：</p>
<pre class="brush: cpp;">
void GetString(char* pOut)
{
    ASSERT(pOut);
    strncpy(pOut, &quot;hello&quot;, 5);
}
</pre>
<p>这种情况与前述string使用方法有些不同，前面 两种情况，我们可以选择string或者StringBuilder来封送数据，而在这种情况下，我们只能选择StringBuilder，即，只能以如下方式调用：</p>
<pre class="brush: csharp;">
public static extern void GetString(
    MarshalAs(UnmanagedType.LPStr)]
    StringBuilder pOut
);
</pre>
<p>也就是说，对于传出型的参数，我们只能使用StringBuilder，这个其实很好理解，在C#中，string的内容是不可改变的，而StringBuilder中的内容则可以改变，我们可以将string视为 const char*， 则以下代码是不可接受的：</p>
<pre class="brush: cpp;">
char a[10];
const char* p = a;
GetString(p);
</pre>
<p><strong>总结<strong></p>
<p>1. 使用 MarshalAs 可以指定pinvoke数据封送格式为字符串，字符串有三种： LPSTR, LPTSTR和LPWSTR<br />
2. 输出型参数只能用StringBuilder表示，其他则可以使用string，也可以使用StringBuilder<br />
3. 附注： string和StringBuilder均为引用类型，在使用时，不要在参数前加 ref 关键字</p>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2010/09/01/pinvoke_string.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C#端口扫描</title>
		<link>http://www.soft-bin.com/html/2010/08/31/charp_port_scan.html</link>
		<comments>http://www.soft-bin.com/html/2010/08/31/charp_port_scan.html#comments</comments>
		<pubDate>Tue, 31 Aug 2010 01:41:42 +0000</pubDate>
		<dc:creator>luckzj</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=424</guid>
		<description><![CDATA[介绍如何使用C#扫描网络上的代理服务器。]]></description>
			<content:encoded><![CDATA[<p>最近公司断网，不让访问外网，于是写了个网络代理扫描程序。</p>
<p><strong>端口扫描的概念</strong></p>
<p>我们知道，每一个网络服务程序都会绑定一个端口，客户端可以通过将数据发送到这个端口，从而获得服务。这种获取服务的活动，是我们在已知某一IP上开启了某种服务后，通过端口与服务器通信的活动。我们也可以逆向考虑这个问题，即，可以通过尝试给某一IP发送数据，通过响应情况来判断这个IP上是否存在这一服务，而连续向某一段IP地址发送网络数据，以测试服务是否存在的情况，就被称为端口扫描。</p>
<p>我们已知的默认端口列表如下：</p>
<p>HTTP网站服务：80   （很多人喜欢把端口改为8080，如果想扫描HTTP服务，建议扫描80和8080端口）</p>
<p>FTP服务： 21</p>
<p>TELNET服务：23</p>
<p>反恐精英服务器（CS）：27015   （本科的时候见到有人扫这个端口，然后加入别人建立的CS游戏）</p>
<p>网络代理软件ccProxy默认端口： 808(http)， 1080(sockV5)</p>
<p>其他的端口就不列了，想要扫什么服务，直接查其端口即可。</p>
<p><strong>C#简单的端口扫描</strong></p>
<p>简单的端口扫描其实没什么好说的，就是在界面上指定IP范围，程序通过死循环来不断尝试连接指定的IP。这里需要注意几个地方：</p>
<p>1. 输入的IP是string类型的，我们可以通过IPAddress.Parse方法，将其转换成IPAddress类的实例。</p>
<p>2. 为了扫描一个范围的IP地址，我们需要能够对IP地址实现加1，比较的功能。</p>
<p>以下的讨论中，只考虑IPV4的处理。IP通常被表示为10.1.2.3的形式，但实际上在内存中，其使用4个字节的空间存储，每个字节存储0到255，也就是使用字符串表示的值变为数字，例如 10.1.2.3 在内存中存储为4个字节，分别为：</p>
<pre class="brush: csharp;">
b[0] = 10;
b[1] = 1;
b[2] = 2;
b[3] = 3;
</pre>
<p>在此基础上，我们需要编写两个函数来实现IP地址的自增和比较，废话不多，源码如下：<br />
<span id="more-424"></span></p>
<pre class="brush: csharp;">
// a&gt;b=&gt;1, a&lt;b=&gt;-1, a==b=&gt;0
int Compare(byte[] a, byte[] b)
{
    for (int i = 0; i &lt; 4; i++)
    {
        if (a[i] &gt; b[i]) return 1;
        if (a[i] &lt; b[i]) return -1;
    }

    return 0;
}

void Increment(byte[] a)
{
    int i = 3;
    while (a[i] == 255 &amp;&amp; i &gt; 0)
    {
         i--;
    }

    a[i] += 1;
    for (int j = 3; j &gt; i; j--)
    {
        a[j] = 0;
    }
}
</pre>
<p>下面就可以开始扫描了，扫描实际上使用TcpClient类来尝试连接ip:port，伪代码如下：</p>
<p>[chsarp]<br />
public class PortScan<br />
{<br />
    private byte[] ipStart;<br />
    private byte[] ipEnd;<br />
    private byte[] cursor;<br />
    private int[] ports;</p>
<p>    public PortScan()<br />
    {<br />
        // 初始化条件<br />
        cursor = ipStart;<br />
    }</p>
<p>    void DoScan()<br />
    {<br />
        while (Compare(this.ipEnd, cursor, 4) > 0)<br />
        {<br />
            foreach (int port in ports)<br />
            {<br />
                TcpClient client = new TcpClient();<br />
                try<br />
                {<br />
                    IPAddress ip = new IPAddress(cursor);<br />
                    IPEndPoint endpoint = new IPEndPoint(ip, port);<br />
                    client.Connect(endpoint);</p>
<p>                    Console.WriteLine(&#8220;OK&#8221;);<br />
                }<br />
                catch (Exception e)<br />
                {<br />
                }<br />
            }</p>
<p>            Increment(cursor);<br />
        }<br />
    }<br />
}</p>
<p>[/csharp]</p>
<p><strong>开启多线程扫描</strong></p>
<p>如果运行这种代码，你会发现扫描速度实在是慢的难以忍受，原因就在于Connect函数阻塞的时间太长了，我们可以考虑使用多线程扫描。如果使用多线程扫描，上述代码要变动的地方其实不多。</p>
<p>1. 将DoScan丢到线程池中</p>
<p>[chsarp]<br />
ThreadPool.SetMaxThreads(256, 256);</p>
<p>for (int j = 0; j < 50; j++)<br />
{<br />
   ThreadPool.QueueUserWorkItem(this.DoScan, null);<br />
}<br />
[/csharp]</p>
<p>这里要注意，线程并不是越多越好，过多的线程会导致对网络的频繁访问，使得Connect出现非连接异常。说简单点就是扫描无法发现可用服务器。</p>
<p>2. 调整下DoScan，使其支持多线程：</p>
<pre class="brush: csharp;">
void DoScan()
{
    while (Compare(this.ipEnd, cursor) &gt; 0)
    {
        byte[] temp = new byte[4];

        // 多线程，获取一个IP以扫描
        Thread.BeginCriticalRegion();
        for (int i = 0; i &lt; 4; i++)
        {
            temp[i] = cursor[i];
        }

        Increment(cursor);
        Thread.EndCriticalRegion();

        if (Compare(temp, cursor) &lt; 0)
        {
            break;
        }

        foreach (int port in ports)
        {
            TcpClient client = new TcpClient();
            try
            {
                IPAddress ip = new IPAddress(cursor);
                IPEndPoint endpoint = new IPEndPoint(ip, port);
                client.Connect(endpoint);

                Console.WriteLine(&quot;OK&quot;);
            }
            catch (Exception e)
            {
            }
        }
    }
}
</pre>
<p>这里在进行线程同步时，使用的是临界区，这是用户态同步方式，切勿使用互斥量，事件等内核态同步方式，否则扫描速度会慢很多(状态切换的开销大概是1000个指令周期，50个线程切来切去，效率的损失可想而知)。</p>
<p><strong>增加扫描进度事件</strong></p>
<p>为了能够监控扫描进度，可以增加一个事件：</p>
<pre class="brush: csharp;">
delegate void StepForwardDelegate(double percent, string currentIP);

public event StepForwardDelegate OnStepForward;
</pre>
<p>在每次扫描完一个IP时，计算percent，然后触发这个事件。在监控界面中，以ProgressBar将扫描进度显示出来(不要忘记Invoke)</p>
<p><strong>扫描代理服务器</strong></p>
<p>ccProxy上网代理的默认端口是808，除了扫描这个端口是否打开外，我们还希望能够进一步确认是否可以通过这个代理来连接远端服务器。这个判断其实不难。</p>
<p>WebProxy p = new WebProxy();<br />
p.Address = new Uri("http://" + new IPAddress(cursor).ToString() + ":" + port.ToString());</p>
<p>上面代码创建了一个网络代理，cursor就是前面我讲到的扫描IP。有了这个代理以后，我们可以使用WebClient来测试是否可以正常下载网络数据：</p>
<p>WebClient wc = new WebClient();<br />
wc.Proxy = p;<br />
try<br />
{<br />
    byte[] bs = wc.DownloadData(http://baidu.com);</p>
<p>    // 验证成功，代理可以使用<br />
    flag = LogFlag.OK;<br />
}<br />
catch (Exception e)<br />
{<br />
}</p>
<p>上述我使用baidu作为目标站点，查看是否可以连接到外部网络。实际上这个验证目标最好是由用户在界面上输入来指定。</p>
<p>最后</p>
<p>1. 如果要扫代理服务器，建议将扫描结果分级： Fail表示不能连接；Pending表示端口连接成功，但无法通过这个代理访问外网；OK表示验证成功；</p>
<p>2. Pending有两种情况，一种是对方的808端口是干别的事情，不是代理服务，另外一种是对方在代理服务器上加了密码或者mac校验。如果扫到同一个IP的808和1080都是Pending，那基本可以确定对方开了代理服务，但加了访问限制。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2010/08/31/charp_port_scan.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows下使用内核对象进行线程同步</title>
		<link>http://www.soft-bin.com/html/2010/08/30/use_kernal_object_to_sync_thread.html</link>
		<comments>http://www.soft-bin.com/html/2010/08/30/use_kernal_object_to_sync_thread.html#comments</comments>
		<pubDate>Mon, 30 Aug 2010 09:00:13 +0000</pubDate>
		<dc:creator>luckzj</dc:creator>
				<category><![CDATA[Windows平台编程]]></category>

		<guid isPermaLink="false">http://www.soft-bin.com/?p=421</guid>
		<description><![CDATA[在多线程编程时，线程间的同步操作是非常重要，也是非常麻烦的。关于windows下的进程和线程，谈得比较多的是线程同步和进程间通信，而进程间的同步，其实和线程同步是有些类似的。对于线程间的通信，如果线程属于同一个进程，则可以直接通过共享进程资源的方式进行通信，如果两个线程从属于不同的进程，则线程通信实际上变成了进程间通信了。
因此，我们谈到多线程编程时，通常只说线程的同步以及进程的通信。
线程同步方式概述
线程的同步可以分为用户态同步和内核态同步。
用户态同步的方式即是使用互锁函数和临界区两种方式进行线程同步，这两种方式在前一篇文章 使用互锁函数和临界区(CriticalSection)实现线程同步 中已经做过介绍。在用户态下进行线程同步的好处在于速度快，使用方便。
内核态同步则是这篇文章要介绍的重点，即使用内核对象进行线程同步。使用内核对象进行线程同步，速度会比使用互锁函数和临界区要慢一些， 但好处在于内核对象可以用于跨进程的同步。原因很简单，内核对象是独立于进程存在的，由系统进行维护，我们可以创建一个内核对象，并在不同的进程中打开它，那么我们就可以使用这个内核对象进行跨进程的同步了。
在另外一个进程中打开内核对象，我们可以有两种思路，一种是利用父子进程间的继承关系，让子进程继承父进程的内核对象。另外一种思路则是创建内核对象时，为起指定一个名称，在另外一个进程中，只需要根据这个名称打开相应的内核对象即可。关于内核对象的更多操作，可以参考 Windows内核对象 一文。
有的内核对象会有两种状态，一种叫做已通知状态，一种叫做未通知状态。对于这种内核对象，我们可以使用等待函数，来等待其从未通知状态变为已通知状态。我们可以通过选择不同的等待函数以及不同的内核对象，来实现线程的同步。
等待函数
最常见的等待函数莫过于 WaitForSingleObject，其原型如下：

DWORD WaitForSingleObject(
    HANDLE hObject,    // 要等待的内核对象句柄
    DWORD dwMilliseconds);  // 等待时间，可以设置为 INFINITE表示永久等待


WaitForSingleObject函数返回值有如下几种：
WAIT_OBJECT_0： 等待完成，内核对象变为已通知
WAIT_TIMEOUT：  超时
WAIT_FAILED：     函数调用错误，有可能是hObject无效

我们也可以使用 WaitForMultipleObjects 函数来等待多个内核对象，这正如 select函数一样，其原型为：

DWORD WaitForMultipleObjects(
    DWORD dwCount,      // phObjects 中内核对象个数
    [...]]]></description>
			<content:encoded><![CDATA[<p>在多线程编程时，线程间的同步操作是非常重要，也是非常麻烦的。关于windows下的进程和线程，谈得比较多的是线程同步和进程间通信，而进程间的同步，其实和线程同步是有些类似的。对于线程间的通信，如果线程属于同一个进程，则可以直接通过共享进程资源的方式进行通信，如果两个线程从属于不同的进程，则线程通信实际上变成了进程间通信了。</p>
<p>因此，我们谈到多线程编程时，通常只说线程的同步以及进程的通信。</p>
<p><strong>线程同步方式概述</strong></p>
<p>线程的同步可以分为用户态同步和内核态同步。</p>
<p>用户态同步的方式即是使用互锁函数和临界区两种方式进行线程同步，这两种方式在前一篇文章 <a href="http://www.soft-bin.com/html/2010/08/12/thread_sync_critical_section.html">使用互锁函数和临界区(CriticalSection)实现线程同步</a> 中已经做过介绍。在用户态下进行线程同步的好处在于速度快，使用方便。</p>
<p>内核态同步则是这篇文章要介绍的重点，即使用内核对象进行线程同步。使用内核对象进行线程同步，速度会比使用互锁函数和临界区要慢一些， 但好处在于内核对象可以用于跨进程的同步。原因很简单，内核对象是独立于进程存在的，由系统进行维护，我们可以创建一个内核对象，并在不同的进程中打开它，那么我们就可以使用这个内核对象进行跨进程的同步了。</p>
<p>在另外一个进程中打开内核对象，我们可以有两种思路，一种是利用父子进程间的继承关系，让子进程继承父进程的内核对象。另外一种思路则是创建内核对象时，为起指定一个名称，在另外一个进程中，只需要根据这个名称打开相应的内核对象即可。关于内核对象的更多操作，可以参考 <a href="http://www.soft-bin.com/html/2010/07/29/windows_kernel_object.html">Windows内核对象</a> 一文。</p>
<p>有的内核对象会有两种状态，一种叫做已通知状态，一种叫做未通知状态。对于这种内核对象，我们可以使用等待函数，来等待其从未通知状态变为已通知状态。我们可以通过选择不同的等待函数以及不同的内核对象，来实现线程的同步。</p>
<p><strong>等待函数</strong></p>
<p>最常见的等待函数莫过于 WaitForSingleObject，其原型如下：</p>
<pre class="brush: cpp;">
DWORD WaitForSingleObject(
    HANDLE hObject,    // 要等待的内核对象句柄
    DWORD dwMilliseconds);  // 等待时间，可以设置为 INFINITE表示永久等待
</pre>
<p><span id="more-421"></span><br />
WaitForSingleObject函数返回值有如下几种：<br />
WAIT_OBJECT_0： 等待完成，内核对象变为已通知<br />
WAIT_TIMEOUT：  超时<br />
WAIT_FAILED：     函数调用错误，有可能是hObject无效</p>
<p><!--more--><br />
我们也可以使用 WaitForMultipleObjects 函数来等待多个内核对象，这正如 select函数一样，其原型为：</p>
<pre class="brush: cpp;">
DWORD WaitForMultipleObjects(
    DWORD dwCount,      // phObjects 中内核对象个数
    CONST HANDLE* phObjects,  // 内核对象数组
    BOOL fWaitAll,    // TRUE表示等待所有内核对象都变为已通知，FALSE表示等待任意内核对象变为已通知
    DWORD dwMilliseconds);
</pre>
<p>函数返回值包括如下含义：<br />
WAIT_FAILED: 调用失败<br />
WAIT_TIMEOUT：超时，但等待的条件没有满足<br />
WAIT_OBJECT_0 +　N： hObject[N] 这个句柄已经变为已通知状态</p>
<p>WaitForSingleObject和WaitForMultipleObjects是使用得最多的两个等待函数，除此之外，还有其他的一些等待函数，用以实现特殊的目的。在这里，也一并进行简单介绍。</p>
<p>WaitForInputIdle</p>
<pre class="brush: cpp;">
DWORD WaitForInputIdle(
    HANDLE hProcess,
    DWORD dwMilliseconds
    );
</pre>
<p>这个函数等待 hProcess 代表的进程第一个窗口的线程中，已经没有尚未处理的输入才返回。这句话有些绕，大致可以理解为等待进程初始化完成。试想如果我们想在父进程中获取子进程的窗口，如果子进程没有初始化完毕，则父进程获取窗口必然失败，因此，在父进程创建子进程以后，可以调用 WaitForInputIdle等待子进程初始化完成。</p>
<p>MsgWaitForMultipleObjects(Ex)</p>
<pre class="brush: cpp;">
DWORD MsgWaitForMultipleObjects(
    DWORD dwCount,
    PHANDLE phObjects,
    BOOL fWaitAll,
    DWORD dwMilliseconds,
    DWORD dwWakeMask);

DWORD MsgWaitForMultipleObjectsEx(
    DWORD dwCount,
    PHANDLE phObjects,
    DWORD dwMilliseconds,
    DWORD dwWakeMask,
    DWORD dwFlags
    );
</pre>
<p>这两个函数与WaitForMultipleObjects非常相似，不同的是，WaitForMultipleObjects和WaitForSingleObject两个函数在等待对象满足要求之前，会一直阻塞，而MsgWaitForMultipleObjects(Ex)函数在阻塞的过程中，如果线程中有需要处理的窗口消息，这些要处理的消息将可以被响应。</p>
<p>也就是说，在窗口线程中，应当调用MsgWaitForMultipleObjects(Ex)函数，而不是WaitForMultipleObjects，否则窗口可能会因为长时间无法响应ON_PAINT消息而导致界面卡死。</p>
<p>SingleObjectAndWait</p>
<pre class="brush: cpp;">
DWORD  SingleObjectAndWait(
    HANDLE hObjectToSignal,
    HANDLE hObjectToWaitOn,
    DWORD dwMilliseconds,
    BOOL fAlertable);
</pre>
<p>SingleObjectAndWait 函数以原子的方式执行如下操作：</p>
<p>将 hObjectToSignal 设置为已通知状态，等待 hObjectToWaitOn</p>
<p>参数 dwMillliseconds 表示等待超时的时间， fAlertable表示线程等待时，该线程是否应该能够处理任何已经排队的异步过程调用。</p>
<p><strong>可以用作等待的内核对象</strong></p>
<p>可以等待的内核对象包括：</p>
<p>进程，线程，事件，作业，文件修改通知，可等待定时器，文件，信标，互斥对象，控制台输入。下面将对比较常用的几种等待对象进行介绍。</p>
<p><strong>进程，线程</strong></p>
<p>进程和线程在运行时，其状态为未通知状态，当进程和线程结束时，其状态就变为已通知。我们可以使用等待函数来等待进程或线程退出。</p>
<p><strong>事件</strong></p>
<p>事件内核对象是最基本的内核对象，其包含一个引用计数，一个用于指明该事件是自动重置事件还是人工重置事件的bool变量，一个指明该事件处于已通知还是未通知状态的bool变量。</p>
<p>自动重置事件是指在事件被某一等待函数等待成功后，会立即自动变为未通知状态。人工重置事件则需要手工调用ResetEvent才会被重新置为未通知状态。这两类事件的区别很明显，在有多个线程等待事件时，自动重置事件会保证只有一个线程会得以运行，而人工重置事件则允许多个线程同时被激活。</p>
<p>跟事件相关的API函数包括以下几个：</p>
<pre class="brush: cpp;">
// 创建一个事件内核对象
HANDLE CreateEvent(
    PSECURITY_ATTRIBUTES psa,  // 内核对象安全属性
   BOOL fManualRest,   // 是否是手工重置事件
   BOOL fInitialState,   // 初始状态
   PCTSTR pszname     // 对象名称，命名后，可在其他进程中打开
   );

HANDLE OpenEvent(
    DWORD fdwAccess,  // 需要的权限，详情查询MSDN
    BOOL  fInherit,        // 是否可被继承
   PCTSTR pszName     // 要打开的对象的名称
);

// 将事件设置为已通知状态
BOOL SetEvent(HANDLE hEvent);

// 将事件设置为未通知状态
BOOL ResetEvent(HANDLE hEvent);

// 将事件设置为已通知，然后立即设置为未通知状态
BOOL PulseEvent(HANDLE hEvent);
</pre>
<p><strong>信标内核对象 Semaphore</strong></p>
<p>Semaphore用于对资源进行计数，其使用规则如下：<br />
1. 如果当前资源数量大于0，则发出信标信号<br />
2. 如果资源数量是0，则不发出信标号<br />
3. 系统不允许当前资源为负数<br />
4. 当前资源数量不能大于最大资源数</p>
<p>与Semaphore相关的API函数包括：</p>
<pre class="brush: cpp;">
HANDLE CreateSemaphore(
    PSECURITY_ATTRIBUTES psa,   // 内核对象安全属性
   LONG lInitialCount,   // 初始数量
   LONG lMaximumCount,  // 最大数量
   PCTSTR pszName  // 名称
)

HANDLE OpenSemaphore(
    DWORD dwAccess,      // 希望取得的权限
   bInheritHandle,           // 继承性
   PCTSTR pszName       // 名称
);

BOOL ReleaseSemaphore(
    HANDLE hSem,
    LONG lReleaseCount,
    PLONG lpPreviousCount   // 返回之前的资源数量
);
</pre>
<p>等待函数在获取到semaphore后，将semaphore资源数量减1。在新的资源可用时，需要调用ReleaseSemaphore增加资源数量。</p>
<p><strong>互斥量Mutex</strong></p>
<p>互斥量是我们使用得比较多的几种同步对象之一。与其他用于同步的内核对象不同，互斥量内核对象中还包含一个线程ID，用以标识当前哪个线程拥有该互斥对象。同一个线程可以多次拥有同一个互斥对象，拥有的次数也会保存在互斥对象当中。</p>
<p>创建或者打开互斥对象可以使用以下两个API函数：</p>
<pre class="brush: cpp;">
HANDLE CreateMutex(
    PSECURITY_ATTRIBUTES psa,
    BOOL fInitialOwner,
    PCTSTR pszName
);

HANDLE OpenMutex(
    DWORD dwAccess,
    BOOL bInheritHandle,
    PCTSTR pszName
);
</pre>
<p>在线程等待到互斥对象时，也就拥有了这个互斥对象，线程必须保证在互斥量使用完毕后，及时地释放互斥量，避免造成死锁。</p>
<pre class="brush: cpp;">
BOOL ReleaseMutex(HANDLE hMutex);
</pre>
<p>互斥量中保存了线程拥有该互斥量的次数，只有当拥有次数变为0时，互斥量才可以重新被其他线程所拥有。因此，我们在使用互斥量时，必须保证等待函数和ReleaseMutex是一一对应的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.soft-bin.com/html/2010/08/30/use_kernal_object_to_sync_thread.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

