﻿<?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++博客-Error-随笔分类-cpp 1x and boost</title><link>http://www.cppblog.com/Error/category/20456.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 31 Mar 2013 15:09:32 GMT</lastBuildDate><pubDate>Sun, 31 Mar 2013 15:09:32 GMT</pubDate><ttl>60</ttl><item><title>boost::atomic 实现 spinlock</title><link>http://www.cppblog.com/Error/archive/2013/03/31/198988.html</link><dc:creator>Enic</dc:creator><author>Enic</author><pubDate>Sun, 31 Mar 2013 13:49:00 GMT</pubDate><guid>http://www.cppblog.com/Error/archive/2013/03/31/198988.html</guid><wfw:comment>http://www.cppblog.com/Error/comments/198988.html</wfw:comment><comments>http://www.cppblog.com/Error/archive/2013/03/31/198988.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Error/comments/commentRss/198988.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Error/services/trackbacks/198988.html</trackback:ping><description><![CDATA[<div style="display: inline-block; "><div><pre class="programlisting"><span class="preprocessor">先看下boost给的例子，我觉得有问题：<br /><br />#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">atomic</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>

<span class="keyword">class</span> <span class="identifier">spinlock</span> <span class="special">{</span>
<span class="keyword">private</span><span class="special">:</span>
  <span class="keyword">typedef</span> <span class="keyword">enum</span> <span class="special">{</span><span class="identifier">Locked</span><span class="special">,</span> <span class="identifier">Unlocked</span><span class="special">}</span> <span class="identifier">LockState</span><span class="special">;</span>
  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">atomic</span><span class="special">&lt;</span><span class="identifier">LockState</span><span class="special">&gt;</span> <span class="identifier">state_</span><span class="special">;</span>

<span class="keyword">public</span><span class="special">:</span>
  <span class="identifier">spinlock</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">state_</span><span class="special">(</span><span class="identifier">Unlocked</span><span class="special">)</span> <span class="special">{}</span>

  <span class="keyword">void</span> <span class="identifier">lock</span><span class="special">()</span>
  <span class="special">{<br /></span>    // 可能这里的boost::memory_order_acquire有原子操作的效果吧，偶不是很理解，不过我觉得这里应该用cae操作才对
    <span class="keyword">while</span> <span class="special">(</span><span class="identifier">state_</span><span class="special">.</span><span class="identifier">exchange</span><span class="special">(</span><span class="identifier">Locked</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_acquire</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">Locked</span><span class="special">)</span> <span class="special">{</span>
      <span class="comment">/* busy-wait */</span>
    <span class="special">}</span>
  <span class="special">}</span>
  <span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">()</span>
  <span class="special">{<br /></span>    // 这里都直接写不做检查了，更加难以理解
    <span class="identifier">state_</span><span class="special">.</span><span class="identifier">store</span><span class="special">(</span><span class="identifier">Unlocked</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">memory_order_release</span><span class="special">);</span>
  <span class="special">}</span>
<span class="special">};<br /><br /></span>有可能是我不理解后面的内存访问参数的意义，给下我自己的实现：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;CESpinLock&nbsp;:&nbsp;boost::noncopyable<br />{<br /></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</span><span style="color: #0000FF; ">enum</span><span style="color: #000000; ">&nbsp;{emUnlocked&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;emLocked}&nbsp;EM_LockState;<br /><br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;CESpinLock()&nbsp;:&nbsp;m_atomicState(emLocked)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">lock</span><span style="color: #000000; ">()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EM_LockState&nbsp;state&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;emUnlocked;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;m_atomicState.compare_exchange_strong(state,&nbsp;emLocked))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;emUnlocked;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;unlock()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EM_LockState&nbsp;state&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;emLocked;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;m_atomicState.compare_exchange_strong(state,&nbsp;emUnlocked))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;emLocked;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br /></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;boost::atomic</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">EM_LockState</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;m_atomicState;<br />};</span></div><br /></pre></div></div><br />可以适当的在false里边加一点sleep操作感觉。<br /><br />还有一点就是不太激烈这里的cae操作分两种 strong和weak<br /><div><p><code>bool compare_exchange_weak(T &amp; expected, T desired, memory_order success_order, memory_order failure_order)</code>  </p>  <p>Compare current value with <code>expected</code>, change it to <code>desired</code> if matches.  Returns <code>true</code> if an  exchange has been performed, and always writes the previous value back in <code>expected</code>. May fail  spuriously, so must generally be retried in a loop. </p>   <p><code>bool compare_exchange_strong(T &amp; expected, T desired, memory_order order)</code> </p>  <p>Compare current value with <code>expected</code>, change it to <code>desired</code> if matches.  Returns <code>true</code> if an  exchange has been performed, and always writes the previous value back in <code>expected</code>.&nbsp;<br /><br />实在不理解&nbsp;May fail spuriously, so must generally be retried in a loop.的意义，不过看了代码，在win32的实现上，weak是调用了stong实现的。<br /><br /><br /><br /><div><div>&nbsp;VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;21:49:07<br />atomic的&nbsp;compare_exchange_weak<br />compare_exchange_weak<br />有啥区别<br /><img src="file:///C:\Users\Error\AppData\Local\Temp\)SC5BVG@Z77TFAZI3REO[}R.gif" sysface="36"  alt="" /><br />求解释<br />vczh.Iskandar&lt;vczh@163.com&gt;&nbsp;&nbsp;21:49:27<br />不是一样吗<br />御虚舟北(314969051)&nbsp;&nbsp;21:49:40<br />改代码中，&nbsp;ing<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;21:49:49<br />Windows上的实现是一样的<br />May&nbsp;fail&nbsp;spuriously,&nbsp;so&nbsp;must&nbsp;generally&nbsp;be&nbsp;retried&nbsp;in&nbsp;a&nbsp;loop.&nbsp;<br />这一句怎么理解呢<br />vczh.Iskandar&lt;vczh@163.com&gt;&nbsp;&nbsp;21:50:07<br />compare_exchange_weak<br />compare_exchange_weak<br />质量最大vczh粉(402740419)&nbsp;&nbsp;21:50:14<br />compare_exchange_weak<br />compare_exchange_weak<br /><br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;21:50:16<br />strong<br /><br />compare_exchange_strong<br />还有一个问题<br />class&nbsp;spinlock&nbsp;{<br />private:<br />&nbsp;&nbsp;typedef&nbsp;enum&nbsp;{Locked,&nbsp;Unlocked}&nbsp;LockState;<br />&nbsp;&nbsp;boost::atomic&lt;LockState&gt;&nbsp;state_;<br /><br />public:<br />&nbsp;&nbsp;spinlock()&nbsp;:&nbsp;state_(Unlocked)&nbsp;{}<br /><br />&nbsp;&nbsp;void&nbsp;lock()<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(state_.exchange(Locked,&nbsp;boost::memory_order_acquire)&nbsp;==&nbsp;Locked)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;busy-wait&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;void&nbsp;unlock()<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;state_.store(Unlocked,&nbsp;boost::memory_order_release);<br />&nbsp;&nbsp;}<br />};<br /><br />boost例子给的&nbsp;spinloc<br />怎么是这样实现的<br />都没有用cae操作<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;21:51:20<br />unlock都直接用store了<br />vczh.Iskandar&lt;vczh@163.com&gt;&nbsp;&nbsp;21:51:50<br />不用compare<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;21:51:59<br /><img src="file:///D:\Program Files (x86)\Tencent\QQ\PersonalData\85126585\Image\Image3\HY)ZO7GDOQ)]Q8H(Q}8WQ~S.gif"  alt="" />&nbsp;为啥<br />无法理解<br />vczh.Iskandar&lt;vczh@163.com&gt;&nbsp;&nbsp;21:52:34<br />想要解释好麻烦<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;21:52:40<br />还有在Windows上<br />boost::memory_order_acquire<br />这个参数也没用<br />貌似<br /><img src="file:///C:\Users\Error\AppData\Local\Temp\V~OKLWS%3HDUFQ4IH)AJTFW.gif"  alt="" />求V神解释<br />还有strong和weak的区别<br />质量最大vczh粉(402740419)&nbsp;&nbsp;21:54:46<br />spinlock本来就不用compare啊<br />直接swap就行了<br />while&nbsp;(state_.swap(1)&nbsp;==&nbsp;1);<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;21:56:24<br />你看假设现在是lock状态<br />boost的实现是无条件吧lock换成unlock<br />如果是继续lock&nbsp;他还是lock<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;21:58:08<br />只要要避免&nbsp;重入吧<br />lock之前检查一下<br />御虚舟北(314969051)&nbsp;&nbsp;22:00:03<br />小康你的书收到没有<br />质量最大vczh粉(402740419)&nbsp;&nbsp;22:03:17<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;21:58:08<br />只要要避免&nbsp;重入吧<br />lock之前检查一下<br /><br />你用错了他不管你<br />就是这个意思<br />同一个线程lock两次也会死锁<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;22:05:05<br /><img src="file:///D:\Program Files (x86)\Tencent\QQ\PersonalData\85126585\Image\Image3\HY)ZO7GDOQ)]Q8H(Q}8WQ~S.gif"  alt="" />原来是这样<br /><br />但是他lock的时候不检查，也会导致两个线程同时lock吧？<br />while&nbsp;(state_.exchange(Locked,&nbsp;boost::memory_order_acquire)&nbsp;==&nbsp;Locked)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;busy-wait&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />质量最大vczh粉(402740419)&nbsp;&nbsp;22:05:18<br />不会啊<br />假设A进程先来了，lock成功了<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;22:05:33<br />怎能理解，我理解和直接赋值是一样<br />我再去看<br />质量最大vczh粉(402740419)&nbsp;&nbsp;22:05:40<br />这不是复制<br />是exchange<br />swap<br />另一个线程exchange就会收到Locked<br />那么另一个线程就会while循环，直到原来线程给设置了Unlocked<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;22:06:47<br />Exchange&nbsp;current&nbsp;value&nbsp;with&nbsp;new_value,&nbsp;returning&nbsp;current&nbsp;value&nbsp;<br /><br />exchange是把新值写入旧值返回么？&nbsp;&nbsp;不是这样么？<br />我有点理解了<br />质量最大vczh粉(402740419)&nbsp;&nbsp;22:07:46<br />对啊，新值写入，旧值返回，原子的<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;22:07:59<br />就是说写入也是写入的lock，&nbsp;不影响之前的lock<br />当前线程拿到旧值检查是不是lock状态，如果是就继续尝试直到不是<br />质量最大vczh粉(402740419)&nbsp;&nbsp;22:08:00<br />所以只会有一个线程返回Unlocked，另一个线程会收到之前线程设置的Locked<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;22:08:11<br />&nbsp;受教了<br />质量最大vczh粉(402740419)&nbsp;&nbsp;22:08:13<br />恩<br />VCZH.粉丝数组[0]&lt;errorcpp@qq.com&gt;&nbsp;&nbsp;22:08:20<br />我贴到博客上去&nbsp;</div></div></p></div><img src ="http://www.cppblog.com/Error/aggbug/198988.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Error/" target="_blank">Enic</a> 2013-03-31 21:49 <a href="http://www.cppblog.com/Error/archive/2013/03/31/198988.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>