﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-局部变量的作用域-随笔分类-多线程</title><link>http://www.cppblog.com/localvar/category/15386.html</link><description>&lt;font color="yellow" size=4&gt;本站关闭评论功能，如需评论请移步：&lt;a href="http://zbm.xuanwo.tk/"&gt;http://zbm.xuanwo.tk/&lt;/a&gt;&lt;/font&gt;</description><language>zh-cn</language><lastBuildDate>Thu, 17 Mar 2011 17:03:47 GMT</lastBuildDate><pubDate>Thu, 17 Mar 2011 17:03:47 GMT</pubDate><ttl>60</ttl><item><title>一个轻量级的事件对象</title><link>http://www.cppblog.com/localvar/archive/2011/03/17/142059.html</link><dc:creator>局部变量</dc:creator><author>局部变量</author><pubDate>Thu, 17 Mar 2011 08:48:00 GMT</pubDate><guid>http://www.cppblog.com/localvar/archive/2011/03/17/142059.html</guid><description><![CDATA[<p>评论请移步<a href="http://zbm.xuanwo.tk/2011/03/slim-event.html">http://zbm.xuanwo.tk/2011/03/slim-event.html</a></p>
<p>&#8220;事件&#8221;对象的一个轻量级实现，方法与&#8220;<a href="http://zbm.xuanwo.tk/2011/03/slim-semaphore.html">信号量</a>&#8221;基本一样。</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"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CSlimEvent<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;SRWLOCK&nbsp;m_lock;<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;CONDITION_VARIABLE&nbsp;m_cv;<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;m_manual;<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;m_state;<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;CSlimEvent(&nbsp;BOOL&nbsp;bManualReset,&nbsp;BOOL&nbsp;bInitialState&nbsp;)<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeSRWLock(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeConditionVariable(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_cv&nbsp;);<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_manual&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;bManualReset;<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_state&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;bInitialState;<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">CSlimEvent()&nbsp;{&nbsp;}<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;Set()<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AcquireSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_state&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TRUE;<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">26</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;m_manual&nbsp;)<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WakeAllConditionVariable(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_cv&nbsp;);<br></span><span style="COLOR: #008080">28</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">29</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WakeConditionVariable(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_cv&nbsp;);<br></span><span style="COLOR: #008080">30</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">31</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;TRUE;<br></span><span style="COLOR: #008080">32</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">33</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">34</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;Reset()<br></span><span style="COLOR: #008080">35</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">36</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AcquireSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">37</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_state&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;FALSE;<br></span><span style="COLOR: #008080">38</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">39</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;TRUE;<br></span><span style="COLOR: #008080">40</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">41</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">42</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;Wait(&nbsp;DWORD&nbsp;dwTimeout&nbsp;)<br></span><span style="COLOR: #008080">43</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">44</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WAIT_TIMEOUT;<br></span><span style="COLOR: #008080">45</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;start&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetTickCount();<br></span><span style="COLOR: #008080">46</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">47</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AcquireSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">48</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">49</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">&nbsp;)<br></span><span style="COLOR: #008080">50</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">51</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;m_state&nbsp;)<br></span><span style="COLOR: #008080">52</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">53</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_state&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;m_manual;<br></span><span style="COLOR: #008080">54</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WAIT_OBJECT_0;<br></span><span style="COLOR: #008080">55</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: #0000ff">break</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">56</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">57</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">58</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;dwTimeout&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;INFINITE&nbsp;)<br></span><span style="COLOR: #008080">59</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">60</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;end&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetTickCount();<br></span><span style="COLOR: #008080">61</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: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;end&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;start&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">gt;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dwTimeout&nbsp;)<br></span><span style="COLOR: #008080">62</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">63</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwTimeout&nbsp;</span><span style="COLOR: #000000">-=</span><span style="COLOR: #000000">&nbsp;end&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;start;<br></span><span style="COLOR: #008080">64</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;end;<br></span><span style="COLOR: #008080">65</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">66</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">67</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><span style="COLOR: #000000">SleepConditionVariableSRW(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_cv,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock,&nbsp;dwTimeout,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)&nbsp;)<br></span><span style="COLOR: #008080">68</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">69</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: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;GetLastError()&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;ERROR_TIMEOUT&nbsp;)<br></span><span style="COLOR: #008080">70</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WAIT_FAILED;<br></span><span style="COLOR: #008080">71</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: #0000ff">break</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">72</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">73</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">74</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">75</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">76</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">77</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;result;<br></span><span style="COLOR: #008080">78</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">79</span>&nbsp;<span style="COLOR: #000000">};</span></div><img src ="http://www.cppblog.com/localvar/aggbug/142059.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/localvar/" target="_blank">局部变量</a> 2011-03-17 16:48 <a href="http://www.cppblog.com/localvar/archive/2011/03/17/142059.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个轻量级的信号量</title><link>http://www.cppblog.com/localvar/archive/2011/03/16/141998.html</link><dc:creator>局部变量</dc:creator><author>局部变量</author><pubDate>Wed, 16 Mar 2011 09:50:00 GMT</pubDate><guid>http://www.cppblog.com/localvar/archive/2011/03/16/141998.html</guid><description><![CDATA[<p>评论请移步：<a href="http://zbm.xuanwo.tk/2011/03/slim-semaphore.html">http://zbm.xuanwo.tk/2011/03/slim-semaphore.html</a></p>
<p>基于SRWLOCK和条件变量（Condition Variable）实现，需要windows vista及以上操作系统，编译时_WIN32_WINNT要大于0x0600。基本功能和用CreateSemaphore创建出来的差不多，不过不支持跨进程使用，也模拟不了WaitForMultipleObjects的情形。和系统自带的那个相比一般会快一点，具体结果取决于硬件，有些机器上能快十几倍，有些机器则只稍快一丁点。请注意我说的快十几倍也仅仅是指这两个实现本身的差别，而不是说程序的总体性能提高这么多。具体是否使用，大家可以根据自己的测试结果来决定。代码和使用应该都很简单，就不多解释和举例了。</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"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CSlimSemaphore<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;SRWLOCK&nbsp;m_lock;<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;CONDITION_VARIABLE&nbsp;m_cv;<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LONG&nbsp;m_value;<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;LONG&nbsp;m_maximum;<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;CSlimSemaphore(&nbsp;LONG&nbsp;lInitialCount,&nbsp;LONG&nbsp;lMaximumCount&nbsp;)<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeSRWLock(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeConditionVariable(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_cv&nbsp;);<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;lInitialCount;<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_maximum&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;lMaximumCount;<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">CSlimSemaphore()&nbsp;{&nbsp;}<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;Release(&nbsp;LONG&nbsp;lReleaseCount,&nbsp;LONG</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;lpPreviousCount&nbsp;)<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;succeeded&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;FALSE;<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AcquireSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">26</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;m_value&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;lReleaseCount&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">lt;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;m_maximum&nbsp;)<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">28</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;lpPreviousCount&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;NULL&nbsp;)<br></span><span style="COLOR: #008080">29</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">lpPreviousCount&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;m_value;<br></span><span style="COLOR: #008080">30</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_value&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;lReleaseCount;<br></span><span style="COLOR: #008080">31</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;succeeded&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TRUE;<br></span><span style="COLOR: #008080">32</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">33</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">34</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">35</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">36</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;succeeded&nbsp;)<br></span><span style="COLOR: #008080">37</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WakeAllConditionVariable(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_cv&nbsp;);<br></span><span style="COLOR: #008080">38</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">39</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetLastError(&nbsp;ERROR_TOO_MANY_POSTS&nbsp;);<br></span><span style="COLOR: #008080">40</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">41</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;succeeded;<br></span><span style="COLOR: #008080">42</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">43</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">44</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;Wait(&nbsp;DWORD&nbsp;dwTimeout&nbsp;)<br></span><span style="COLOR: #008080">45</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">46</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WAIT_TIMEOUT;<br></span><span style="COLOR: #008080">47</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;start&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetTickCount();<br></span><span style="COLOR: #008080">48</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">49</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AcquireSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">50</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">51</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">&nbsp;)<br></span><span style="COLOR: #008080">52</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">53</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;m_value&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">gt;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)<br></span><span style="COLOR: #008080">54</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">55</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">m_value;<br></span><span style="COLOR: #008080">56</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WAIT_OBJECT_0;<br></span><span style="COLOR: #008080">57</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: #0000ff">break</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">58</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">59</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">60</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;dwTimeout&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;INFINITE&nbsp;)<br></span><span style="COLOR: #008080">61</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">62</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;end&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetTickCount();<br></span><span style="COLOR: #008080">63</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: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;end&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;start&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">gt;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dwTimeout&nbsp;)<br></span><span style="COLOR: #008080">64</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">65</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwTimeout&nbsp;</span><span style="COLOR: #000000">-=</span><span style="COLOR: #000000">&nbsp;end&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;start;<br></span><span style="COLOR: #008080">66</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;end;<br></span><span style="COLOR: #008080">67</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">68</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">69</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><span style="COLOR: #000000">SleepConditionVariableSRW(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_cv,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock,&nbsp;dwTimeout,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)&nbsp;)<br></span><span style="COLOR: #008080">70</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">71</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: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;GetLastError()&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;ERROR_TIMEOUT&nbsp;)<br></span><span style="COLOR: #008080">72</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WAIT_FAILED;<br></span><span style="COLOR: #008080">73</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: #0000ff">break</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">74</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">75</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">76</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">77</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseSRWLockExclusive(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_lock&nbsp;);<br></span><span style="COLOR: #008080">78</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">79</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;result;<br></span><span style="COLOR: #008080">80</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">81</span>&nbsp;<span style="COLOR: #000000">};</span></div>
<img src ="http://www.cppblog.com/localvar/aggbug/141998.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/localvar/" target="_blank">局部变量</a> 2011-03-16 17:50 <a href="http://www.cppblog.com/localvar/archive/2011/03/16/141998.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程中的单件模式</title><link>http://www.cppblog.com/localvar/archive/2011/02/11/139892.html</link><dc:creator>局部变量</dc:creator><author>局部变量</author><pubDate>Fri, 11 Feb 2011 06:07:00 GMT</pubDate><guid>http://www.cppblog.com/localvar/archive/2011/02/11/139892.html</guid><description><![CDATA[<p>评论请移步：<a href="http://zbm.xuanwo.tk/2011/02/singleton-in-multithread.html"><u><font color=#810081>http://zbm.xuanwo.tk/2011/02/singleton-in-multithread.html</font></u></a></p>
<p>单件模式可能是所有设计模式中最简单的一个了，但在C++中，尤其是还要支持多线程的话，要想写一个正确的实现却并不容易，不信请看：</p>
<pre class=brush:cpp>
<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"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CSingleton<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;CSingleton()<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;_tprintf(&nbsp;_T(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">CSingleton::Constructor:&nbsp;Before&nbsp;Sleep\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;);<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;Sleep(&nbsp;</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">&nbsp;);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;不会改变逻辑,&nbsp;但增大了问题出现的概率</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;_tprintf(&nbsp;_T(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">CSingleton::Constructor:&nbsp;After&nbsp;Sleep\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;);<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;}<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;DoSomeThing()<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;_tprintf(&nbsp;_T(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">CSingleton::DoSomeThing\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;);<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;}<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CSingleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;GetInstance()<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CSingleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;p&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL&nbsp;)<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CSingleton();<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;p;<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;}<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">};<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">unsigned&nbsp;__stdcall&nbsp;thread(&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;)<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;CSingleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CSingleton::GetInstance();<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000">&nbsp;p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">DoSomeThing();<br></span><span style="COLOR: #008080">26</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000">}<br></span><span style="COLOR: #008080">28</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_tmain(&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[]&nbsp;)<br></span><span style="COLOR: #008080">29</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">30</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i&nbsp;)<br></span><span style="COLOR: #008080">31</span>&nbsp;<span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">32</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;uintptr_t&nbsp;t&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_beginthreadex(&nbsp;NULL,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;thread,&nbsp;NULL,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;NULL&nbsp;);<br></span><span style="COLOR: #008080">33</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;CloseHandle(&nbsp;(HANDLE)t&nbsp;);<br></span><span style="COLOR: #008080">34</span>&nbsp;<span style="COLOR: #000000">&nbsp;}<br></span><span style="COLOR: #008080">35</span>&nbsp;<span style="COLOR: #000000">&nbsp;_getch();<br></span><span style="COLOR: #008080">36</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">37</span>&nbsp;<span style="COLOR: #000000">}</span></div>
</pre>
<p>上面的单件实现在单线程中肯定是正确的，不过在多线程中的输出却如下：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span>&nbsp;<span style="COLOR: #000000">CSingleton::Constructor:&nbsp;Before&nbsp;Sleep<br></span><span style="COLOR: #008080">2</span>&nbsp;<span style="COLOR: #000000">CSingleton::Constructor:&nbsp;Before&nbsp;Sleep<br></span><span style="COLOR: #008080">3</span>&nbsp;<span style="COLOR: #000000">CSingleton::Constructor:&nbsp;Before&nbsp;Sleep<br></span><span style="COLOR: #008080">4</span>&nbsp;<span style="COLOR: #000000">CSingleton::Constructor:&nbsp;After&nbsp;Sleep<br></span><span style="COLOR: #008080">5</span>&nbsp;<span style="COLOR: #000000">CSingleton::DoSomeThing<br></span><span style="COLOR: #008080">6</span>&nbsp;<span style="COLOR: #000000">CSingleton::Constructor:&nbsp;After&nbsp;Sleep<br></span><span style="COLOR: #008080">7</span>&nbsp;<span style="COLOR: #000000">CSingleton::DoSomeThing<br></span><span style="COLOR: #008080">8</span>&nbsp;<span style="COLOR: #000000">CSingleton::Constructor:&nbsp;After&nbsp;Sleep<br></span><span style="COLOR: #008080">9</span>&nbsp;<span style="COLOR: #000000">CSingleton::DoSomeThing</span></div>
<p>很明显，虽然我们想做个单件，但它却出现了多个实例（或一个实例被初始化了多次）。其原因是我们的实现根本没有考虑多线程，那下面的代码把创建实例的部分锁住是不是就行了呢？</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CCriSec&nbsp;:&nbsp;CRITICAL_SECTION<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;CCriSec()<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;Sleep(&nbsp;</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">&nbsp;);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;增大出问题的概率,&nbsp;但不改变逻辑</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;InitializeCriticalSection(&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">&nbsp;);<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;}<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">CCriSec()&nbsp;{&nbsp;DeleteCriticalSection(&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">&nbsp;);&nbsp;}<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Enter()<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;EnterCriticalSection(&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">&nbsp;);<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;}<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Leave()&nbsp;{&nbsp;LeaveCriticalSection(&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">&nbsp;);&nbsp;}<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">};<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CSingleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;GetInstance()<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CSingleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CCriSec&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">.Enter();<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;p&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL&nbsp;)<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CSingleton();<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">.Leave();<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;p;<br></span><span style="COLOR: #008080">26</span>&nbsp;<span style="COLOR: #000000">}<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"></span></div>
<p>运行一下，不管输出是什么，程序崩溃了。分析一下可以发现，这个例子中的我们确实控制好了对CSingleton实例的初始化，但这种控制却依赖于另一个静态变量（CCriSec的实例）的初始化，而这个新的静态变量导致了程序的崩溃，也就是说我们在解决问题的同时引入了新的问题。而且，在这种情况下，就算再引入多少个新的临界区也无济于事，因为对最外层的临界区的初始化总会有问题。</p>
<p>上面的例子的问题在于CCriSec是一种复杂的数据类型，所以对它的初始化总要到运行时才能完成，如果用整数这样简单的、能在编译期完成初始化的数据类型来做是不是可以呢？</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"><span style="COLOR: #008080">1</span>&nbsp;<span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CSingleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;GetInstance()<br></span><span style="COLOR: #008080">2</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">3</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CSingleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;<br></span><span style="COLOR: #008080">4</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">5</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;InterlockedCompareExchange(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)<br></span><span style="COLOR: #008080">6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CSingleton();<br></span><span style="COLOR: #008080">7</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;p;<br></span><span style="COLOR: #008080">8</span>&nbsp;<span style="COLOR: #000000">}</span></div>
<p>看起来好像没有问题，但运行一下却是下面的输出：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span>&nbsp;<span style="COLOR: #000000">CSingleton::Constructor:&nbsp;Before&nbsp;Sleep<br></span><span style="COLOR: #008080">2</span>&nbsp;<span style="COLOR: #000000">CSingleton::DoSomeThing<br></span><span style="COLOR: #008080">3</span>&nbsp;<span style="COLOR: #000000">CSingleton::DoSomeThing<br></span><span style="COLOR: #008080">4</span>&nbsp;<span style="COLOR: #000000">CSingleton::Constructor:&nbsp;After&nbsp;Sleep<br></span><span style="COLOR: #008080">5</span>&nbsp;<span style="COLOR: #000000">CSingleton::DoSomeThing</span></div>
<p>也就是说DoSomeThing在构造函数返回之前已经被调用了，这显然也是错误的。其原因是我们忽略了&#8220;对象的创建时需要时间的&#8221;，把这个问题也修正一下，就是最终的正确实现了：</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"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CSingleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;GetInstance()<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CSingleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;InterlockedCompareExchange(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&nbsp;)&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;等待对象创建完成</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;Sleep(&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;);<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;p;<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;}<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CSingleton();<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;p;<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">}</span></div>
<p>本文采用的单件实现是函数内的静态变量，如果你采用其它方式，也会有类似问题。其实在我看来，单件模式是一个看起来简单、做对了很难（上面演示的是多线程中的问题，在具体的实践中还会遇到很多其他问题）、同时又没有太多实用价值的东西。</p>
<p>另外，从Windows Vista开始，微软提供了一种多线程下对象初始化的方法，有兴趣的可以中搜一下&#8220;INITONCE&#8221;，个人认为INITONCE有点完美的过头了，真正好玩又有用的是与它同时出现的&#8220;条件变量（condition variable）&#8221;。</p>
<img src ="http://www.cppblog.com/localvar/aggbug/139892.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/localvar/" target="_blank">局部变量</a> 2011-02-11 14:07 <a href="http://www.cppblog.com/localvar/archive/2011/02/11/139892.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个支持多线程的内存池</title><link>http://www.cppblog.com/localvar/archive/2010/10/28/132765.html</link><dc:creator>局部变量</dc:creator><author>局部变量</author><pubDate>Thu, 28 Oct 2010 09:45:00 GMT</pubDate><guid>http://www.cppblog.com/localvar/archive/2010/10/28/132765.html</guid><description><![CDATA[<p>代码并不复杂，不多做解释了，用的是windows api，但应该不难移植。<br><br>头文件:</p>
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="75%" bgColor=#f1f1f1>
    <tbody>
        <tr>
            <td>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000"><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">pragma</span> once<br><br><span style="COLOR: #0000ff">int</span> mp_register_usage<span style="COLOR: #0000cc">(</span> <span style="COLOR: #ff0000">size_t</span> size<span style="COLOR: #0000cc">,</span> <span style="COLOR: #ff0000">size_t</span> <span style="COLOR: #ff0000">count</span> <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">bool</span> mp_create<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">void</span> mp_destory<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">void</span><span style="COLOR: #0000cc">*</span> mp_alloc<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">int</span> objtype <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">void</span> mp_free<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">int</span> objtype<span style="COLOR: #0000cc">,</span> <span style="COLOR: #0000ff">void</span><span style="COLOR: #0000cc">*</span> mem <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<p><br>实现文件：</p>
<p>&nbsp;</p>
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="75%" bgColor=#f1f1f1>
    <tbody>
        <tr>
            <td>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000"><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">include</span> <span style="COLOR: #0000cc">&lt;</span>windows<span style="COLOR: #0000cc">.</span>h<span style="COLOR: #0000cc">&gt;</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">define</span> MP_MAX_OBJECT_TYPE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br><br><span style="COLOR: #0000ff">struct</span> MP_OBJECT_ENTRY<br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;SLIST_HEADER lsthdr<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">size_t</span> size<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">size_t</span> <span style="COLOR: #ff0000">count</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><span style="COLOR: #0000cc">;</span><br><br><span style="COLOR: #0000ff">static</span> MP_OBJECT_ENTRY s_entries<span style="COLOR: #0000cc">[</span>MP_MAX_OBJECT_TYPE<span style="COLOR: #0000cc">]</span> <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000cc">{</span> 0 <span style="COLOR: #0000cc">}</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">void</span><span style="COLOR: #0000cc">*</span> s_base <span style="COLOR: #0000cc">=</span> <span style="COLOR: #ff0000">NULL</span><span style="COLOR: #0000cc">;</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000ff">int</span> mp_register_usage<span style="COLOR: #0000cc">(</span> <span style="COLOR: #ff0000">size_t</span> size<span style="COLOR: #0000cc">,</span> <span style="COLOR: #ff0000">size_t</span> <span style="COLOR: #ff0000">count</span> <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> size <span style="COLOR: #0000cc">=</span><span style="COLOR: #0000cc">=</span> 0 <span style="COLOR: #0000cc">|</span><span style="COLOR: #0000cc">|</span> <span style="COLOR: #ff0000">count</span> <span style="COLOR: #0000cc">=</span><span style="COLOR: #0000cc">=</span> 0 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> <span style="COLOR: #0000cc">-</span>1<span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;size <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">=</span> MEMORY_ALLOCATION_ALIGNMENT <span style="COLOR: #0000cc">-</span> 1<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;size <span style="COLOR: #0000cc">/</span><span style="COLOR: #0000cc">=</span> MEMORY_ALLOCATION_ALIGNMENT<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;size <span style="COLOR: #0000cc">*</span><span style="COLOR: #0000cc">=</span> MEMORY_ALLOCATION_ALIGNMENT<span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">for</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">int</span> i <span style="COLOR: #0000cc">=</span> 0<span style="COLOR: #0000cc">;</span> i <span style="COLOR: #0000cc">&lt;</span> MP_MAX_OBJECT_TYPE<span style="COLOR: #0000cc">;</span> <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">+</span>i <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MP_OBJECT_ENTRY<span style="COLOR: #0000cc">*</span> entry <span style="COLOR: #0000cc">=</span> s_entries <span style="COLOR: #0000cc">+</span> i<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>size <span style="COLOR: #0000cc">=</span><span style="COLOR: #0000cc">=</span> size <span style="COLOR: #0000cc">|</span><span style="COLOR: #0000cc">|</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>size <span style="COLOR: #0000cc">=</span><span style="COLOR: #0000cc">=</span> 0 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>size <span style="COLOR: #0000cc">=</span> size<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #ff0000">count</span> <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">=</span> <span style="COLOR: #ff0000">count</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> i<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> <span style="COLOR: #0000cc">-</span>1<span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">//------------------------------------------------------------------------------<br></span><br><span style="COLOR: #0000ff">bool</span> mp_create<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">size_t</span> total <span style="COLOR: #0000cc">=</span> 0<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">for</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">int</span> i <span style="COLOR: #0000cc">=</span> 0<span style="COLOR: #0000cc">;</span> i <span style="COLOR: #0000cc">&lt;</span> MP_MAX_OBJECT_TYPE<span style="COLOR: #0000cc">;</span> <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">+</span>i <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;total <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">=</span> s_entries<span style="COLOR: #0000cc">[</span>i<span style="COLOR: #0000cc">]</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #ff0000">count</span> <span style="COLOR: #0000cc">*</span> s_entries<span style="COLOR: #0000cc">[</span>i<span style="COLOR: #0000cc">]</span><span style="COLOR: #0000cc">.</span>size<span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;s_base <span style="COLOR: #0000cc">=</span> VirtualAlloc<span style="COLOR: #0000cc">(</span> <span style="COLOR: #ff0000">NULL</span><span style="COLOR: #0000cc">,</span> total<span style="COLOR: #0000cc">,</span> MEM_COMMIT<span style="COLOR: #0000cc">,</span> PAGE_READWRITE <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> s_base <span style="COLOR: #0000cc">=</span><span style="COLOR: #0000cc">=</span> <span style="COLOR: #ff0000">NULL</span> <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> <span style="COLOR: #0000ff">false</span><span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">char</span><span style="COLOR: #0000cc">*</span> base <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000ff">reinterpret_cast</span><span style="COLOR: #0000cc">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #0000cc">*</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">(</span> s_base <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">for</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">int</span> i <span style="COLOR: #0000cc">=</span> 0<span style="COLOR: #0000cc">;</span> i <span style="COLOR: #0000cc">&lt;</span> MP_MAX_OBJECT_TYPE<span style="COLOR: #0000cc">;</span> <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">+</span>i <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MP_OBJECT_ENTRY<span style="COLOR: #0000cc">*</span> entry <span style="COLOR: #0000cc">=</span> s_entries <span style="COLOR: #0000cc">+</span> i<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeSListHead<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000cc">&amp;</span>entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>lsthdr <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">char</span><span style="COLOR: #0000cc">*</span> addr <span style="COLOR: #0000cc">=</span> base <span style="COLOR: #0000cc">+</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>size <span style="COLOR: #0000cc">*</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #ff0000">count</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addr <span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">=</span> MEMORY_ALLOCATION_ALIGNMENT<span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">for</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #ff0000">size_t</span> j <span style="COLOR: #0000cc">=</span> 0<span style="COLOR: #0000cc">;</span> j <span style="COLOR: #0000cc">&lt;</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #ff0000">count</span><span style="COLOR: #0000cc">;</span> <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">+</span>j <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SLIST_ENTRY<span style="COLOR: #0000cc">*</span> node <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000ff">reinterpret_cast</span><span style="COLOR: #0000cc">&lt;</span>SLIST_ENTRY<span style="COLOR: #0000cc">*</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">(</span> addr <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InterlockedPushEntrySList<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000cc">&amp;</span>entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>lsthdr<span style="COLOR: #0000cc">,</span> node <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addr <span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">=</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>size<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;base <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">=</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #ff0000">count</span> <span style="COLOR: #0000cc">*</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>size<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> <span style="COLOR: #0000ff">true</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">//------------------------------------------------------------------------------<br></span><br><span style="COLOR: #0000ff">void</span> mp_destory<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> s_base <span style="COLOR: #0000cc">!</span><span style="COLOR: #0000cc">=</span> <span style="COLOR: #ff0000">NULL</span> <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VirtualFree<span style="COLOR: #0000cc">(</span> s_base<span style="COLOR: #0000cc">,</span> 0<span style="COLOR: #0000cc">,</span> MEM_RELEASE <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_base <span style="COLOR: #0000cc">=</span> <span style="COLOR: #ff0000">NULL</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">//------------------------------------------------------------------------------<br></span><br><span style="COLOR: #0000ff">void</span><span style="COLOR: #0000cc">*</span> mp_alloc<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">int</span> objtype <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;MP_OBJECT_ENTRY<span style="COLOR: #0000cc">*</span> entry <span style="COLOR: #0000cc">=</span> s_entries <span style="COLOR: #0000cc">+</span> objtype<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;SLIST_ENTRY<span style="COLOR: #0000cc">*</span> node <span style="COLOR: #0000cc">=</span> InterlockedPopEntrySList<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000cc">&amp;</span>entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>lsthdr <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">char</span><span style="COLOR: #0000cc">*</span> p <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000ff">reinterpret_cast</span><span style="COLOR: #0000cc">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #0000cc">*</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">(</span> node <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> p <span style="COLOR: #0000cc">!</span><span style="COLOR: #0000cc">=</span> <span style="COLOR: #ff0000">NULL</span> <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p <span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">=</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>size <span style="COLOR: #0000cc">-</span> MEMORY_ALLOCATION_ALIGNMENT<span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> p<span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">//------------------------------------------------------------------------------<br></span><br><span style="COLOR: #0000ff">void</span> mp_free<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">int</span> objtype<span style="COLOR: #0000cc">,</span> <span style="COLOR: #0000ff">void</span><span style="COLOR: #0000cc">*</span> mem <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> mem <span style="COLOR: #0000cc">=</span><span style="COLOR: #0000cc">=</span> <span style="COLOR: #ff0000">NULL</span> <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span><span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;MP_OBJECT_ENTRY<span style="COLOR: #0000cc">*</span> entry <span style="COLOR: #0000cc">=</span> s_entries <span style="COLOR: #0000cc">+</span> objtype<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">char</span><span style="COLOR: #0000cc">*</span> p <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000ff">reinterpret_cast</span><span style="COLOR: #0000cc">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #0000cc">*</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">(</span> mem <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;p <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">=</span> entry<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>size <span style="COLOR: #0000cc">-</span> MEMORY_ALLOCATION_ALIGNMENT<span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;SLIST_ENTRY<span style="COLOR: #0000cc">*</span> node <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000ff">reinterpret_cast</span><span style="COLOR: #0000cc">&lt;</span>SLIST_ENTRY<span style="COLOR: #0000cc">*</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">(</span> p <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;InterlockedPushEntrySList<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000cc">&amp;</span>s_entries<span style="COLOR: #0000cc">[</span>objtype<span style="COLOR: #0000cc">]</span><span style="COLOR: #0000cc">.</span>lsthdr<span style="COLOR: #0000cc">,</span> node <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<p><br>应用举例：</p>
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="75%" bgColor=#f1f1f1>
    <tbody>
        <tr>
            <td>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000"><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000ff">template</span><span style="COLOR: #0000cc">&lt;</span><span style="COLOR: #ff0000">size_t</span> size<span style="COLOR: #0000cc">&gt;</span><br><span style="COLOR: #0000ff">class</span> CSomeObject<br><span style="COLOR: #0000cc">{</span><br><span style="COLOR: #0000ff">private</span><span style="COLOR: #0000cc">:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">int</span> s_objtype<span style="COLOR: #0000cc">;</span><br><br><span style="COLOR: #0000ff">private</span><span style="COLOR: #0000cc">:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">char</span> m_data<span style="COLOR: #0000cc">[</span>size<span style="COLOR: #0000cc">]</span><span style="COLOR: #0000cc">;</span><br><br><span style="COLOR: #0000ff">public</span><span style="COLOR: #0000cc">:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CSomeObject<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">{</span><span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">void</span> DoSomeThing<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_tprintf<span style="COLOR: #0000cc">(</span> _T<span style="COLOR: #0000cc">(</span><span style="COLOR: #ff00ff">"Object Type = %d, Object Size = %d\n"</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">,</span> s_objtype<span style="COLOR: #0000cc">,</span> size <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">~</span>CSomeObject<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">{</span><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #0000ff">public</span><span style="COLOR: #0000cc">:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">void</span> RegisterMemoryUsage<span style="COLOR: #0000cc">(</span> <span style="COLOR: #ff0000">size_t</span> <span style="COLOR: #ff0000">count</span> <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_objtype <span style="COLOR: #0000cc">=</span> mp_register_usage<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #0000cc">(</span>CSomeObject<span style="COLOR: #0000cc">&lt;</span>size<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">,</span> <span style="COLOR: #ff0000">count</span> <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">void</span><span style="COLOR: #0000cc">*</span> <span style="COLOR: #0000ff">operator</span> <span style="COLOR: #0000ff">new</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #ff0000">size_t</span> size <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> mp_alloc<span style="COLOR: #0000cc">(</span> s_objtype <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #0000ff">operator</span> <span style="COLOR: #0000ff">delete</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">void</span><span style="COLOR: #0000cc">*</span> mem <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mp_free<span style="COLOR: #0000cc">(</span> s_objtype<span style="COLOR: #0000cc">,</span> mem <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><span style="COLOR: #0000cc">}</span><span style="COLOR: #0000cc">;</span><br><br><span style="COLOR: #0000ff">template</span><span style="COLOR: #0000cc">&lt;</span><span style="COLOR: #ff0000">size_t</span> size<span style="COLOR: #0000cc">&gt;</span> <span style="COLOR: #0000ff">int</span> CSomeObject<span style="COLOR: #0000cc">&lt;</span>size<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">:</span><span style="COLOR: #0000cc">:</span>s_objtype <span style="COLOR: #0000cc">=</span> -1<span style="COLOR: #0000cc">;</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br>HANDLE g_stopevent <span style="COLOR: #0000cc">=</span> <span style="COLOR: #ff0000">NULL</span><span style="COLOR: #0000cc">;</span><br><br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">define</span> TEST_OBJECT<span style="COLOR: #0000cc">(</span> c<span style="COLOR: #0000cc">,</span> s <span style="COLOR: #0000cc">)</span> \<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">case</span> c<span style="COLOR: #0000cc">:</span><span style="COLOR: #0000cc">\</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><span style="COLOR: #0000cc">\</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CSomeObject<span style="COLOR: #0000cc">&lt;</span>s<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">*</span> p <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000ff">new</span> CSomeObject<span style="COLOR: #0000cc">&lt;</span>s<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">;</span><span style="COLOR: #0000cc">\</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> p <span style="COLOR: #0000cc">!</span><span style="COLOR: #0000cc">=</span> <span style="COLOR: #ff0000">NULL</span> <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">\</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><span style="COLOR: #0000cc">\</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>DoSomeThing<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><span style="COLOR: #0000cc">\</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">delete</span> p<span style="COLOR: #0000cc">;</span><span style="COLOR: #0000cc">\</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><span style="COLOR: #0000cc">\</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><span style="COLOR: #0000cc">\</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">break</span><span style="COLOR: #0000cc">;</span><br><br><span style="COLOR: #ff0000">uintptr_t</span> __stdcall worker_thread<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">void</span><span style="COLOR: #0000cc">*</span> <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">srand</span><span style="COLOR: #0000cc">(</span> GetTickCount<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">while</span><span style="COLOR: #0000cc">(</span> WaitForSingleObject<span style="COLOR: #0000cc">(</span> g_stopevent<span style="COLOR: #0000cc">,</span> 0 <span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">=</span><span style="COLOR: #0000cc">=</span> WAIT_TIMEOUT <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">switch</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #ff0000">rand</span><span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">%</span> 7 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TEST_OBJECT<span style="COLOR: #0000cc">(</span> 0<span style="COLOR: #0000cc">,</span> 1 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TEST_OBJECT<span style="COLOR: #0000cc">(</span> 1<span style="COLOR: #0000cc">,</span> 9 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TEST_OBJECT<span style="COLOR: #0000cc">(</span> 2<span style="COLOR: #0000cc">,</span> 10 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TEST_OBJECT<span style="COLOR: #0000cc">(</span> 3<span style="COLOR: #0000cc">,</span> 20 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TEST_OBJECT<span style="COLOR: #0000cc">(</span> 4<span style="COLOR: #0000cc">,</span> 36 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TEST_OBJECT<span style="COLOR: #0000cc">(</span> 5<span style="COLOR: #0000cc">,</span> 100 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TEST_OBJECT<span style="COLOR: #0000cc">(</span> 6<span style="COLOR: #0000cc">,</span> 1000 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> 0<span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000ff">int</span> _tmain<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">int</span> argc<span style="COLOR: #0000cc">,</span> _TCHAR<span style="COLOR: #0000cc">*</span> argv<span style="COLOR: #0000cc">[</span><span style="COLOR: #0000cc">]</span> <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CSomeObject<span style="COLOR: #0000cc">&lt;</span>1<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">:</span><span style="COLOR: #0000cc">:</span>RegisterMemoryUsage<span style="COLOR: #0000cc">(</span> 100 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CSomeObject<span style="COLOR: #0000cc">&lt;</span>9<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">:</span><span style="COLOR: #0000cc">:</span>RegisterMemoryUsage<span style="COLOR: #0000cc">(</span> 2 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CSomeObject<span style="COLOR: #0000cc">&lt;</span>10<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">:</span><span style="COLOR: #0000cc">:</span>RegisterMemoryUsage<span style="COLOR: #0000cc">(</span> 100 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CSomeObject<span style="COLOR: #0000cc">&lt;</span>20<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">:</span><span style="COLOR: #0000cc">:</span>RegisterMemoryUsage<span style="COLOR: #0000cc">(</span> 200 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CSomeObject<span style="COLOR: #0000cc">&lt;</span>36<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">:</span><span style="COLOR: #0000cc">:</span>RegisterMemoryUsage<span style="COLOR: #0000cc">(</span> 300 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CSomeObject<span style="COLOR: #0000cc">&lt;</span>100<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">:</span><span style="COLOR: #0000cc">:</span>RegisterMemoryUsage<span style="COLOR: #0000cc">(</span> 205 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CSomeObject<span style="COLOR: #0000cc">&lt;</span>1000<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">:</span><span style="COLOR: #0000cc">:</span>RegisterMemoryUsage<span style="COLOR: #0000cc">(</span> 128 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;mp_create<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;g_stopevent <span style="COLOR: #0000cc">=</span> CreateEvent<span style="COLOR: #0000cc">(</span> <span style="COLOR: #ff0000">NULL</span><span style="COLOR: #0000cc">,</span> <span style="COLOR: #0000ff">TRUE</span><span style="COLOR: #0000cc">,</span> <span style="COLOR: #0000ff">FALSE</span><span style="COLOR: #0000cc">,</span> <span style="COLOR: #ff0000">NULL</span> <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">for</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">int</span> i <span style="COLOR: #0000cc">=</span> 0<span style="COLOR: #0000cc">;</span> i <span style="COLOR: #0000cc">&lt;</span> 10<span style="COLOR: #0000cc">;</span> <span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">+</span>i <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">uintptr_t</span> h <span style="COLOR: #0000cc">=</span> _beginthreadex<span style="COLOR: #0000cc">(</span> <span style="COLOR: #ff0000">NULL</span><span style="COLOR: #0000cc">,</span> 0<span style="COLOR: #0000cc">,</span> worker_thread<span style="COLOR: #0000cc">,</span> <span style="COLOR: #ff0000">NULL</span><span style="COLOR: #0000cc">,</span> 0<span style="COLOR: #0000cc">,</span> <span style="COLOR: #ff0000">NULL</span> <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">reinterpret_cast</span><span style="COLOR: #0000cc">&lt;</span>HANDLE<span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">(</span> h <span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;_getch<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;SetEvent<span style="COLOR: #0000cc">(</span> g_stopevent <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">Sleep</span><span style="COLOR: #0000cc">(</span> 500 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle<span style="COLOR: #0000cc">(</span> g_stopevent <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;mp_destory<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> 0<span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br><img src="http://blog.vckbase.com/localvar/aggbug/51946.html" width=1 height=1> 
<img src ="http://www.cppblog.com/localvar/aggbug/132765.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/localvar/" target="_blank">局部变量</a> 2010-10-28 17:45 <a href="http://www.cppblog.com/localvar/archive/2010/10/28/132765.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决了一个困惑很久的bug</title><link>http://www.cppblog.com/localvar/archive/2009/01/08/132767.html</link><dc:creator>局部变量</dc:creator><author>局部变量</author><pubDate>Thu, 08 Jan 2009 08:58:00 GMT</pubDate><guid>http://www.cppblog.com/localvar/archive/2009/01/08/132767.html</guid><description><![CDATA[<p>让这个bug困扰了很久，前一段太忙只找了个临时解决方案而没有追究原因，今天终于把它搞清楚了。由于测试时只在多cpu系统上出现，我甚至一度怀疑它是cpu的bug<img title=大汗 alt=大汗 src="http://vckbase.com/bbs/image/emimg/010.gif"> 。</p>
<p>两个c/s结构的网络通讯程序，服务器端使用完成端口模型，客户端使用阻塞模型，双方以一种客户端发送命令，服务器端处理，然后返回应答的方式通讯。问题出在服务器端。以下是服务器端代码的大致处理逻辑：</p>
<pre><span style="COLOR: #0000ff">long</span> <span style="COLOR: #0000ff">volatile</span> g_busy = 0;
<span style="COLOR: #0000ff">void</span> iocp_thread()
{
<span style="COLOR: #0000ff">while</span>( GetQueuedCompletionStatus() )
{
<span style="COLOR: #0000ff">if</span>( InterlockedCompareExchange( &amp;g_busy, 1, 0 ) != 0 )
WSASend( "<span style="COLOR: #8b0000">服务器忙</span>" );
<span style="COLOR: #008000">// 处理命令</span>
ProcessCommand();
WSASend( "<span style="COLOR: #8b0000">应答信息</span>" );
InterlockedExchange( &amp;g_busy, 0 );
}
}</pre>
<p>其中ProcessCommand需要互斥运行（这是简化的逻辑，实际上有很多不同的命令，有些需要互斥，有些可以并行，否则就没必要用完成端口了），并且需要一定的时间才能处理完毕。为了避免多个客户端同时执行命令，导致所有的iocp线程都等在那，我把g_busy当成了一个锁，第一个线程可以成功进入，其它的都直接向客户端返回&#8220;服务器忙&#8221;。</p>
<p>程序一直都运行的很好，直到有一天把服务器程序装到了一台有双核cpu的机器上。我发现，如果让客户端连续发送命令，即收到上一条命令的应答后立即发送下一条命令，就会随机的返回&#8220;服务器忙&#8221;，而这时只有一个客户端连接上去，按照我设想的逻辑是不可能出这种情况的。检查了半天代码，没觉得有什么问题，调试吧，又遇到了另一个难题，海森堡的测不准原理起作用了，做的工作太多问题就消失了，做的太少又得不到什么有价值的信息。搞得我很是头疼。</p>
<p>今天再次看这个问题，突然想到：它肯定和线程切换相关，所以我应该记录下每次处理命令的线程的ID，这样出错时就可以看看上次成功执行命令的那个线程在干什么了。方法正确了，问题也就迎刃而解了，我发现，出问题时，上一个线程的WSASend居然还没有返回，也就是说，客户端已经收到应答并发送了下一条命令，服务器端也收到了命令并准备处理，但上一条命令的应答却还没有完全发送完成，难怪出错了！</p>
<p>总结经验教训，感觉自己一开始被两点给误导了，一是实际程序中的WSARecv/WSASend藏的比较深，没这么明显，所以没注意到。二是当时粗略检查代码觉得没问题，就把主要精力放在ProcessCommand上了，由于我把它里面一段访问sql server的代码注释掉以后，问题就不出了，所以还看了半天atl oledb的源码，最后精疲力尽，其它事情又比较多就放弃了。</p>
<img src="http://blog.vckbase.com/localvar/aggbug/36194.html" width=1 height=1> 
<img src ="http://www.cppblog.com/localvar/aggbug/132767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/localvar/" target="_blank">局部变量</a> 2009-01-08 16:58 <a href="http://www.cppblog.com/localvar/archive/2009/01/08/132767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>锁？不锁？如何锁？</title><link>http://www.cppblog.com/localvar/archive/2007/10/15/132762.html</link><dc:creator>局部变量</dc:creator><author>局部变量</author><pubDate>Mon, 15 Oct 2007 01:46:00 GMT</pubDate><guid>http://www.cppblog.com/localvar/archive/2007/10/15/132762.html</guid><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; 加锁、解锁(同步/互斥)是多线程中非常基本的操作，但我却看到不少的代码对它们处理的很不好。简单说来有三类问题，一是加锁范围太大，虽然避免了逻辑错误，但锁了不该锁的东西，难免降低程序的效率；二是该锁的不锁，导致各种莫名其妙的错误；三是加锁方式不合适，该用临界区的用内核对象等，也会降低程序的效率。<br>&nbsp;&nbsp;&nbsp; 要正确的运用锁操作，首先要弄清楚什么时候需要加锁。很多书上都说在可能&#8220;同时发生多个写操作&#8221;或&#8220;同时发生读写操作&#8221;时，应该加锁。这固然没什么错，但我认为它没有说到问题的根上，更准确的表述应该是：如果不加锁会导致不可容忍的数据不一致，那么就应该加锁。据此，我在下表中列出了多线程中应该加锁和无需加锁的条件，其中的&#8220;简单数据类型&#8221;是指cpu可以在一条指令中完成操作的数据类型，一般整形和所有比整形小的数据类型都是，除此之外的类型都属于&#8220;复杂数据类型&#8221;，例如你自己定义的结构体等。<br>
<table style="WIDTH: 590px; HEIGHT: 87px" border=1 cellSpacing=1 cellPadding=1 width=590>
    <tbody>
        <tr>
            <td>&nbsp;</td>
            <td>&nbsp;操作的结果与初值无关</td>
            <td>&nbsp;操作的结果与初值相关</td>
        </tr>
        <tr>
            <td>&nbsp;写简单数据类型</td>
            <td>&nbsp;不需要加锁①</td>
            <td>&nbsp;需要加锁②</td>
        </tr>
        <tr>
            <td>&nbsp;写复杂数据类型</td>
            <td>&nbsp;需要加锁③</td>
            <td>&nbsp;需要加锁④</td>
        </tr>
        <tr>
            <td>&nbsp;读简单数据类型</td>
            <td>&nbsp;不需要加锁⑤</td>
            <td>&nbsp;不需要加锁⑥</td>
        </tr>
        <tr>
            <td>&nbsp;读复杂数据类型</td>
            <td>&nbsp;需要加锁⑦</td>
            <td>&nbsp;需要加锁⑧</td>
        </tr>
    </tbody>
</table>
</div>
&nbsp;&nbsp;&nbsp; 大家可能注意到，在第1、5、6种情况下，我认为可以不加锁，粗看起来，这与书上的说法有些矛盾。其实却不然，因为这些操作可以在一条指令内完成，所以它们具有天然的&#8220;原子性&#8221;，我们可以认为cpu已经给它们加锁了，我们没必要再画蛇添足。如果这个理由还不够的话，你不妨想一下我们再加一次锁是否有用，看下面的代码(以第1种情况为例)：
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="75%" bgColor=#f1f1f1>
    <tbody>
        <tr>
            <td>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000">Lock<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span> <span style="COLOR: #ff9900">// ①<br></span>n <span style="COLOR: #0000cc">=</span> 10<span style="COLOR: #0000cc">;</span> <span style="COLOR: #ff9900">// ②<br></span>Unlock<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span> <span style="COLOR: #ff9900">// ③<br></span><span style="COLOR: #0000ff">int</span> x <span style="COLOR: #0000cc">=</span> n<span style="COLOR: #0000cc">;</span> <span style="COLOR: #ff9900">// ④</span></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
看出来了吗？不管语句①③是否存在，这段代码执行完毕后，我们都无法保证x的值是10。也许你会想如果把③④两条语句的位置换一下，x就肯定是10了。可是在这个例子中，想让x是10，为什么不把语句④直接换成&#8220;int x = 10;&#8221;呢？既省了加锁，有减少了键盘的磨损，何乐而不为？！而且，我的这个例子并不是刻意构造的，在多线程，这种情况比比皆是。 <br>&nbsp;&nbsp;&nbsp; 第2种情况的典型代表是&#8220;i++;&#8221;，需要对它加锁是因为它表面上虽然只有一条语句，却要执行至少两个操作，一是读出i的初始, 二是把加一后的结果写回去，两个操作就没有&#8220;原子性&#8221;了，所以需要加锁。<br>&nbsp;&nbsp;&nbsp; 另外，上表中判断是否需要加锁的依据是&#8220;是否可能造成数据不一致&#8221;。实际上，有些情况下数据不一致是可以容忍的,如果它发生概率极低、造成的不良后果可以忽略、并能很快自动恢复，那它可能就是可以容忍的。对这种数据不一致，我们可以不加锁。不过对它的判定与程序的实际情况关联太大，我们在这里就不讨论了。<br>&nbsp;&nbsp;&nbsp; 加锁的方法也可分为三类，临界区、内核对象和互锁函数。相比前两类，互锁函数的知名度要低不少，但它却是我用的最多的方法，因为它有一个最大的优点：快！有不少书上比较临界区和内核对象时都说临界区的优点是不会进入内核模式，速度快。不过这是不全面的，如果没有冲突(实际发生冲突的概率一般很低)，临界区确实不会进内核模式，但如果发生了冲突要进行等待，它就要依靠内核对象了。而互锁函数则绝不会进内核模式，所以互锁函数是最快的(临界区在没有冲突时的行为是依靠互锁函数实现的)。互锁函数的缺点是只能处理相对简单的数据类型(不要和我前面说的&#8220;简单数据类型&#8221;等价起来)，但另一方面，对加锁需求最高的也往往是这些类型的数据。<br>&nbsp;&nbsp;&nbsp; 实际开发中，还有一种锁比较常用，这就是单写多读锁，《windows核心编程》上有一个单写多读锁的实现，我的blog上有另一个实现。前者适用于需加锁的对象数量较少(例如如只有一个)，访问冲突概率相对较高的情况。后者适用于需加锁的对象很多，访问冲突概率很低的情况(对象多了, 单个对象的访问冲突自然就少了)。两个实现的共同缺点是不支持重入，即同一个线程中，解锁前不能再次加锁。临界区在这方面有优势，它支持重入。使用TLS(线程局部存储)技术进行改进应该能让它们支持重入，不过这样做了以后我那个实现应该就算不上轻量级了:)。<br>&nbsp;&nbsp;&nbsp; 最后，还有其它的一些不用锁的方法也可以保证多线程中的数据一致性，其中最常用的就是循环。例如下面的例子：<br>
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="75%" bgColor=#f1f1f1>
    <tbody>
        <tr>
            <td>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000"><span style="COLOR: #0000ff">struct</span> bar<br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">volatile</span> <span style="COLOR: #0000ff">unsigned</span> version<span style="COLOR: #0000cc">;</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff9900">// 一个额外的版本号字段<br></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">int</span> field1<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">char</span> field2<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">char</span> field3<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><br><span style="COLOR: #0000cc">}</span><span style="COLOR: #0000cc">;</span><br>bar g_bar <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000cc">{</span> 0 <span style="COLOR: #0000cc">}</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #ff9900"></span></span></code></p>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000"><span style="COLOR: #ff9900">// 写线程<br></span><span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">+</span>g_bar<span style="COLOR: #0000cc">.</span>version<span style="COLOR: #0000cc">;</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff9900">// 加1, version是奇数, 表示正在更新<br></span>g_bar<span style="COLOR: #0000cc">.</span>field1 <span style="COLOR: #0000cc">=</span> 10<span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><br><span style="COLOR: #0000cc">+</span><span style="COLOR: #0000cc">+</span>g_bar<span style="COLOR: #0000cc">.</span>version<span style="COLOR: #0000cc">;</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff9900">// 再加1, version是偶数, 表示更新完毕<br></span><br><span style="COLOR: #ff9900">// 读线程<br></span><span style="COLOR: #0000ff">void</span> ReadGlobalBar<span style="COLOR: #0000cc">(</span> bar<span style="COLOR: #0000cc">*</span> p <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">unsigned</span> ver<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">do</span> <span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ver <span style="COLOR: #0000cc">=</span> g_bar<span style="COLOR: #0000cc">.</span>version<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> ver <span style="COLOR: #0000cc">%</span> 2 <span style="COLOR: #0000cc">!</span><span style="COLOR: #0000cc">=</span> 0 <span style="COLOR: #0000cc">)</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff9900">// 正在更新<br></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">Sleep</span><span style="COLOR: #0000cc">(</span> 0 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff9900">// 等待<br></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">continue</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p<span style="COLOR: #0000cc">-</span><span style="COLOR: #0000cc">&gt;</span>field1 <span style="COLOR: #0000cc">=</span> g_bar<span style="COLOR: #0000cc">.</span>field1<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><span style="COLOR: #0000cc">.</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span> <span style="COLOR: #0000ff">while</span><span style="COLOR: #0000cc">(</span> ver <span style="COLOR: #0000cc">!</span><span style="COLOR: #0000cc">=</span> g_bar<span style="COLOR: #0000cc">.</span>version <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span></span></code></p>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000"><font face=新宋体><span style="COLOR: #0000cc">}</span></font></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
然而这种方法真的没用锁吗？看你怎么理解了，那个version字段其实就可以看做是锁的。不过它只是半个锁，因为它只锁了读操作，而没锁写操作，也就是说写操作可以随时进行而无需等待。如果读操作非常多，但写操作较少，并且你不希望写操作经常被打断，那它正好满足你的要求。它的缺点是你要保证系统中某个时刻最多有一个&#8220;writer&#8221;，&#8220;writer&#8221;一多，它就的无能为力了(这时一般应该用单写多读锁)。
<div><br><strong>2007.10.18：补充一点，关于acquire release semantics</strong><br>&nbsp;&nbsp; 在多处理器平台上，一个处理器的实际的操作顺序，和其它处理器所看到的它的操作顺序可能并不相同，例如：<br>a++;<br>b++;<br>在其他处理器看来，很有可能&#8220;b++&#8221;发生在前面，而&#8220;a++&#8221;发生在后面。某些情况下，其他处理器看到的顺序必须和实际的顺序保持一致，所以就需要引入acquire semantics和release semantics了。<br>&nbsp;&nbsp; 说一个操作具有acquire semantics，就表示可以保证其它处理器在看到这一操作的结果前，不会看到(该处理器上)后续操作的结果，对该处理器而言，可以理解为它进行此操作前，不会进行后续操作；而一个操作具有release semantics，就表示可以保证其它处理器在看到这一操作的结果前，能看到(该处理器)上先前所有操作的结果，对该处理器而言，可以理解为在完成所有先前的操作之前，不会进行此操作。<br>&nbsp;&nbsp; vc编译器(其它编译器不一定保证)保证对volatile对象的写操作具有release semantics；对volatile对象的读操作具有acquire semantics。基于此点保证，多线程环境中就可以用volatile型对象实现锁操作了。<br><br><a id=CategoryEntryList1_EntryStoryList_Entries__ctl12_TitleUrl href="http://www.cppblog.com/localvar/archive/2005/10/22/13826.html"><font color=#006666>对windows互锁函数的补充</font></a><br><a id=CategoryEntryList1_EntryStoryList_Entries__ctl6_TitleUrl href="http://www.cppblog.com/localvar/archive/2007/01/23/24160.html"><font color=#006666>一个轻量级的单写多读锁</font></a></div>
<img src="http://blog.vckbase.com/localvar/aggbug/29995.html" width=1 height=1> 
<img src ="http://www.cppblog.com/localvar/aggbug/132762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/localvar/" target="_blank">局部变量</a> 2007-10-15 09:46 <a href="http://www.cppblog.com/localvar/archive/2007/10/15/132762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个轻量级的单写多读锁</title><link>http://www.cppblog.com/localvar/archive/2007/01/23/132735.html</link><dc:creator>局部变量</dc:creator><author>局部变量</author><pubDate>Tue, 23 Jan 2007 12:41:00 GMT</pubDate><guid>http://www.cppblog.com/localvar/archive/2007/01/23/132735.html</guid><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; 与《windows核心编程》上的那个相比最大的优势是体积小, 它只有四个字节(《windows核心编程》上的那个至少是它的10倍), 如果你有大量对象需要进行单写多读访问的话, 它会比较适用. 缺点是它在加锁时使用的等待函数是Sleep, 如果访问冲突很多的话, 效率比较低. 代码如下(很简单, 就不多做解释了):<br></div>
<div><br><font color=#ff0000>发现代码里有个bug，参见<a href="http://www.cppblog.com/localvar/archive/2008/01/08/132759.html">http://www.cppblog.com/localvar/archive/2008/01/08/132759.html</a></font><font color=#ff0000>的第二条</font><font color=#ff0000>。时间有限，我暂时不改了，请大家自己注意一下。</font><br></div>
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="75%" bgColor=#f1f1f1>
    <tbody>
        <tr>
            <td>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000"><span style="COLOR: #ff9900">// 头文件<br></span><br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">ifndef</span> SWMR_LOCK_H<br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">define</span> SWMR_LOCK_H<br><br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">ifndef</span> SWMR_LOCK_NUMBER_OF_WRITER<br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">define</span> SWMR_LOCK_NUMBER_OF_WRITER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">endif</span> <span style="COLOR: #ff9900">// SWMR_LOCK_NUMBER_OF_WRITER<br></span><br><span style="COLOR: #0000ff">typedef</span> <span style="COLOR: #0000ff">volatile</span> <span style="COLOR: #0000ff">long</span> SWMR_LOCK<br><br><span style="COLOR: #0000ff">void</span> SwmrLockInitialize<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">void</span> SwmrLockWriteLock<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">void</span> SwmrLockWriteUnlock<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">void</span> SwmrLockReadLock<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">void</span> SwmrLockReadUnlock<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000ff">void</span> SwmrLockUninitialize<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">endif</span> </span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<p>--------------------------------------------------------------------------------</p>
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="75%" bgColor=#f1f1f1>
    <tbody>
        <tr>
            <td>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000"><span style="COLOR: #ff9900">// 实现文件<br></span><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">include</span> <span style="COLOR: #ff00ff">"srmrl.h"</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">define</span> WRITING_FLAG&nbsp;&nbsp;&nbsp;&nbsp;0x40000000<br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000ff">void</span> SwmrLockInitialize<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">*</span>pLock <span style="COLOR: #0000cc">=</span> 0<span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000ff">void</span> SwmrLockWriteLock<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">long</span> old<span style="COLOR: #0000cc">,</span> xchg<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">do</span> <span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;old <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000cc">*</span>pLock<span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">#</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> SWMR_LOCK_NUMBER_OF_WRITER <span style="COLOR: #0000cc">&gt;</span> 1 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> old <span style="COLOR: #0000cc">&amp;</span> WRITING_FLAG <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">Sleep</span><span style="COLOR: #0000cc">(</span> 0 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">continue</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><span style="COLOR: #0000cc">#</span><span style="COLOR: #ff0000">endif</span> <span style="COLOR: #ff9900">// ( SWMR_LOCK_NUMBER_OF_WRITER &gt; 1 )<br></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xchg <span style="COLOR: #0000cc">=</span> old <span style="COLOR: #0000cc">|</span> WRITING_FLAG<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span> <span style="COLOR: #0000ff">while</span><span style="COLOR: #0000cc">(</span> _InterlockedCompareExchange<span style="COLOR: #0000cc">(</span> pLock<span style="COLOR: #0000cc">,</span> xchg<span style="COLOR: #0000cc">,</span> old <span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">!</span><span style="COLOR: #0000cc">=</span> old <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff9900">// wait until all readers quit reading<br></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">while</span><span style="COLOR: #0000cc">(</span> old <span style="COLOR: #0000cc">!</span><span style="COLOR: #0000cc">=</span> WRITING_FLAG <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">Sleep</span><span style="COLOR: #0000cc">(</span> 0 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;old <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000cc">*</span>pLock<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000ff">void</span> SwmrLockWriteUnlock<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">*</span>pLock <span style="COLOR: #0000cc">=</span> 0<span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000ff">void</span> SwmrLockReadLock<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">long</span> old<span style="COLOR: #0000cc">,</span> xchg<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">do</span> <span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;old <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000cc">*</span>pLock<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> old <span style="COLOR: #0000cc">&amp;</span> WRITING_FLAG <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000">Sleep</span><span style="COLOR: #0000cc">(</span> 0 <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">continue</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xchg <span style="COLOR: #0000cc">=</span> old <span style="COLOR: #0000cc">+</span> 1<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span> <span style="COLOR: #0000ff">while</span><span style="COLOR: #0000cc">(</span> _InterlockedCompareExchange<span style="COLOR: #0000cc">(</span> pLock<span style="COLOR: #0000cc">,</span> xchg<span style="COLOR: #0000cc">,</span> old <span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">!</span><span style="COLOR: #0000cc">=</span> old <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000ff">void</span> SwmrLockReadUnlock<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;_InterlockedDecrement<span style="COLOR: #0000cc">(</span> pLock <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br><span style="COLOR: #0000cc">}</span><br><br><span style="COLOR: #ff9900">////////////////////////////////////////////////////////////////////////////////<br></span><br><span style="COLOR: #0000ff">void</span> SwmrLockUninitialize<span style="COLOR: #0000cc">(</span> SWMR_LOCK<span style="COLOR: #0000cc">*</span> pLock <span style="COLOR: #0000cc">)</span><br><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;pLock<span style="COLOR: #0000cc">;</span> <span style="COLOR: #ff9900">// has nothing to do<br></span><br><span style="COLOR: #0000cc">}</span></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<div></div>
<div></div>
<div></div>
<img src="http://blog.vckbase.com/localvar/aggbug/24160.html" width=1 height=1> 
<img src ="http://www.cppblog.com/localvar/aggbug/132735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/localvar/" target="_blank">局部变量</a> 2007-01-23 20:41 <a href="http://www.cppblog.com/localvar/archive/2007/01/23/132735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一种引用计数机制的实现</title><link>http://www.cppblog.com/localvar/archive/2006/11/26/132737.html</link><dc:creator>局部变量</dc:creator><author>局部变量</author><pubDate>Sun, 26 Nov 2006 08:49:00 GMT</pubDate><guid>http://www.cppblog.com/localvar/archive/2006/11/26/132737.html</guid><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; 毫无疑问, 引用计数是一种非常有效的动态控制对象生命周期的机制. 我们最熟悉的引用计数实现可能就要数COM的AddRef和Release了. 但这种机制也有明显的缺点, 那就是无法实现对对象死亡时间的精确控制: 调用Release后, 就失去了对对象的控制, 虽然对象可能会被立即杀掉, 但我们无法保证这一点. 也许程序的其他地方还对它拥有引用, 并且还会有一系列的AddRef和Release, 而只要计数不降到0, 对象就一直活着, 甚至可能比你我更长寿<img border=0 src="http://www.cppblog.com/Emoticons/QQ/15.gif" width=20 height=20>.</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; 为了更好的说明这一点, 请考虑下面的情况: 我们有某种类型的对象, 这种对象在程序运行过程中会不断的被创建和杀死, 而所有活着的对象都被放在一个全局表格中. 由于表格拥有一个对象的引用, 所以表格中不被程序其它部分使用的对象的计数将为1. 当程序要访问某个对象时, 就会通过一个键值从表格中找到它, 递增其引用计数, 待访问完毕后, 再递减计数. 从以上可以看出, 我们要想杀掉一个对象, 只要去掉表格对它的引用(也就是把引用计数减一)就可以了. 但这并不能确保对象被杀死, 因为程序的其它地方仍能从表格中找到它, 并增加其计数; 更进一步, 我们可以在去掉表格的引用后, 把对象从表格中删除, 这样计数就不会增加了, 但很不幸, 我们并不是在任何时候都能这样做, 有些时候没有"彻底死亡"的对象是不能从表格中删除的.</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; 那有没有两全其美的方法呢? 应该说还是有的. 引用计数通常用一个32位整数来表示, 它最大能支持几十亿个引用, 但实践上, 能达到的最大值要远小于这个数字, 所以, 我们可以把其中的某些位挪作它用, 用来表示对象是否已经被杀掉, 而不能再增加新的引用. 看下面的实现:</div>
<div>&nbsp;</div>
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="75%" bgColor=#f1f1f1>
    <tbody>
        <tr>
            <td>
            <p style="LINE-HEIGHT: 150%; MARGIN: 5px"><code><span style="COLOR: #000000"><span style="COLOR: #0000ff">template</span><span style="COLOR: #0000cc">&lt;</span><span style="COLOR: #0000ff">class</span> T<span style="COLOR: #0000cc">&gt;</span><br><span style="COLOR: #0000ff">class</span> CRefCount<br><span style="COLOR: #0000cc">{</span><br><span style="COLOR: #0000ff">private</span><span style="COLOR: #0000cc">:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff9900">// 使用第30位作为生存标志位, 你可以改成其它位, 但千万不要用了符号位<br></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">const</span> <span style="COLOR: #0000ff">LONG</span> s_lAliveFlag <span style="COLOR: #0000cc">=</span> 0x40000000<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">volatile</span> <span style="COLOR: #0000ff">LONG</span> m_lRef<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<br><span style="COLOR: #0000ff">public</span><span style="COLOR: #0000cc">:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;CRefCount<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">:</span> m_lRef<span style="COLOR: #0000cc">(</span> s_lAliveFlag <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">bool</span> AddRef<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">LONG</span> lRef<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">do</span><span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lRef <span style="COLOR: #0000cc">=</span> m_lRef<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff9900">// 已经死亡了, 增加引用失败<br></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000cc">(</span>lRef <span style="COLOR: #0000cc">&amp;</span> s_lAliveFlag<span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">=</span><span style="COLOR: #0000cc">=</span> 0 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> <span style="COLOR: #0000ff">false</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span> <span style="COLOR: #0000ff">while</span><span style="COLOR: #0000cc">(</span> InterlockedCompareExchange<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">&amp;</span>m_lRef<span style="COLOR: #0000cc">,</span> lRef<span style="COLOR: #0000cc">+</span>1<span style="COLOR: #0000cc">,</span> lRef<span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">!</span><span style="COLOR: #0000cc">=</span> lRef <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span> <span style="COLOR: #0000ff">true</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">void</span> Release<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if</span><span style="COLOR: #0000cc">(</span> InterlockedDecrement<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000cc">&amp;</span>m_lRef <span style="COLOR: #0000cc">)</span> <span style="COLOR: #0000cc">=</span><span style="COLOR: #0000cc">=</span> 0 <span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T<span style="COLOR: #0000cc">*</span> pT <span style="COLOR: #0000cc">=</span> <span style="COLOR: #0000ff">static_cast</span><span style="COLOR: #0000cc">&lt;</span>T<span style="COLOR: #0000cc">*</span><span style="COLOR: #0000cc">&gt;</span><span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000ff">this</span> <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">delete</span> pT<span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">void</span> Suicide<span style="COLOR: #0000cc">(</span><span style="COLOR: #0000cc">)</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">{</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff9900">// 注意: 调用此函数前应AddRef, 这样调用之后的Release才能正确删除对象<br></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InterlockedAnd<span style="COLOR: #0000cc">(</span> <span style="COLOR: #0000cc">&amp;</span>m_lRef<span style="COLOR: #0000cc">,</span> <span style="COLOR: #0000cc">~</span>s_lActiveFlag <span style="COLOR: #0000cc">)</span><span style="COLOR: #0000cc">;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000cc">}</span><br><span style="COLOR: #0000cc">}</span><span style="COLOR: #0000cc">;</span><br></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;&nbsp;&nbsp; 程序很简单, 我就不做过多解释了, 但正像我在标题中写的, 它只是"一种引用计数的实现"方法而已, 和其他实现相比, 它既有优点, 也有缺点, 所以使用时一定要根据实际情况, 选择最合适的方法.</p>
<p><br>PS: InterlockedAnd在VS2005中是编译器的一个intrinsic, 如果你使用的编译器不支持它, 可参考我的《<a href="http://www.cppblog.com/localvar/archive/2005/10/22/132745.html" target=_blank>对windows互锁函数的补充</a>》, 自己实现一个.</p>
<img src="http://blog.vckbase.com/localvar/aggbug/23242.html" width=1 height=1> 
<img src ="http://www.cppblog.com/localvar/aggbug/132737.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/localvar/" target="_blank">局部变量</a> 2006-11-26 16:49 <a href="http://www.cppblog.com/localvar/archive/2006/11/26/132737.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对windows互锁函数的补充</title><link>http://www.cppblog.com/localvar/archive/2005/10/22/132745.html</link><dc:creator>局部变量</dc:creator><author>局部变量</author><pubDate>Sat, 22 Oct 2005 04:14:00 GMT</pubDate><guid>http://www.cppblog.com/localvar/archive/2005/10/22/132745.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp; 互锁函数是多线程处理中最简单高效的手段之一，但这些函数的功能实在是太差劲了，要求稍微复杂一点，就完成不了。比如&#8220;if( n &gt; 100 ) n++;&#8221;这么简单的功能，它们就做不到。以前，为了达到互斥的目的，我都要使用一个临界区，现在想想，这个方法简直太笨了！因为借助InterlockedCompareExchange，甚至更复杂的功能都可以轻松实现，而这个函数曾经是我认为的最没用的互锁函数。例如前面的大于某值才加1的功能就可以通过下面这个函数以原子的形式完成：<br>
<div style="BORDER-BOTTOM: windowtext 0.5pt solid; BORDER-LEFT: windowtext 0.5pt solid; PADDING-BOTTOM: 4px; PADDING-LEFT: 5.4pt; WIDTH: 98%; PADDING-RIGHT: 5.4pt; BACKGROUND: #e6e6e6; BORDER-TOP: windowtext 0.5pt solid; BORDER-RIGHT: windowtext 0.5pt solid; PADDING-TOP: 4px">
<div><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">LONG&nbsp;InterlockedBiggerExchangeAdd(&nbsp;LONG&nbsp;</span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;Addend,&nbsp;LONG&nbsp;Value,&nbsp;LONG&nbsp;Comperand&nbsp;)&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">()<br><img id=Codehighlighter1_95_266_Open_Image onclick="this.style.display='none'; Codehighlighter1_95_266_Open_Text.style.display='none'; Codehighlighter1_95_266_Closed_Image.style.display='inline'; Codehighlighter1_95_266_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_95_266_Closed_Image onclick="this.style.display='none'; Codehighlighter1_95_266_Closed_Text.style.display='none'; Codehighlighter1_95_266_Open_Image.style.display='inline'; Codehighlighter1_95_266_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_95_266_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_95_266_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;LONG&nbsp;lOrigin;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000">&nbsp;lOrigin&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">Addend;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(&nbsp;(lOrigin&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;Comperand)&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(::InterlockedCompareExchange(Addend,&nbsp;lOrigin&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;Value,&nbsp;lOrigin)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;lOrigin)&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;lOrigin;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
</div>
<p>这个函数比较*Addend和Comperand, 如果*Addend大于Comperand, 就给*Addend加上Value, 返回值则是*Addend的初值。</p>
<p>&nbsp;&nbsp;&nbsp; 仿照上面的例子，我们还可以写出InterlockedAnd、InterlockedOr和InterlockedXor的实现，这也是我以前经常抱怨的，因为系统只在ddk中提供了它们！但话说回来，这三个函数还有更简单的实现方式，因为汇编指令and、or、xor都支持lock前缀，如果直接用汇编实现的话，会更简单高效！</p>
<img src="http://blog.vckbase.com/localvar/aggbug/13826.html" width=1 height=1> 
<img src ="http://www.cppblog.com/localvar/aggbug/132745.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/localvar/" target="_blank">局部变量</a> 2005-10-22 12:14 <a href="http://www.cppblog.com/localvar/archive/2005/10/22/132745.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>