﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-#ant</title><link>http://www.cppblog.com/ant/</link><description>The dreams in which I'm dying are the best I've ever had...</description><language>zh-cn</language><lastBuildDate>Sun, 06 Jul 2008 20:47:29 GMT</lastBuildDate><pubDate>Sun, 06 Jul 2008 20:47:29 GMT</pubDate><ttl>60</ttl><item><title>strlen源码剖析</title><link>http://www.cppblog.com/ant/archive/2007/10/12/32886.html</link><dc:creator>蚂蚁终结者</dc:creator><author>蚂蚁终结者</author><pubDate>Fri, 12 Oct 2007 05:19:00 GMT</pubDate><guid>http://www.cppblog.com/ant/archive/2007/10/12/32886.html</guid><wfw:comment>http://www.cppblog.com/ant/comments/32886.html</wfw:comment><comments>http://www.cppblog.com/ant/archive/2007/10/12/32886.html#Feedback</comments><slash:comments>24</slash:comments><wfw:commentRss>http://www.cppblog.com/ant/comments/commentRss/32886.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ant/services/trackbacks/32886.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 学习高效编程的有效途径之一就是阅读高手写的源代码，CRT(C/C++ Runtime Library)作为底层的函数库，实现必然高效。恰好手中就有glibc和VC的CRT源代码，于是挑了一个相对简单的函数strlen研究了一下，并对各种实现作了简单的效率测试。strlen的函数原形如下：      size_t strlen(const char *str);strlen返回str中字符的个数，其...&nbsp;&nbsp;<a href='http://www.cppblog.com/ant/archive/2007/10/12/32886.html'>阅读全文</a><img src ="http://www.cppblog.com/ant/aggbug/32886.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ant/" target="_blank">蚂蚁终结者</a> 2007-10-12 13:19 <a href="http://www.cppblog.com/ant/archive/2007/10/12/32886.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TEA加密算法的C/C++实现</title><link>http://www.cppblog.com/ant/archive/2007/10/12/31326.html</link><dc:creator>蚂蚁终结者</dc:creator><author>蚂蚁终结者</author><pubDate>Fri, 12 Oct 2007 05:17:00 GMT</pubDate><guid>http://www.cppblog.com/ant/archive/2007/10/12/31326.html</guid><wfw:comment>http://www.cppblog.com/ant/comments/31326.html</wfw:comment><comments>http://www.cppblog.com/ant/archive/2007/10/12/31326.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/ant/comments/commentRss/31326.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ant/services/trackbacks/31326.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: TEA(Tiny Encryption Algorithm)		是一种简单高效的加密算法，以加密解密速度快，实现简单著称。算法真的很简单，TEA算法每一次可以操作64-bit(8-byte)，采用128-bit(16-byte)作为key，算法采用迭代的形式，推荐的迭代轮数是64轮，最少32轮。目前我只知道QQ一直用的是16轮TEA。没什么好说的，先给出C语言的源代码(默认是32轮)： 1 v...&nbsp;&nbsp;<a href='http://www.cppblog.com/ant/archive/2007/10/12/31326.html'>阅读全文</a><img src ="http://www.cppblog.com/ant/aggbug/31326.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ant/" target="_blank">蚂蚁终结者</a> 2007-10-12 13:17 <a href="http://www.cppblog.com/ant/archive/2007/10/12/31326.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Win32 Service的简单封装</title><link>http://www.cppblog.com/ant/archive/2007/09/24/32769.html</link><dc:creator>蚂蚁终结者</dc:creator><author>蚂蚁终结者</author><pubDate>Mon, 24 Sep 2007 05:01:00 GMT</pubDate><guid>http://www.cppblog.com/ant/archive/2007/09/24/32769.html</guid><wfw:comment>http://www.cppblog.com/ant/comments/32769.html</wfw:comment><comments>http://www.cppblog.com/ant/archive/2007/09/24/32769.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/ant/comments/commentRss/32769.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ant/services/trackbacks/32769.html</trackback:ping><description><![CDATA[<p>前段时间学习Windows程序设计，刚好学到Win32 Service，于是写了两个简单的类：BaseService和ServiceCtrl。虽然功能比较简单，但是也能适用于大多数情况。下面介绍一下简单用法，如果你刚好需要写一些简单的服务程序，这两个类也许能派上用场：<br><br><span style="FONT-SIZE: 14pt"><strong style="COLOR: #993366">1. BaseService<br></strong></span><em style="COLOR: #333399">BaseService.h<br></em></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">#ifndef&nbsp;BASE_SERVICE_H<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">#define&nbsp;BASE_SERVICE_H<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;BaseService&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;explicit&nbsp;BaseService(LPCTSTR&nbsp;szServiceName,<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwServiceType&nbsp;</span><span style="COLOR: #000000">=</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;SERVICE_WIN32_OWN_PROCESS,<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwStartType&nbsp;</span><span style="COLOR: #000000">=</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;SERVICE_AUTO_START);<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #000000">~</span></font> <font face="Courier New"><span style="COLOR: #000000">BaseService()&nbsp;{}<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;ParseStandardArgs(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;argv[]);<br></span><span style="COLOR: #008080">11</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;IsInstalled();<br></span><span style="COLOR: #008080">12</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;Install();<br></span><span style="COLOR: #008080">13</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;Uninstall();<br></span><span style="COLOR: #008080">14</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;Start();<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Run()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span></font> <font face="Courier New"><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;bool&nbsp;OnInitialize()&nbsp;{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span></font> <font face="Courier New"><span style="COLOR: #000000">;&nbsp;}<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;OnStop()&nbsp;{}<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;OnPause()&nbsp;{}<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;OnContinue()&nbsp;{}<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;OnInterrogate()&nbsp;{}<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;OnShutdown()&nbsp;{}<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;OnUserControl(DWORD&nbsp;dwControl)&nbsp;{}<br></span><span style="COLOR: #008080">24</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;...<br></span><span style="COLOR: #008080">25</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">};<br></span><span style="COLOR: #008080">26</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000">#endif</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">BASE_SERVICE_H</span><span style="COLOR: #008000">*/</span></font> </div>
<p>要实现自己的服务类只需从BaseService继承并且Override相关的virtual函数即可，下面示范一个BeepService类，该服务只是简单地每隔2秒beep一下，为了简单所有代码均放在.h文件中：<br><em style="COLOR: #333399">BeepService.h</em></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">#ifndef&nbsp;BEEP_SERVICE_H<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">#define&nbsp;BEEP_SERVICE_H<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">BaseService.h</span><span style="COLOR: #000000">"</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;5</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;BeepService&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;BaseService&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BeepService(LPCTSTR&nbsp;szServiceName)<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:BaseService(szServiceName)<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,m_bPaused(</span><span style="COLOR: #0000ff">false</span></font> <font face="Courier New"><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,m_bRunning(</span><span style="COLOR: #0000ff">false</span></font> <font face="Courier New"><span style="COLOR: #000000">)&nbsp;{}<br></span><span style="COLOR: #008080">12</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnStop()&nbsp;{&nbsp;m_bRunning&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span></font> <font face="Courier New"><span style="COLOR: #000000">;&nbsp;}<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnPause()&nbsp;{&nbsp;m_bPaused&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span></font> <font face="Courier New"><span style="COLOR: #000000">;&nbsp;}<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnContinue()&nbsp;{&nbsp;m_bPaused&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span></font> <font face="Courier New"><span style="COLOR: #000000">;&nbsp;}<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Run()&nbsp;{<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_bRunning&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span></font> <font face="Courier New"><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;(m_bRunning)&nbsp;{<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">!</span></font> <font face="Courier New"><span style="COLOR: #000000">m_bPaused)<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Beep(</span><span style="COLOR: #000000">800</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">800</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">2000</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">22</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">23</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">volatile</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;bool&nbsp;m_bPaused;<br></span><span style="COLOR: #008080">26</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">volatile</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;bool&nbsp;m_bRunning;<br></span><span style="COLOR: #008080">27</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">};<br></span><span style="COLOR: #008080">28</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">29</span>&nbsp;<span style="COLOR: #000000">#endif</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">BEEP_SERVICE_H</span><span style="COLOR: #008000">*/</span></font> </div>
<p>通常来说只须要Override上面的4个virtual函数就OK了：<br>在<em>Run()</em>中进行实际的工作，<em>OnStop(),OnPause(),OnContinue()</em>则是为了响应Service Control Manager的控制。<br><em style="COLOR: #333399"><br>test.cpp<br></em></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">tchar.h</span><span style="COLOR: #000000">&gt;</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">BeepService.h</span><span style="COLOR: #000000">"</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;5</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span></font> <font face="Courier New"><span style="COLOR: #000000">argv[])&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BeepService&nbsp;beepService(_T(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">BeepService</span><span style="COLOR: #000000">"</span></font> <font face="Courier New"><span style="COLOR: #000000">));<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">!</span></font> <font face="Courier New"><span style="COLOR: #000000">beepService.ParseStandardArgs(argc,&nbsp;argv))&nbsp;{<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;(beepService.IsInstalled())&nbsp;{<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">!</span></font> <font face="Courier New"><span style="COLOR: #000000">beepService.Start())<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">The&nbsp;service&nbsp;can&nbsp;not&nbsp;run&nbsp;from&nbsp;command&nbsp;line.\n</span><span style="COLOR: #000000">"</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="COLOR: #0000ff">else</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">The&nbsp;service&nbsp;is&nbsp;not&nbsp;installed,&nbsp;</span><span style="COLOR: #000000">"</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">use&nbsp;\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">s&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">i\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;to&nbsp;install.\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;argv[</span><span style="COLOR: #000000">0</span></font> <font face="Courier New"><span style="COLOR: #000000">]);<br></span><span style="COLOR: #008080">16</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">17</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span></font> <font face="Courier New"><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">}</span></font> </div>
<p>假设编译后生成的exe文件为beep.exe，则在命令行中可以如下使用：<br><em style="COLOR: #333399">(1). beep -i&nbsp;&nbsp;&nbsp; 安装service(安装以后系统运行时会自动启动)<br>(2). beep -u&nbsp;&nbsp;&nbsp;卸载service(如果service正在运行，则先停止service再卸载)<br></em>BaseServiced&nbsp;的ParseStandardArgs正是用来解析上述两个命令。<br><br><span style="FONT-SIZE: 14pt"><strong style="COLOR: #993366">2. ServiceCtrl<br></strong></span>虽然Windows自带的Service Control Manager可以控制服务程序，但是很多时候我们都需要用代码控制，这就用到ServiceCtrl类，该类的接口如下：<br><em style="COLOR: #333399">ServiceCtrl.h</em></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">#ifndef&nbsp;SERVICE_CTRL_H<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">#define&nbsp;SERVICE_CTRL_H<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;ServiceCtrl&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;ServiceCtrl(LPCTSTR&nbsp;szServiceName);<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span></font> <font face="Courier New"><span style="COLOR: #000000">ServiceCtrl();<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;Start();<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;Pause();<br></span><span style="COLOR: #008080">10</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;Continue();<br></span><span style="COLOR: #008080">11</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;Stop();<br></span><span style="COLOR: #008080">12</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;Interrogate();<br></span><span style="COLOR: #008080">13</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;UserControl(DWORD&nbsp;dwControl);<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;State()&nbsp;</span><span style="COLOR: #0000ff">const</span></font> <font face="Courier New"><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">15</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;...<br></span><span style="COLOR: #008080">16</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">};<br></span><span style="COLOR: #008080">17</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">#endif</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">SERVICE_CTRL_H</span><span style="COLOR: #008000">*/</span></font> </div>
<p>接口比较直观没什么好说的，看下面的示例代码：<br><em><font color=#333399>test.cpp</font></em></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">tchar.h</span><span style="COLOR: #000000">&gt;</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">exception</span><span style="COLOR: #000000">&gt;</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">BeepService.h</span><span style="COLOR: #000000">"</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ServiceCtrl.h</span><span style="COLOR: #000000">"</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;7</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span></font> <font face="Courier New"><span style="COLOR: #000000">argv[])&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServiceCtrl&nbsp;servCtrl(_T(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">BeepService</span><span style="COLOR: #000000">"</span></font> <font face="Courier New"><span style="COLOR: #000000">));<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(servCtrl.State()&nbsp;</span><span style="COLOR: #000000">!=</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;SERVICE_STOPPED)&nbsp;{<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Service&nbsp;already&nbsp;started.\n</span><span style="COLOR: #000000">"</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="COLOR: #0000ff">else</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">15</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;servCtrl.Start();<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Start.\n</span><span style="COLOR: #000000">"</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">6000</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">18</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;servCtrl.Pause();<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Pause.\n</span><span style="COLOR: #000000">"</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">6000</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">21</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;servCtrl.Continue();<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Continue.\n</span><span style="COLOR: #000000">"</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">6000</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">24</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;servCtrl.Stop();<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Stop.\n</span><span style="COLOR: #000000">"</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">26</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(std::exception&nbsp;</span><span style="COLOR: #000000">&amp;</span></font> <font face="Courier New"><span style="COLOR: #000000">e)&nbsp;{<br></span><span style="COLOR: #008080">28</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%s\n</span><span style="COLOR: #000000">"</span></font> <font face="Courier New"><span style="COLOR: #000000">,&nbsp;e.what());<br></span><span style="COLOR: #008080">29</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">30</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span></font> <font face="Courier New"><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">31</span>&nbsp;<span style="COLOR: #000000">}</span></font> </div>
<br>源代码：<a title=点击下载 href="http://www.cppblog.com/Files/ant/Service.rar">点击下载</a><br>
<img src ="http://www.cppblog.com/ant/aggbug/32769.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ant/" target="_blank">蚂蚁终结者</a> 2007-09-24 13:01 <a href="http://www.cppblog.com/ant/archive/2007/09/24/32769.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MD5算法的C++实现</title><link>http://www.cppblog.com/ant/archive/2007/09/11/31886.html</link><dc:creator>蚂蚁终结者</dc:creator><author>蚂蚁终结者</author><pubDate>Tue, 11 Sep 2007 04:20:00 GMT</pubDate><guid>http://www.cppblog.com/ant/archive/2007/09/11/31886.html</guid><wfw:comment>http://www.cppblog.com/ant/comments/31886.html</wfw:comment><comments>http://www.cppblog.com/ant/archive/2007/09/11/31886.html#Feedback</comments><slash:comments>29</slash:comments><wfw:commentRss>http://www.cppblog.com/ant/comments/commentRss/31886.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ant/services/trackbacks/31886.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1. Introduction		MD5算法是一种消息摘要算法(Message Digest Algorithm)，此算法以任意长度的信息(message)作为输入进行计算，产生一个128-bit(16-byte)的指纹或报文摘要(fingerprint or message digest)。两个不同的message产生相同message digest的几率相当小，从一个给定的message ...&nbsp;&nbsp;<a href='http://www.cppblog.com/ant/archive/2007/09/11/31886.html'>阅读全文</a><img src ="http://www.cppblog.com/ant/aggbug/31886.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ant/" target="_blank">蚂蚁终结者</a> 2007-09-11 12:20 <a href="http://www.cppblog.com/ant/archive/2007/09/11/31886.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>非完美C++ Singleton实现[2]</title><link>http://www.cppblog.com/ant/archive/2007/09/07/31786.html</link><dc:creator>蚂蚁终结者</dc:creator><author>蚂蚁终结者</author><pubDate>Fri, 07 Sep 2007 15:22:00 GMT</pubDate><guid>http://www.cppblog.com/ant/archive/2007/09/07/31786.html</guid><wfw:comment>http://www.cppblog.com/ant/comments/31786.html</wfw:comment><comments>http://www.cppblog.com/ant/archive/2007/09/07/31786.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.cppblog.com/ant/comments/commentRss/31786.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ant/services/trackbacks/31786.html</trackback:ping><description><![CDATA[
		<strong style="FONT-SIZE: 14pt; COLOR: #993366">4.解决多线程问题<br /></strong>上一篇实现的Singleton只能在单线程环境中使用，在多线程环境中会出现很多问题，看Instance()实现代码：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">1</span> <span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Singleton</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000"> Instance() {<br /></span><span style="COLOR: #008080">2</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> _instance) { </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">1</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">3</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">        _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Singleton(); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">2</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">4</span> <span style="COLOR: #008000"></span></font><font face="Courier New"><span style="COLOR: #000000">        atexit(Destroy);<br /></span><span style="COLOR: #008080">5</span> </font><font face="Courier New"><span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080">6</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_instance; </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">3</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">7</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">}</span></font></div>考虑如下情况：线程一调用Instance()，进入//1，0 == _instance 返回true，线程一于是进入//2。这时候线程一被挂起，线程二开始执行，线程二调用Instance()，进入//1，发现0 == _instance 仍然返回true，线程二于是也进入//2，线程二继续执行到//3直到返回。这时候线程一被唤醒，继续从//2开始执行，这将会覆盖线程二创建的_instance，线程一继续执行到//3直到返回...<br /><br />解决方法很简单，引入相关同步对象(synchronization object)就行了，例如在win32平台下可以如下实现：<br /><em style="COLOR: #333399">synobj.h<br /></em><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080"> 1</span> </font><font face="Courier New"><span style="COLOR: #000000">#ifndef SYNOBJ_H<br /></span><span style="COLOR: #008080"> 2</span> </font><font face="Courier New"><span style="COLOR: #000000">#define SYNOBJ_H<br /></span><span style="COLOR: #008080"> 3</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 4</span> <span style="COLOR: #000000">#include </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span></font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 5</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 6</span> </font><font face="Courier New"><span style="COLOR: #000000">#define CLASS_UNCOPYABLE(classname) \<br /></span><span style="COLOR: #008080"> 7</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">private</span></font><font face="Courier New"><span style="COLOR: #000000">: \<br /></span><span style="COLOR: #008080"> 8</span> <span style="COLOR: #000000">    classname(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> classname</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000">); \<br /></span><span style="COLOR: #008080"> 9</span> <span style="COLOR: #000000">    classname</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> operator</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> classname</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000">);<br /></span><span style="COLOR: #008080">10</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">11</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span></font><font face="Courier New"><span style="COLOR: #000000"> Mutex {<br /></span><span style="COLOR: #008080">12</span> </font><font face="Courier New"><span style="COLOR: #000000">    CLASS_UNCOPYABLE(Mutex)<br /></span><span style="COLOR: #008080">13</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">14</span> <span style="COLOR: #000000">    Mutex() :_cs() { InitializeCriticalSection(</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000">_cs); }<br /></span><span style="COLOR: #008080">15</span> <span style="COLOR: #000000">    </span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">Mutex() { DeleteCriticalSection(</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000">_cs); }<br /></span><span style="COLOR: #008080">16</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> lock() { EnterCriticalSection(</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000">_cs); }<br /></span><span style="COLOR: #008080">17</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> unlock() { LeaveCriticalSection(</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000">_cs); }<br /></span><span style="COLOR: #008080">18</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">19</span> </font><font face="Courier New"><span style="COLOR: #000000">    CRITICAL_SECTION _cs;<br /></span><span style="COLOR: #008080">20</span> </font><font face="Courier New"><span style="COLOR: #000000">};<br /></span><span style="COLOR: #008080">21</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">22</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span></font><font face="Courier New"><span style="COLOR: #000000"> Lock {<br /></span><span style="COLOR: #008080">23</span> </font><font face="Courier New"><span style="COLOR: #000000">    CLASS_UNCOPYABLE(Lock)<br /></span><span style="COLOR: #008080">24</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">25</span> <span style="COLOR: #000000">    explicit Lock(Mutex</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000"> cs) :_cs(cs) { _cs.lock(); }<br /></span><span style="COLOR: #008080">26</span> <span style="COLOR: #000000">    </span><span style="COLOR: #000000">~</span></font><font face="Courier New"><span style="COLOR: #000000">Lock() { _cs.unlock(); }<br /></span><span style="COLOR: #008080">27</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">28</span> <span style="COLOR: #000000">    Mutex</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000"> _cs;<br /></span><span style="COLOR: #008080">29</span> </font><font face="Courier New"><span style="COLOR: #000000">};<br /></span><span style="COLOR: #008080">30</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">31</span> <span style="COLOR: #000000">#endif</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">SYNOBJ_H</span><span style="COLOR: #008000">*/</span></font></div><br />有了同步对象很容易就能够写出如下代码：<br /><em style="COLOR: #333399">singleton.h<br /></em><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080"> 1</span> </font><font face="Courier New"><span style="COLOR: #000000">#ifndef SINGLETON_H<br /></span><span style="COLOR: #008080"> 2</span> </font><font face="Courier New"><span style="COLOR: #000000">#define SINGLETON_H<br /></span><span style="COLOR: #008080"> 3</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 4</span> <span style="COLOR: #000000">#include </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">synobj.h</span><span style="COLOR: #000000">"</span></font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 5</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 6</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span></font><font face="Courier New"><span style="COLOR: #000000"> Singleton {<br /></span><span style="COLOR: #008080"> 7</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080"> 8</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> Instance() { </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Unique point of access</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 9</span> <span style="COLOR: #008000"></span></font><font face="Courier New"><span style="COLOR: #000000">        Lock lock(_mutex);<br /></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">==</span></font><font face="Courier New"><span style="COLOR: #000000"> _instance) {<br /></span><span style="COLOR: #008080">11</span> <span style="COLOR: #000000">            _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span></font><font face="Courier New"><span style="COLOR: #000000"> Singleton();<br /></span><span style="COLOR: #008080">12</span> <span style="COLOR: #000000">            atexit(Destroy); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Register Destroy function</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">13</span> <span style="COLOR: #008000"></span></font><font face="Courier New"><span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">14</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span></font><font face="Courier New"><span style="COLOR: #000000">_instance;<br /></span><span style="COLOR: #008080">15</span> </font><font face="Courier New"><span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080">16</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">void</span></font><font face="Courier New"><span style="COLOR: #000000"> DoSomething(){}<br /></span><span style="COLOR: #008080">17</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">18</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> Destroy() { </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Destroy the only instance</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">19</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( _instance </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span></font><font face="Courier New"><span style="COLOR: #000000"> ) {<br /></span><span style="COLOR: #008080">20</span> </font><font face="Courier New"><span style="COLOR: #000000">            delete _instance;<br /></span><span style="COLOR: #008080">21</span> <span style="COLOR: #000000">            _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span></font><font face="Courier New"><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080">22</span> </font><font face="Courier New"><span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">23</span> </font><font face="Courier New"><span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080">24</span> <span style="COLOR: #000000">    Singleton(){} </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Prevent clients from creating a new Singleton</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">25</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">    </span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">Singleton(){} </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Prevent clients from deleting a Singleton</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">26</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">    Singleton(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Prevent clients from copying a Singleton</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">27</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">    Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> operator</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> Singleton</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000">);<br /></span><span style="COLOR: #008080">28</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">29</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span></font><font face="Courier New"><span style="COLOR: #000000"> Mutex _mutex;<br /></span><span style="COLOR: #008080">30</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Singleton </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_instance; </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> The one and only instance</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">31</span> <span style="COLOR: #008000"></span></font><font face="Courier New"><span style="COLOR: #000000">};<br /></span><span style="COLOR: #008080">32</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">33</span> <span style="COLOR: #000000">#endif</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">SINGLETON_H</span><span style="COLOR: #008000">*/</span></font></div><br /><em style="COLOR: #333399">singleton.cpp<br /></em><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">1</span> <span style="COLOR: #000000">#include </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">singleton.h</span><span style="COLOR: #000000">"</span></font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">2</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">3</span> </font><font face="Courier New"><span style="COLOR: #000000">Mutex Singleton::_mutex;<br /></span><span style="COLOR: #008080">4</span> <span style="COLOR: #000000">Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Singleton::_instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;</span></font></div>现在的Singleton虽然多线程安全，性能却受到了影响。从Instance()中可以看到，实际上仅仅当0 == _instance为true时才需要Lock。你很容易就写出如下代码：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">1</span> <span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Singleton</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000"> Instance() {<br /></span><span style="COLOR: #008080">2</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">==</span></font><font face="Courier New"><span style="COLOR: #000000"> _instance) {<br /></span><span style="COLOR: #008080">3</span> </font><font face="Courier New"><span style="COLOR: #000000">        Lock lock(_mutex);<br /></span><span style="COLOR: #008080">4</span> <span style="COLOR: #000000">        _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span></font><font face="Courier New"><span style="COLOR: #000000"> Singleton();<br /></span><span style="COLOR: #008080">5</span> </font><font face="Courier New"><span style="COLOR: #000000">        atexit(Destroy);<br /></span><span style="COLOR: #008080">6</span> </font><font face="Courier New"><span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080">7</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span></font><font face="Courier New"><span style="COLOR: #000000">_instance;<br /></span><span style="COLOR: #008080">8</span> <span style="COLOR: #000000">}</span></font></div>但是这样还是会产生竞争条件(race condition)，一种广为人知的做法是使用所谓的Double-Checked Locking：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080"> 1</span> <span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Singleton</span><span style="COLOR: #000000">&amp;</span></font><font face="Courier New"><span style="COLOR: #000000"> Instance() {<br /></span><span style="COLOR: #008080"> 2</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">==</span></font><font face="Courier New"><span style="COLOR: #000000"> _instance) {<br /></span><span style="COLOR: #008080"> 3</span> </font><font face="Courier New"><span style="COLOR: #000000">        Lock lock(_mutex);<br /></span><span style="COLOR: #008080"> 4</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">==</span></font><font face="Courier New"><span style="COLOR: #000000"> _instance) {<br /></span><span style="COLOR: #008080"> 5</span> <span style="COLOR: #000000">            _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span></font><font face="Courier New"><span style="COLOR: #000000"> Singleton();<br /></span><span style="COLOR: #008080"> 6</span> </font><font face="Courier New"><span style="COLOR: #000000">            atexit(Destroy);<br /></span><span style="COLOR: #008080"> 7</span> </font><font face="Courier New"><span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080"> 8</span> </font><font face="Courier New"><span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080"> 9</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span></font><font face="Courier New"><span style="COLOR: #000000">_instance;<br /></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000">}</span></font></div><span style="COLOR: #333399"><em>Double-Checked Locking</em></span>机制看起来像是一个完美的解决方案，但是在某些条件下仍然不行。简单的说，编译器为了效率可能会重排指令的执行顺序(<span style="COLOR: #333399"><em>compiler-based reorderings</em></span>)。看这一行代码：<br /><br /><font face="Courier New">_instance <span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span></font><span style="COLOR: #000000"><font face="Courier New"> Singleton();</font><br /><br />在编译器未优化的情况下顺序如下：<br /><span style="COLOR: #993366">1.new operator分配适当的内存；<br />2.在分配的内存上构造Singleton对象；<br />3.内存地址赋值给_instance。</span><br /><br />但是当编译器优化后执行顺序可能如下：<br /><span style="COLOR: #993366">1.new operator分配适当的内存；<br />2.内存地址赋值给_instance；<br />3.在分配的内存上构造Singleton对象。</span><br /><br />当编译器优化后，如果线程一执行到2后被挂起。线程二开始执行并发现0 == _instance为false，于是直接return，而这时Singleton对象可能还未构造完成，后果...<br /><br />上面说的还只是单处理器的情况，在多处理器(multiprocessors)的情况下，超线程技术必然会混合执行指令，指令的执行顺序更无法保障。关于<span style="COLOR: #333399"><em>Double-Checked Locking</em></span>的更详细的文章，请看：<br /><a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html"><font color="#810081">The "Double-Checked Locking is Broken" Declaration</font></a><br /><br /><span style="COLOR: #993366"><strong style="FONT-SIZE: 14pt">5.使用volatile关键字<br /></strong></span>为了说明问题，请先考虑如下代码：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080"> 1</span> <span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> MyThread : </span><span style="COLOR: #0000ff">public</span></font><font face="Courier New"><span style="COLOR: #000000"> Thread {<br /></span><span style="COLOR: #008080"> 2</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080"> 3</span> <span style="COLOR: #000000">    virtual </span><span style="COLOR: #0000ff">void</span></font><font face="Courier New"><span style="COLOR: #000000"> run() {<br /></span><span style="COLOR: #008080"> 4</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">!</span></font><font face="Courier New"><span style="COLOR: #000000">_stopped) {<br /></span><span style="COLOR: #008080"> 5</span> <span style="COLOR: #000000">            </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">do something</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 6</span> <span style="COLOR: #008000"></span></font><font face="Courier New"><span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080"> 7</span> </font><font face="Courier New"><span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080"> 8</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">void</span></font><font face="Courier New"><span style="COLOR: #000000"> stop() {<br /></span><span style="COLOR: #008080"> 9</span> <span style="COLOR: #000000">        _stopped </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">true</span></font><font face="Courier New"><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080">10</span> </font><font face="Courier New"><span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080">11</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">12</span> </font><font face="Courier New"><span style="COLOR: #000000">    bool _stopped;<br /></span><span style="COLOR: #008080">13</span> </font><font face="Courier New"><span style="COLOR: #000000">};<br /></span><span style="COLOR: #008080">14</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">15</span> ...</font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">16</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">17</span> </font><font face="Courier New"><span style="COLOR: #000000">MyThread thread;<br /></span><span style="COLOR: #008080">18</span> <span style="COLOR: #000000">thread.start();</span></font></div></span>上面用thread.start()开启了一个线程，该线程在while循环中检测bool标记_stopped，看是否该继续执行。如果想要结束这个线程，调用thread.stop()应该没问题。但是需要注意的是编译器很有可能对_stopped的存取进行优化。如果编译器发现_stopped被频繁存取(_stopped在while循环中)，编译器可能会考虑将_stopped缓存到寄存器中，以后_stopped将会直接从寄存器存取。这时候如果某个线程调用了thread.stop()，对_stopped的修改将不会反映到寄存器中，thread将会永远循环下去...<br /><br />为了防止编译器优化，用volatile关键字就OK了，volatile跟const的用法几乎一样，能用const的地方也都能用volatile。对Singleton来说，修改如下两处即可：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">1</span> <span style="COLOR: #008000">//</span><span style="COLOR: #008000">singleton.h中</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">2</span> <span style="COLOR: #008000"></span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Singleton </span><span style="COLOR: #000000">*</span></font><font face="Courier New"><span style="COLOR: #000000">_instance;<br /></span><span style="COLOR: #008080">3</span> <span style="COLOR: #000000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">改为</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">4</span> <span style="COLOR: #008000"></span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Singleton </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">volatile</span></font><font face="Courier New"><span style="COLOR: #000000"> _instance;<br /></span><span style="COLOR: #008080">5</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">6</span> <span style="COLOR: #000000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">singleton.cpp中</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">7</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Singleton::_instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span></font><font face="Courier New"><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080">8</span> <span style="COLOR: #000000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">改为</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">9</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000"> Singleton::_instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;</span></font></div><br /><br /><strong style="FONT-SIZE: 14pt; COLOR: #993366">6.将Singleton泛化为模板<br /></strong><em style="COLOR: #333399">singleton.h<br /></em><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080"> 1</span> </font><font face="Courier New"><span style="COLOR: #000000">#ifndef SINGLETON_H<br /></span><span style="COLOR: #008080"> 2</span> </font><font face="Courier New"><span style="COLOR: #000000">#define SINGLETON_H<br /></span><span style="COLOR: #008080"> 3</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 4</span> <span style="COLOR: #000000">#include </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">synobj.h</span><span style="COLOR: #000000">"</span></font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 5</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 6</span> <span style="COLOR: #000000">template</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> T</span><span style="COLOR: #000000">&gt;</span></font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 7</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span></font><font face="Courier New"><span style="COLOR: #000000"> Singleton {<br /></span><span style="COLOR: #008080"> 8</span> </font><font face="Courier New"><span style="COLOR: #000000">    CLASS_UNCOPYABLE(Singleton)<br /></span><span style="COLOR: #008080"> 9</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> T</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> Instance() { </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Unique point of access</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">11</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">==</span></font><font face="Courier New"><span style="COLOR: #000000"> _instance) {<br /></span><span style="COLOR: #008080">12</span> </font><font face="Courier New"><span style="COLOR: #000000">            Lock lock(_mutex);<br /></span><span style="COLOR: #008080">13</span> <span style="COLOR: #000000">            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">==</span></font><font face="Courier New"><span style="COLOR: #000000"> _instance) {<br /></span><span style="COLOR: #008080">14</span> <span style="COLOR: #000000">                _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span></font><font face="Courier New"><span style="COLOR: #000000"> T();<br /></span><span style="COLOR: #008080">15</span> </font><font face="Courier New"><span style="COLOR: #000000">                atexit(Destroy);<br /></span><span style="COLOR: #008080">16</span> </font><font face="Courier New"><span style="COLOR: #000000">            }<br /></span><span style="COLOR: #008080">17</span> </font><font face="Courier New"><span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">18</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span></font><font face="Courier New"><span style="COLOR: #000000">_instance;<br /></span><span style="COLOR: #008080">19</span> </font><font face="Courier New"><span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080">20</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">protected</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">21</span> </font><font face="Courier New"><span style="COLOR: #000000">    Singleton(){}<br /></span><span style="COLOR: #008080">22</span> <span style="COLOR: #000000">    </span><span style="COLOR: #000000">~</span></font><font face="Courier New"><span style="COLOR: #000000">Singleton(){}<br /></span><span style="COLOR: #008080">23</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080">24</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> Destroy() { </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Destroy the only instance</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">25</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( _instance </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span></font><font face="Courier New"><span style="COLOR: #000000"> ) {<br /></span><span style="COLOR: #008080">26</span> </font><font face="Courier New"><span style="COLOR: #000000">            delete _instance;<br /></span><span style="COLOR: #008080">27</span> <span style="COLOR: #000000">            _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span></font><font face="Courier New"><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080">28</span> </font><font face="Courier New"><span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">29</span> </font><font face="Courier New"><span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080">30</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span></font><font face="Courier New"><span style="COLOR: #000000"> Mutex _mutex;<br /></span><span style="COLOR: #008080">31</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> T </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000"> _instance; </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> The one and only instance</span></font><span style="COLOR: #008000"><br /></span><font face="Courier New"><span style="COLOR: #008080">32</span> <span style="COLOR: #008000"></span></font><font face="Courier New"><span style="COLOR: #000000">};<br /></span><span style="COLOR: #008080">33</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">34</span> <span style="COLOR: #000000">template</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> T</span><span style="COLOR: #000000">&gt;</span></font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">35</span> <span style="COLOR: #000000">Mutex Singleton</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span></font><font face="Courier New"><span style="COLOR: #000000">::_mutex;<br /></span><span style="COLOR: #008080">36</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">37</span> <span style="COLOR: #000000">template</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> T</span><span style="COLOR: #000000">&gt;</span></font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">38</span> <span style="COLOR: #000000">T </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000"> Singleton</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::_instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span></font><font face="Courier New"><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080">39</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">40</span> <span style="COLOR: #000000">#endif</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">SINGLETON_H</span><span style="COLOR: #008000">*/</span></font></div><br />测试代码：<br /><span style="COLOR: #333399"><em>test.cpp<br /></em></span><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080"> 1</span> <span style="COLOR: #000000">#include </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">singleton.h</span><span style="COLOR: #000000">"</span></font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 2</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 3</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> A : </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Singleton</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">A</span><span style="COLOR: #000000">&gt;</span></font><font face="Courier New"><span style="COLOR: #000000"> {<br /></span><span style="COLOR: #008080"> 4</span> <span style="COLOR: #000000">    friend </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Singleton</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">A</span><span style="COLOR: #000000">&gt;</span></font><font face="Courier New"><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080"> 5</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">protected</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080"> 6</span> </font><font face="Courier New"><span style="COLOR: #000000">    A(){}<br /></span><span style="COLOR: #008080"> 7</span> <span style="COLOR: #000000">    </span><span style="COLOR: #000000">~</span></font><font face="Courier New"><span style="COLOR: #000000">A(){}<br /></span><span style="COLOR: #008080"> 8</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font><font face="Courier New"><span style="COLOR: #000000">:<br /></span><span style="COLOR: #008080"> 9</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">void</span></font><font face="Courier New"><span style="COLOR: #000000"> DoSomething(){}<br /></span><span style="COLOR: #008080">10</span> </font><font face="Courier New"><span style="COLOR: #000000">};<br /></span><span style="COLOR: #008080">11</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">12</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span></font><font face="Courier New"><span style="COLOR: #000000"> main() {<br /></span><span style="COLOR: #008080">13</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">14</span> <span style="COLOR: #000000">    A </span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">a </span><span style="COLOR: #000000">=</span></font><font face="Courier New"><span style="COLOR: #000000"> A::Instance();<br /></span><span style="COLOR: #008080">15</span> </font><font face="Courier New"><span style="COLOR: #000000">    a.DoSomething();<br /></span><span style="COLOR: #008080">16</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080">17</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span></font><font face="Courier New"><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080">18</span> <span style="COLOR: #000000">}</span></font></div><p><br /><span style="COLOR: #993366"><strong style="FONT-SIZE: 14pt">7.Singleton的析构问题</strong></span><br />到此Singleton已经算比较完善了，但是依然算不上完美，因为到现在只是解决了多线程问题，加入了模板支持，对于<span style="COLOR: #333399"><em>KDL problem(The Dead Reference Problem)</em></span>依然没法解决，可以说在实现Singleton模式时，最大的问题就是<span style="COLOR: #993366">多个有依赖关系的Singleton的析构顺序</span>。虽然<em style="COLOR: #333399">Modern C++ Design</em>中给出了解决方案，但是<span style="COLOR: #333399"><em>Loki</em></span>的实现太过复杂，在此就不详细说明了，有兴趣的可以看看<span style="COLOR: #333399"><em>Modern C++ Design</em></span>，当然了，<span style="COLOR: #333399"><em>Loki</em></span>库中用策略模式实现的Singleton也很不错！<br /></p><img src ="http://www.cppblog.com/ant/aggbug/31786.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ant/" target="_blank">蚂蚁终结者</a> 2007-09-07 23:22 <a href="http://www.cppblog.com/ant/archive/2007/09/07/31786.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>非完美C++ Singleton实现[1]</title><link>http://www.cppblog.com/ant/archive/2007/09/07/31445.html</link><dc:creator>蚂蚁终结者</dc:creator><author>蚂蚁终结者</author><pubDate>Fri, 07 Sep 2007 06:49:00 GMT</pubDate><guid>http://www.cppblog.com/ant/archive/2007/09/07/31445.html</guid><wfw:comment>http://www.cppblog.com/ant/comments/31445.html</wfw:comment><comments>http://www.cppblog.com/ant/archive/2007/09/07/31445.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.cppblog.com/ant/comments/commentRss/31445.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ant/services/trackbacks/31445.html</trackback:ping><description><![CDATA[<p>Singleton模式是一种非常简单的设计模式，这种模式很常用也很容易被滥用。当你设计应用程序的时候，经常会遇到某些对象在整个程序的生命周期应该仅有一个实例的情况，比如<span style="COLOR: #333399"><em>File System，Graphic System，Logging Utility</em></span>，这时候就可以用到Singleton模式。Singleton模式在<span style="COLOR: #333399"><em>GOF</em></span>中描述如下：<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #993366"><em>&nbsp; Ensure a class only has one instance, and provide a global point of access to it.</em></span><br><br>Singleton模式的定义很简单，实现也有N多种，但是却很难找到一个称得上&#8220;完美&#8221;的。实现一个完美的Singleton比想象中要难的多，下面探索性的来实现一个非完美的。<br><br><span style="COLOR: #993366"><strong style="FONT-SIZE: 14pt">1.典型实现<br></strong></span>在C++中，Singleton模式的典型实现如下：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Header&nbsp;file&nbsp;Singleton.h</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #0000ff">class</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Singleton&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;Instance()&nbsp;{&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Unique&nbsp;point&nbsp;of&nbsp;access</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">==</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;_instance)<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_instance&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Singleton();<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span></font> <font face="Courier New"><span style="COLOR: #000000">_instance;<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;DoSomething();<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Singleton();&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Prevent&nbsp;clients&nbsp;from&nbsp;creating&nbsp;a&nbsp;new&nbsp;Singleton</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">Singleton();&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Prevent&nbsp;clients&nbsp;from&nbsp;deleting&nbsp;a&nbsp;Singleton</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Singleton(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Prevent&nbsp;clients&nbsp;from&nbsp;copying&nbsp;a&nbsp;Singleton</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;operator</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;Singleton&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_instance;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;The&nbsp;one&nbsp;and&nbsp;only&nbsp;instance</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #008000"></span></font> <font face="Courier New"><span style="COLOR: #000000">};<br></span><span style="COLOR: #008080">18</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Implementation&nbsp;file&nbsp;Singleton.cpp</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;Singleton::_instance&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;</span></font> </div>
<p><br>通过将Singleton的构造函数设为private可以禁止客户代码直接创建Singleton对象，除此之外，Singleton的copy constructor和copy assignment operator都为private且仅有声明没有实现，禁止了客户代码拷贝Singleton对象。唯一可以创建Singleton对象的是Singleton自己的静态成员函数Instance，这样就在编译器保证了Singleton实例的唯一性。上面这些是在C++中实现Singleton模式最基本的要点。<br><br>Instance方法保证只有在第一次调用时才会生成Singleton对象，以后的调用只是简单返回唯一的已存在的实例。Instance方法实际上实现的是<span style="COLOR: #333399"><em>懒惰初始化(lazy initialize)，</em></span>如果程序中根本没有用到Singleton对象，也就根本不会产生Singleton的实例，这在Singleton对象很少使用且创建Singleton对象开销比较大的情况下特别有用。</p>
<p>客户代码现在可以这样使用Singleton：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">1</span>&nbsp;<span style="COLOR: #000000">Singleton&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">s&nbsp;</span><span style="COLOR: #000000">=</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Singleton::Instance();<br></span><span style="COLOR: #008080">2</span>&nbsp;<span style="COLOR: #000000">s.DoSomething();</span></font> </div>
<p><br>还需要说明的是Singleton的析构函数，析构函数也为private可以禁止客户写出如下代码。如果某个客户写出了如下代码，随后的对Singleton的访问就会导致为定义行为，因为Singleton对象已经不存在。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">1</span>&nbsp;<span style="COLOR: #000000">Singleton&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span></font> <font face="Courier New"><span style="COLOR: #000000">Singleton::Instance();<br></span><span style="COLOR: #008080">2</span>&nbsp;<span style="COLOR: #000000">delete&nbsp;p;</span></font> </div>
<p><br><strong style="COLOR: #993366"><span style="FONT-SIZE: 14pt">2.引入smart pointer</span><br></strong>上面的实现算是一个好的实现吗？当然不是，或许连一个正确的实现都算不上。如果你想凑合，当然没问题，上面的代码大多数情况下可以工作的很好。也许你已经注意到了一些问题，比如说在上面的代码中只有new没有delete。是的，你说会发生memory leak对吧，其实memory leak都不是主要的问题，所有的现代操作系统在进程结束的时候都会对内存很好的进行回收。比memory leak更值得让人担忧的是resource leak，如果Singleton在构造函数中请求了某些资源：网络连接，文件句柄，数据库连接等。这些资源将得不到释放。<br><br>唯一修正resource leak的方法就是在程序结束的时候delete _instance。当然了，用smart pointer再好不过，在这里用auto_ptr就可以满足需要了(如果你还不知道smart_ptr是什么，花点时间熟悉C++标准库吧)，修改后的代码如下：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Header&nbsp;file&nbsp;Singleton.h</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #0000ff">class</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Singleton&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;Instance()&nbsp;{&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Unique&nbsp;point&nbsp;of&nbsp;access</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">==</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;_instance.get())<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_instance.reset(</span><span style="COLOR: #0000ff">new</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Singleton());<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span></font> <font face="Courier New"><span style="COLOR: #000000">(_instance.get());<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;DoSomething(){}<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Singleton(){}&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Prevent&nbsp;clients&nbsp;from&nbsp;creating&nbsp;a&nbsp;new&nbsp;Singleton</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">Singleton(){}&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Prevent&nbsp;clients&nbsp;from&nbsp;deleting&nbsp;a&nbsp;Singleton</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Singleton(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Prevent&nbsp;clients&nbsp;from&nbsp;copying&nbsp;a&nbsp;Singleton</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;operator</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;friend&nbsp;auto_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Singleton</span><span style="COLOR: #000000">&gt;</span></font> <font face="Courier New"><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;auto_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Singleton</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;_instance;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;The&nbsp;one&nbsp;and&nbsp;only&nbsp;instance</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #008000"></span></font> <font face="Courier New"><span style="COLOR: #000000">};<br></span><span style="COLOR: #008080">19</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Implementation&nbsp;file&nbsp;Singleton.cpp</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">auto_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Singleton</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;Singleton::_instance;</span></font> </div>
<p><br><span style="COLOR: #993366"><strong style="FONT-SIZE: 14pt">3.用atexit替换smart pointer<br></strong></span>C++并没有规定不同<span style="COLOR: #333399"><em>编译单元(translation unit，简单说就是一个可编译的cpp文件)</em></span>中static对象的初始化顺序。如果一个程序中有多个Singleton对象，那么这些Singleton对象的析构顺序也将是任意的。很显然，当多个Singleton对象有依赖关系时，smart pointer根本无法保证Singleton的析构顺序。<br><br>msdn中对atexit描述如下：</p>
<p>The <strong>atexit</strong> function is passed the address of a function (<span class=parameter>func</span>) to be called when the program terminates normally. Successive calls to <strong>atexit</strong> create a register of functions that are executed in last-in, first-out (LIFO) order. The functions passed to <strong>atexit</strong> cannot take parameters. <strong>atexit</strong>&nbsp; use the heap to hold the register of functions. Thus, the number of functions that can be registered is limited only by heap memory.<br><br>需要说明的是atexit并不比smart pointer好多少，LIFO的保证对于有复杂依赖关系的多个Singleton依然束手无力，但是用atexit替换smart pointer却是必须的，它是设计完美Singleton的基础。<br><br><br><span style="COLOR: #993366">#如果你疑惑atexit为什么还是不行，请考虑下面的情况：</span><br>NOTE：下面的情况在<em>Modern C++ Design</em>中叫做<em style="COLOR: #333399">KDL(Keyboard,Display,Log)problem</em>。<br><br>某个程序中使用了如下3个Singleton：<span style="COLOR: #333399">Keyboard</span>，<span style="COLOR: #333399">Display</span>，<span style="COLOR: #333399">Log</span>。<span style="COLOR: #333399">Keyboard</span>和<span style="COLOR: #333399">Display</span>分别对应于计算机的键盘和显示器，<span style="COLOR: #333399">Log</span>用来记录错误信息。假设当<span style="COLOR: #333399">Keyboard</span>和<span style="COLOR: #333399">Display</span>的构造函数和析构函数出现错误时会调用<span style="COLOR: #333399">Log</span>记录错误信息，并且构造和析构导致的任何错误都会终止程序。<br><br>在程序启动时，如果<span style="COLOR: #333399">Keyboard</span>构造成功，<span style="COLOR: #333399">Display</span>构造失败，很显然在<span style="COLOR: #333399">Display</span>的构造函数中将会构造<span style="COLOR: #333399">Log</span>而且失败信息会被<span style="COLOR: #333399">Log</span>记录，根据假设这时候程序准备退出，atexit注册的函数将会按LIFO的顺序被调用。因为<span style="COLOR: #333399">Keyboard</span>先于<span style="COLOR: #333399">Log</span>构造，所以<span style="COLOR: #333399">Log</span>先于<span style="COLOR: #333399">Keyboard</span>析构，但是当由于某种原因<span style="COLOR: #333399">Keyboard</span>在析构时失败，想要调用<span style="COLOR: #333399">Log</span>记录错误信息时，<span style="COLOR: #333399">Log</span>早已被销毁，则Log::Instance()将会导致未定义行为。<br></p>
<p><span style="COLOR: #993366">#atexit的严重问题：</span> <br>从上面的例子可以看出，atexit和smart pointer相比仅仅是有LIFO的保证而已，这样的保证貌似也不怎么有效，因为atexit跟smart pointer一样也无法解决<em style="COLOR: #333399">KDL probleam</em>。<br><br>atexit由于LIFO带来了另外的问题，看下面的代码：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">cstdlib</span><span style="COLOR: #000000">&gt;</span></font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Bar()&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;...<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">}<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Foo()&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;std::atexit(Bar);<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">}<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;main()&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;std::atexit(Foo);<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span></font> <font face="Courier New"><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">}</span></font> </div>
<p>上面的小段代码用atexit注册了Foo，Foo调用了std::atexit(Bar)。当程序退出时，根据atexit的LIFO保证，Bar在Foo之后注册，因此Bar应该在Foo之前调用，但是当Bar注册的时候Foo已经调用了，Bar根本就没有机会能够在Foo之前调用。这明显自相矛盾对吧，没办法，C++标准好像忽视了这一点，因此如果类似代码被调用，肯定不会有什么好的结果，好一点是resource leak，差一点估计程序就崩溃了！！！<br><br>atexit的这个问题跟Singleton有关系吗？当然有，如果在一个Singleton的析构函数中调用atexit就会出现上述问题。即在<span style="COLOR: #333399"><em>KDL problem</em></span>中，如果<span style="COLOR: #333399">Keyboard</span>和<span style="COLOR: #333399">Display</span>都构造成功，当<span style="COLOR: #333399">Keyboard</span>或<span style="COLOR: #333399">Display</span>任意一个析构失败时，<span style="COLOR: #333399">Keyboard</span>或<span style="COLOR: #333399">Display</span>在析构函数中会构造<span style="COLOR: #333399">Log</span>，<span style="COLOR: #333399">Log</span>的构造函数会间接调用atexit。oops!!!，可怕的未定义行为。<br><br>看到这里你一定对atexit相当失望，貌似它带来的好处多于坏处。但是请你相信，如果适当设计，atexit在后面的Singleton改造中会起到很重要的作用。<br><br>用atexit后的代码：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Header&nbsp;file&nbsp;Singleton.h</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #0000ff">class</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Singleton&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;Instance()&nbsp;{&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Unique&nbsp;point&nbsp;of&nbsp;access</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">==</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;_instance)&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_instance&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;Singleton();<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atexit(Destroy);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Register&nbsp;Destroy&nbsp;function</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #008000"></span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span></font> <font face="Courier New"><span style="COLOR: #000000">_instance;<br></span><span style="COLOR: #008080">10</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;DoSomething(){}<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Destroy()&nbsp;{&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Destroy&nbsp;the&nbsp;only&nbsp;instance</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;_instance&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span></font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;)&nbsp;{<br></span><span style="COLOR: #008080">15</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;_instance;<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_instance&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span></font> <font face="Courier New"><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">17</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">18</span>&nbsp;</font> <font face="Courier New"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Singleton(){}&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Prevent&nbsp;clients&nbsp;from&nbsp;creating&nbsp;a&nbsp;new&nbsp;Singleton</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">Singleton(){}&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Prevent&nbsp;clients&nbsp;from&nbsp;deleting&nbsp;a&nbsp;Singleton</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Singleton(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Prevent&nbsp;clients&nbsp;from&nbsp;copying&nbsp;a&nbsp;Singleton</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;operator</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Singleton</span><span style="COLOR: #000000">&amp;</span></font> <font face="Courier New"><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span></font> <font face="Courier New"><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;Singleton&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_instance;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;The&nbsp;one&nbsp;and&nbsp;only&nbsp;instance</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #008000"></span></font> <font face="Courier New"><span style="COLOR: #000000">};<br></span><span style="COLOR: #008080">26</span>&nbsp;</font> <span style="COLOR: #000000"><br></span><font face="Courier New"><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Implementation&nbsp;file&nbsp;Singleton.cpp</span></font> <span style="COLOR: #008000"><br></span><font face="Courier New"><span style="COLOR: #008080">28</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;Singleton::_instance&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;</span></font> </div>
<br>你有没有仔细考虑过Destroy中的_instance = 0;这一行代码，上述代码实际上实现的是<em style="COLOR: #333399">不死鸟模式(The Phoenix Singleton)，</em>所谓不死鸟，就跟一辉一样可以死而复生。上面的代码可以解决本文最早提出的<em style="COLOR: #333399">KDL problem</em>，即如果<span style="COLOR: #333399">Keyboard</span>析构失败，虽然<span style="COLOR: #333399">Log</span>已经析构，但是由于Destroy中的_instance = 0;这一行代码，Log::Instance()将会创建一个新的<span style="COLOR: #333399">Log</span>对象，程序将会表现良好。当然了，<span style="COLOR: #993366">Phoenix Singleton</span>仅能用于无状态的Singleton，如果<span style="COLOR: #333399">Log</span>需要保存某些状态，<span style="COLOR: #993366">Phoenix Singleton</span>也不会带来任何好处。你当然可以用某些方法维持<span style="COLOR: #993366">Phoenix Singleton</span>的状态，但是在做之前先想想看是否值得，维持状态可能会使Singleton变得特别复杂。<br><br>上面的<span style="COLOR: #993366">Phoenix Singleton</span>已经可以满足大部分需要，如果你的Singleton没有涉及到多线程，多个Singleton之间也没有依赖关系，你大可以放心使用。但是如果你用到多线程，或者你的Singleton关系如<span style="COLOR: #333399"><em>KDL</em></span>般复杂，或者你觉得对每一个Singleton都敲同样的代码让你厌烦。在后面几篇会有一个<span style="COLOR: #993366">多线程安全</span>的，能够<span style="COLOR: #993366">解决多个Singleton依赖关系</span>的，<span style="COLOR: #993366">基于模板</span>的Singleton实现。<br>
<img src ="http://www.cppblog.com/ant/aggbug/31445.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ant/" target="_blank">蚂蚁终结者</a> 2007-09-07 14:49 <a href="http://www.cppblog.com/ant/archive/2007/09/07/31445.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从Win32 API封装Thread类[2]</title><link>http://www.cppblog.com/ant/archive/2007/08/31/31280.html</link><dc:creator>蚂蚁终结者</dc:creator><author>蚂蚁终结者</author><pubDate>Fri, 31 Aug 2007 03:58:00 GMT</pubDate><guid>http://www.cppblog.com/ant/archive/2007/08/31/31280.html</guid><wfw:comment>http://www.cppblog.com/ant/comments/31280.html</wfw:comment><comments>http://www.cppblog.com/ant/archive/2007/08/31/31280.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/ant/comments/commentRss/31280.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ant/services/trackbacks/31280.html</trackback:ping><description><![CDATA[在上一篇中介绍了创建Thread的两种方法：从Thread类继承或者实现Runnable接口。有时候这并不是特别方便，我们需要的是更灵活的方法，比如像boost库中的Thread一样可以用普通函数和函数对象<br />(<em>functor</em> and <em>function object</em>)作为构造函数参数。如果你熟悉STL，你应该熟悉bind1st和bind2nd这两个函数配接器(<em>function adapter</em>)，bind1st和bind2nd可以将一个二元函数(<em>binary function</em>)转换成一元函数(<em>unary function</em>)。为了使Thread类能够用普通函数和函数对象作为参数，我们需要一个bind将一元函数转换成无参函数：<br /><em style="COLOR: #333399">bind.h<br /></em><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><font face="Courier New"><span style="COLOR: #008080"> 1</span> </font><font face="Courier New"><span style="COLOR: #000000">#ifndef BIND_H<br /></span><span style="COLOR: #008080"> 2</span> </font><font face="Courier New"><span style="COLOR: #000000">#define BIND_H<br /></span><span style="COLOR: #008080"> 3</span> </font><span style="COLOR: #000000"><br /></span><font face="Courier New"><span style="COLOR: #008080"> 4</span> <span style="COLOR: #000000">template </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> _Result</span><span style="COLOR: #000000">&gt;</span></font><span style="COLOR: #000000"><br /></span><fon