1
0
mirror of https://github.com/tearshark/librf.git synced 2024-10-01 15:57:07 +08:00
librf/doxygen/html/ring__queue__lockfree_8h_source.html
tearshark cd74eea532 完善文档。
上传Doxygen生成的文档。
2020-03-31 15:30:45 +08:00

300 lines
36 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.17"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>librf: librf/src/ring_queue_lockfree.h 源文件</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">librf
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- 制作者 Doxygen 1.8.17 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'搜索');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
initMenu('',true,false,'search.php','搜索');
$(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div id="nav-path" class="navpath">
<ul>
<li class="navelem"><a class="el" href="dir_3c80010775d22af2067790ecc9cdcf9d.html">librf</a></li><li class="navelem"><a class="el" href="dir_54ae0e78d997f6903cdf0996223d047f.html">src</a></li> </ul>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">ring_queue_lockfree.h</div> </div>
</div><!--header-->
<div class="contents">
<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="preprocessor">#pragma once</span></div>
<div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160; </div>
<div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="keyword">namespace </span>resumef</div>
<div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;{</div>
<div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160; <span class="comment">//目前无法解决三个索引数值回绕导致的问题</span></div>
<div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160; <span class="comment">//如果为了避免索引回绕的问题索引采用uint64_t类型</span></div>
<div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160; <span class="comment">//则在与spinlock&lt;T, false, uint32_t&gt;版本的对比中速度反而慢了</span></div>
<div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160; <span class="comment">//pop时无法使用move语义来获取数据。因为算法要求先获取值且获取后有可能失败从而重新获取其它值。</span></div>
<div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty = u<span class="keywordtype">int</span>32_t&gt;</div>
<div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160; <span class="keyword">struct </span>ring_queue_lockfree</div>
<div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160; {</div>
<div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160; <span class="keyword">using</span> value_type = _Ty;</div>
<div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160; <span class="keyword">using</span> size_type = _Sty;</div>
<div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160; <span class="keyword">public</span>:</div>
<div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160; ring_queue_lockfree(<span class="keywordtype">size_t</span> sz);</div>
<div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160; </div>
<div class="line"><a name="l00017"></a><span class="lineno"> 17</span>&#160; ring_queue_lockfree(<span class="keyword">const</span> ring_queue_lockfree&amp;) = <span class="keyword">delete</span>;</div>
<div class="line"><a name="l00018"></a><span class="lineno"> 18</span>&#160; ring_queue_lockfree(ring_queue_lockfree&amp;&amp;) = <span class="keywordflow">default</span>;</div>
<div class="line"><a name="l00019"></a><span class="lineno"> 19</span>&#160; ring_queue_lockfree&amp; operator =(<span class="keyword">const</span> ring_queue_lockfree&amp;) = <span class="keyword">delete</span>;</div>
<div class="line"><a name="l00020"></a><span class="lineno"> 20</span>&#160; ring_queue_lockfree&amp; operator =(ring_queue_lockfree&amp;&amp;) = <span class="keywordflow">default</span>;</div>
<div class="line"><a name="l00021"></a><span class="lineno"> 21</span>&#160; </div>
<div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160; <span class="keyword">auto</span> size() const noexcept-&gt;size_type;</div>
<div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160; auto capacity() const noexcept-&gt;size_type;</div>
<div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160; <span class="keywordtype">bool</span> empty() const noexcept;</div>
<div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160; <span class="keywordtype">bool</span> full() const noexcept;</div>
<div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160; template&lt;class U&gt;</div>
<div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160; <span class="keywordtype">bool</span> try_push(U&amp;&amp; value) noexcept(std::is_nothrow_move_constructible_v&lt;U&gt;);</div>
<div class="line"><a name="l00028"></a><span class="lineno"> 28</span>&#160; <span class="keywordtype">bool</span> try_pop(value_type&amp; value) noexcept(std::is_nothrow_move_constructible_v&lt;value_type&gt;);</div>
<div class="line"><a name="l00029"></a><span class="lineno"> 29</span>&#160; private:</div>
<div class="line"><a name="l00030"></a><span class="lineno"> 30</span>&#160; std::unique_ptr&lt;value_type[]&gt; m_bufferPtr;</div>
<div class="line"><a name="l00031"></a><span class="lineno"> 31</span>&#160; size_type m_bufferSize;</div>
<div class="line"><a name="l00032"></a><span class="lineno"> 32</span>&#160; </div>
<div class="line"><a name="l00033"></a><span class="lineno"> 33</span>&#160; std::atomic&lt;size_type&gt; m_writeIndex; <span class="comment">//Where a new element will be inserted to.</span></div>
<div class="line"><a name="l00034"></a><span class="lineno"> 34</span>&#160; std::atomic&lt;size_type&gt; m_readIndex; <span class="comment">//Where the next element where be extracted from.</span></div>
<div class="line"><a name="l00035"></a><span class="lineno"> 35</span>&#160; std::atomic&lt;size_type&gt; m_maximumReadIndex; <span class="comment">//It points to the place where the latest &quot;commited&quot; data has been inserted. </span></div>
<div class="line"><a name="l00036"></a><span class="lineno"> 36</span>&#160; <span class="comment">//If it&#39;s not the same as writeIndex it means there are writes pending to be &quot;commited&quot; to the queue, </span></div>
<div class="line"><a name="l00037"></a><span class="lineno"> 37</span>&#160; <span class="comment">//that means that the place for the data was reserved (the index in the array) </span></div>
<div class="line"><a name="l00038"></a><span class="lineno"> 38</span>&#160; <span class="comment">//but the data is still not in the queue, </span></div>
<div class="line"><a name="l00039"></a><span class="lineno"> 39</span>&#160; <span class="comment">//so the thread trying to read will have to wait for those other threads to </span></div>
<div class="line"><a name="l00040"></a><span class="lineno"> 40</span>&#160; <span class="comment">//save the data into the queue.</span></div>
<div class="line"><a name="l00041"></a><span class="lineno"> 41</span>&#160; <span class="preprocessor">#ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</span></div>
<div class="line"><a name="l00042"></a><span class="lineno"> 42</span>&#160; std::atomic&lt;size_type&gt; m_count;</div>
<div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160;<span class="preprocessor"> #endif</span></div>
<div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160; </div>
<div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160; <span class="keyword">auto</span> countToIndex(size_type a_count) <span class="keyword">const</span> noexcept-&gt;size_type;</div>
<div class="line"><a name="l00046"></a><span class="lineno"> 46</span>&#160; <span class="keyword">auto</span> nextIndex(size_type a_count) <span class="keyword">const</span> noexcept-&gt;size_type;</div>
<div class="line"><a name="l00047"></a><span class="lineno"> 47</span>&#160; };</div>
<div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160; </div>
<div class="line"><a name="l00049"></a><span class="lineno"> 49</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty&gt;</div>
<div class="line"><a name="l00050"></a><span class="lineno"> 50</span>&#160; ring_queue_lockfree&lt;_Ty, _Sty&gt;::ring_queue_lockfree(<span class="keywordtype">size_t</span> sz)</div>
<div class="line"><a name="l00051"></a><span class="lineno"> 51</span>&#160; : m_bufferPtr(new value_type[sz + 1])</div>
<div class="line"><a name="l00052"></a><span class="lineno"> 52</span>&#160; , m_bufferSize(static_cast&lt;size_type&gt;(sz + 1))</div>
<div class="line"><a name="l00053"></a><span class="lineno"> 53</span>&#160; , m_writeIndex(0)</div>
<div class="line"><a name="l00054"></a><span class="lineno"> 54</span>&#160; , m_readIndex(0)</div>
<div class="line"><a name="l00055"></a><span class="lineno"> 55</span>&#160; , m_maximumReadIndex(0)</div>
<div class="line"><a name="l00056"></a><span class="lineno"> 56</span>&#160; #ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</div>
<div class="line"><a name="l00057"></a><span class="lineno"> 57</span>&#160; , m_count(0)</div>
<div class="line"><a name="l00058"></a><span class="lineno"> 58</span>&#160; #endif</div>
<div class="line"><a name="l00059"></a><span class="lineno"> 59</span>&#160; {</div>
<div class="line"><a name="l00060"></a><span class="lineno"> 60</span>&#160; assert(sz &lt; (std::numeric_limits&lt;size_type&gt;::max)());</div>
<div class="line"><a name="l00061"></a><span class="lineno"> 61</span>&#160; }</div>
<div class="line"><a name="l00062"></a><span class="lineno"> 62</span>&#160; </div>
<div class="line"><a name="l00063"></a><span class="lineno"> 63</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty&gt;</div>
<div class="line"><a name="l00064"></a><span class="lineno"> 64</span>&#160; <span class="keyword">auto</span> ring_queue_lockfree&lt;_Ty, _Sty&gt;::countToIndex(size_type a_count) <span class="keyword">const</span> noexcept-&gt;size_type</div>
<div class="line"><a name="l00065"></a><span class="lineno"> 65</span>&#160; {</div>
<div class="line"><a name="l00066"></a><span class="lineno"> 66</span>&#160; <span class="comment">//return (a_count % m_bufferSize);</span></div>
<div class="line"><a name="l00067"></a><span class="lineno"> 67</span>&#160; <span class="keywordflow">return</span> a_count;</div>
<div class="line"><a name="l00068"></a><span class="lineno"> 68</span>&#160; }</div>
<div class="line"><a name="l00069"></a><span class="lineno"> 69</span>&#160; </div>
<div class="line"><a name="l00070"></a><span class="lineno"> 70</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty&gt;</div>
<div class="line"><a name="l00071"></a><span class="lineno"> 71</span>&#160; <span class="keyword">auto</span> ring_queue_lockfree&lt;_Ty, _Sty&gt;::nextIndex(size_type a_count) <span class="keyword">const</span> noexcept-&gt;size_type</div>
<div class="line"><a name="l00072"></a><span class="lineno"> 72</span>&#160; {</div>
<div class="line"><a name="l00073"></a><span class="lineno"> 73</span>&#160; <span class="comment">//return static_cast&lt;size_type&gt;((a_count + 1));</span></div>
<div class="line"><a name="l00074"></a><span class="lineno"> 74</span>&#160; <span class="keywordflow">return</span> <span class="keyword">static_cast&lt;</span>size_type<span class="keyword">&gt;</span>((a_count + 1) % m_bufferSize);</div>
<div class="line"><a name="l00075"></a><span class="lineno"> 75</span>&#160; }</div>
<div class="line"><a name="l00076"></a><span class="lineno"> 76</span>&#160; </div>
<div class="line"><a name="l00077"></a><span class="lineno"> 77</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty&gt;</div>
<div class="line"><a name="l00078"></a><span class="lineno"> 78</span>&#160; <span class="keyword">auto</span> ring_queue_lockfree&lt;_Ty, _Sty&gt;::size() const noexcept-&gt;size_type</div>
<div class="line"><a name="l00079"></a><span class="lineno"> 79</span>&#160; {</div>
<div class="line"><a name="l00080"></a><span class="lineno"> 80</span>&#160;<span class="preprocessor"> #ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</span></div>
<div class="line"><a name="l00081"></a><span class="lineno"> 81</span>&#160; <span class="keywordflow">return</span> m_count.load();</div>
<div class="line"><a name="l00082"></a><span class="lineno"> 82</span>&#160;<span class="preprocessor"> #else</span></div>
<div class="line"><a name="l00083"></a><span class="lineno"> 83</span>&#160; <span class="keyword">auto</span> currentWriteIndex = m_maximumReadIndex.load(std::memory_order_acquire);</div>
<div class="line"><a name="l00084"></a><span class="lineno"> 84</span>&#160; currentWriteIndex = countToIndex(currentWriteIndex);</div>
<div class="line"><a name="l00085"></a><span class="lineno"> 85</span>&#160; </div>
<div class="line"><a name="l00086"></a><span class="lineno"> 86</span>&#160; <span class="keyword">auto</span> currentReadIndex = m_readIndex.load(std::memory_order_acquire);</div>
<div class="line"><a name="l00087"></a><span class="lineno"> 87</span>&#160; currentReadIndex = countToIndex(currentReadIndex);</div>
<div class="line"><a name="l00088"></a><span class="lineno"> 88</span>&#160; </div>
<div class="line"><a name="l00089"></a><span class="lineno"> 89</span>&#160; <span class="keywordflow">if</span> (currentWriteIndex &gt;= currentReadIndex)</div>
<div class="line"><a name="l00090"></a><span class="lineno"> 90</span>&#160; <span class="keywordflow">return</span> (currentWriteIndex - currentReadIndex);</div>
<div class="line"><a name="l00091"></a><span class="lineno"> 91</span>&#160; <span class="keywordflow">else</span></div>
<div class="line"><a name="l00092"></a><span class="lineno"> 92</span>&#160; <span class="keywordflow">return</span> (m_bufferSize + currentWriteIndex - currentReadIndex);</div>
<div class="line"><a name="l00093"></a><span class="lineno"> 93</span>&#160;<span class="preprocessor"> #endif // _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</span></div>
<div class="line"><a name="l00094"></a><span class="lineno"> 94</span>&#160; }</div>
<div class="line"><a name="l00095"></a><span class="lineno"> 95</span>&#160; </div>
<div class="line"><a name="l00096"></a><span class="lineno"> 96</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty&gt;</div>
<div class="line"><a name="l00097"></a><span class="lineno"> 97</span>&#160; <span class="keyword">auto</span> ring_queue_lockfree&lt;_Ty, _Sty&gt;::capacity() const noexcept-&gt;size_type</div>
<div class="line"><a name="l00098"></a><span class="lineno"> 98</span>&#160; {</div>
<div class="line"><a name="l00099"></a><span class="lineno"> 99</span>&#160; <span class="keywordflow">return</span> m_bufferSize - 1;</div>
<div class="line"><a name="l00100"></a><span class="lineno"> 100</span>&#160; }</div>
<div class="line"><a name="l00101"></a><span class="lineno"> 101</span>&#160; </div>
<div class="line"><a name="l00102"></a><span class="lineno"> 102</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty&gt;</div>
<div class="line"><a name="l00103"></a><span class="lineno"> 103</span>&#160; <span class="keywordtype">bool</span> ring_queue_lockfree&lt;_Ty, _Sty&gt;::empty() const noexcept</div>
<div class="line"><a name="l00104"></a><span class="lineno"> 104</span>&#160; {</div>
<div class="line"><a name="l00105"></a><span class="lineno"> 105</span>&#160;<span class="preprocessor"> #ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</span></div>
<div class="line"><a name="l00106"></a><span class="lineno"> 106</span>&#160; <span class="keywordflow">return</span> m_count.load() == 0;</div>
<div class="line"><a name="l00107"></a><span class="lineno"> 107</span>&#160;<span class="preprocessor"> #else</span></div>
<div class="line"><a name="l00108"></a><span class="lineno"> 108</span>&#160; <span class="keyword">auto</span> currentWriteIndex = m_maximumReadIndex.load(std::memory_order_acquire);</div>
<div class="line"><a name="l00109"></a><span class="lineno"> 109</span>&#160; <span class="keyword">auto</span> currentReadIndex = m_readIndex.load(std::memory_order_acquire);</div>
<div class="line"><a name="l00110"></a><span class="lineno"> 110</span>&#160; <span class="keywordflow">return</span> countToIndex(currentWriteIndex) == countToIndex(currentReadIndex);</div>
<div class="line"><a name="l00111"></a><span class="lineno"> 111</span>&#160;<span class="preprocessor"> #endif // _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</span></div>
<div class="line"><a name="l00112"></a><span class="lineno"> 112</span>&#160; }</div>
<div class="line"><a name="l00113"></a><span class="lineno"> 113</span>&#160; </div>
<div class="line"><a name="l00114"></a><span class="lineno"> 114</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty&gt;</div>
<div class="line"><a name="l00115"></a><span class="lineno"> 115</span>&#160; <span class="keywordtype">bool</span> ring_queue_lockfree&lt;_Ty, _Sty&gt;::full() const noexcept</div>
<div class="line"><a name="l00116"></a><span class="lineno"> 116</span>&#160; {</div>
<div class="line"><a name="l00117"></a><span class="lineno"> 117</span>&#160;<span class="preprocessor"> #ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</span></div>
<div class="line"><a name="l00118"></a><span class="lineno"> 118</span>&#160; <span class="keywordflow">return</span> (m_count.load() == (m_bufferSize - 1));</div>
<div class="line"><a name="l00119"></a><span class="lineno"> 119</span>&#160;<span class="preprocessor"> #else</span></div>
<div class="line"><a name="l00120"></a><span class="lineno"> 120</span>&#160; <span class="keyword">auto</span> currentWriteIndex = m_writeIndex.load(std::memory_order_acquire);</div>
<div class="line"><a name="l00121"></a><span class="lineno"> 121</span>&#160; <span class="keyword">auto</span> currentReadIndex = m_readIndex.load(std::memory_order_acquire);</div>
<div class="line"><a name="l00122"></a><span class="lineno"> 122</span>&#160; <span class="keywordflow">return</span> countToIndex(nextIndex(currentWriteIndex)) == countToIndex(currentReadIndex);</div>
<div class="line"><a name="l00123"></a><span class="lineno"> 123</span>&#160;<span class="preprocessor"> #endif // _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</span></div>
<div class="line"><a name="l00124"></a><span class="lineno"> 124</span>&#160; }</div>
<div class="line"><a name="l00125"></a><span class="lineno"> 125</span>&#160; </div>
<div class="line"><a name="l00126"></a><span class="lineno"> 126</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty&gt;</div>
<div class="line"><a name="l00127"></a><span class="lineno"> 127</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> U&gt;</div>
<div class="line"><a name="l00128"></a><span class="lineno"> 128</span>&#160; <span class="keywordtype">bool</span> ring_queue_lockfree&lt;_Ty, _Sty&gt;::try_push(U&amp;&amp; value) noexcept(std::is_nothrow_move_constructible_v&lt;U&gt;)</div>
<div class="line"><a name="l00129"></a><span class="lineno"> 129</span>&#160; {</div>
<div class="line"><a name="l00130"></a><span class="lineno"> 130</span>&#160; <span class="keyword">auto</span> currentWriteIndex = m_writeIndex.load(std::memory_order_acquire);</div>
<div class="line"><a name="l00131"></a><span class="lineno"> 131</span>&#160; </div>
<div class="line"><a name="l00132"></a><span class="lineno"> 132</span>&#160; <span class="keywordflow">do</span></div>
<div class="line"><a name="l00133"></a><span class="lineno"> 133</span>&#160; {</div>
<div class="line"><a name="l00134"></a><span class="lineno"> 134</span>&#160; <span class="keywordflow">if</span> (countToIndex(nextIndex(currentWriteIndex)) == countToIndex(m_readIndex.load(std::memory_order_acquire)))</div>
<div class="line"><a name="l00135"></a><span class="lineno"> 135</span>&#160; {</div>
<div class="line"><a name="l00136"></a><span class="lineno"> 136</span>&#160; <span class="comment">// the queue is full</span></div>
<div class="line"><a name="l00137"></a><span class="lineno"> 137</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line"><a name="l00138"></a><span class="lineno"> 138</span>&#160; }</div>
<div class="line"><a name="l00139"></a><span class="lineno"> 139</span>&#160; </div>
<div class="line"><a name="l00140"></a><span class="lineno"> 140</span>&#160; <span class="comment">// There is more than one producer. Keep looping till this thread is able </span></div>
<div class="line"><a name="l00141"></a><span class="lineno"> 141</span>&#160; <span class="comment">// to allocate space for current piece of data</span></div>
<div class="line"><a name="l00142"></a><span class="lineno"> 142</span>&#160; <span class="comment">//</span></div>
<div class="line"><a name="l00143"></a><span class="lineno"> 143</span>&#160; <span class="comment">// using compare_exchange_strong because it isn&#39;t allowed to fail spuriously</span></div>
<div class="line"><a name="l00144"></a><span class="lineno"> 144</span>&#160; <span class="comment">// When the compare_exchange operation is in a loop the weak version</span></div>
<div class="line"><a name="l00145"></a><span class="lineno"> 145</span>&#160; <span class="comment">// will yield better performance on some platforms, but here we&#39;d have to</span></div>
<div class="line"><a name="l00146"></a><span class="lineno"> 146</span>&#160; <span class="comment">// load m_writeIndex all over again</span></div>
<div class="line"><a name="l00147"></a><span class="lineno"> 147</span>&#160; } <span class="keywordflow">while</span> (!m_writeIndex.compare_exchange_strong(currentWriteIndex, nextIndex(currentWriteIndex), std::memory_order_acq_rel));</div>
<div class="line"><a name="l00148"></a><span class="lineno"> 148</span>&#160; </div>
<div class="line"><a name="l00149"></a><span class="lineno"> 149</span>&#160; <span class="comment">// Just made sure this index is reserved for this thread.</span></div>
<div class="line"><a name="l00150"></a><span class="lineno"> 150</span>&#160; m_bufferPtr[countToIndex(currentWriteIndex)] = std::move(value);</div>
<div class="line"><a name="l00151"></a><span class="lineno"> 151</span>&#160; </div>
<div class="line"><a name="l00152"></a><span class="lineno"> 152</span>&#160; <span class="comment">// update the maximum read index after saving the piece of data. It can&#39;t</span></div>
<div class="line"><a name="l00153"></a><span class="lineno"> 153</span>&#160; <span class="comment">// fail if there is only one thread inserting in the queue. It might fail </span></div>
<div class="line"><a name="l00154"></a><span class="lineno"> 154</span>&#160; <span class="comment">// if there is more than 1 producer thread because this operation has to</span></div>
<div class="line"><a name="l00155"></a><span class="lineno"> 155</span>&#160; <span class="comment">// be done in the same order as the previous CAS</span></div>
<div class="line"><a name="l00156"></a><span class="lineno"> 156</span>&#160; <span class="comment">//</span></div>
<div class="line"><a name="l00157"></a><span class="lineno"> 157</span>&#160; <span class="comment">// using compare_exchange_weak because they are allowed to fail spuriously</span></div>
<div class="line"><a name="l00158"></a><span class="lineno"> 158</span>&#160; <span class="comment">// (act as if *this != expected, even if they are equal), but when the</span></div>
<div class="line"><a name="l00159"></a><span class="lineno"> 159</span>&#160; <span class="comment">// compare_exchange operation is in a loop the weak version will yield</span></div>
<div class="line"><a name="l00160"></a><span class="lineno"> 160</span>&#160; <span class="comment">// better performance on some platforms.</span></div>
<div class="line"><a name="l00161"></a><span class="lineno"> 161</span>&#160; <span class="keyword">auto</span> savedWriteIndex = currentWriteIndex;</div>
<div class="line"><a name="l00162"></a><span class="lineno"> 162</span>&#160; <span class="keywordflow">while</span> (!m_maximumReadIndex.compare_exchange_weak(currentWriteIndex, nextIndex(currentWriteIndex), std::memory_order_acq_rel))</div>
<div class="line"><a name="l00163"></a><span class="lineno"> 163</span>&#160; {</div>
<div class="line"><a name="l00164"></a><span class="lineno"> 164</span>&#160; currentWriteIndex = savedWriteIndex;</div>
<div class="line"><a name="l00165"></a><span class="lineno"> 165</span>&#160; <span class="comment">// this is a good place to yield the thread in case there are more</span></div>
<div class="line"><a name="l00166"></a><span class="lineno"> 166</span>&#160; <span class="comment">// software threads than hardware processors and you have more</span></div>
<div class="line"><a name="l00167"></a><span class="lineno"> 167</span>&#160; <span class="comment">// than 1 producer thread</span></div>
<div class="line"><a name="l00168"></a><span class="lineno"> 168</span>&#160; <span class="comment">// have a look at sched_yield (POSIX.1b)</span></div>
<div class="line"><a name="l00169"></a><span class="lineno"> 169</span>&#160; std::this_thread::yield();</div>
<div class="line"><a name="l00170"></a><span class="lineno"> 170</span>&#160; }</div>
<div class="line"><a name="l00171"></a><span class="lineno"> 171</span>&#160; </div>
<div class="line"><a name="l00172"></a><span class="lineno"> 172</span>&#160; <span class="comment">// The value was successfully inserted into the queue</span></div>
<div class="line"><a name="l00173"></a><span class="lineno"> 173</span>&#160;<span class="preprocessor"> #ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</span></div>
<div class="line"><a name="l00174"></a><span class="lineno"> 174</span>&#160; m_count.fetch_add(1);</div>
<div class="line"><a name="l00175"></a><span class="lineno"> 175</span>&#160;<span class="preprocessor"> #endif</span></div>
<div class="line"><a name="l00176"></a><span class="lineno"> 176</span>&#160; <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
<div class="line"><a name="l00177"></a><span class="lineno"> 177</span>&#160; }</div>
<div class="line"><a name="l00178"></a><span class="lineno"> 178</span>&#160; </div>
<div class="line"><a name="l00179"></a><span class="lineno"> 179</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">class</span> _Ty, <span class="keyword">class</span> _Sty&gt;</div>
<div class="line"><a name="l00180"></a><span class="lineno"> 180</span>&#160; <span class="keywordtype">bool</span> ring_queue_lockfree&lt;_Ty, _Sty&gt;::try_pop(value_type&amp; value) noexcept(std::is_nothrow_move_constructible_v&lt;value_type&gt;)</div>
<div class="line"><a name="l00181"></a><span class="lineno"> 181</span>&#160; {</div>
<div class="line"><a name="l00182"></a><span class="lineno"> 182</span>&#160; <span class="keyword">auto</span> currentReadIndex = m_readIndex.load(std::memory_order_acquire);</div>
<div class="line"><a name="l00183"></a><span class="lineno"> 183</span>&#160; </div>
<div class="line"><a name="l00184"></a><span class="lineno"> 184</span>&#160; <span class="keywordflow">for</span> (;;)</div>
<div class="line"><a name="l00185"></a><span class="lineno"> 185</span>&#160; {</div>
<div class="line"><a name="l00186"></a><span class="lineno"> 186</span>&#160; <span class="keyword">auto</span> idx = countToIndex(currentReadIndex);</div>
<div class="line"><a name="l00187"></a><span class="lineno"> 187</span>&#160; </div>
<div class="line"><a name="l00188"></a><span class="lineno"> 188</span>&#160; <span class="comment">// to ensure thread-safety when there is more than 1 producer </span></div>
<div class="line"><a name="l00189"></a><span class="lineno"> 189</span>&#160; <span class="comment">// thread a second index is defined (m_maximumReadIndex)</span></div>
<div class="line"><a name="l00190"></a><span class="lineno"> 190</span>&#160; <span class="keywordflow">if</span> (idx == countToIndex(m_maximumReadIndex.load(std::memory_order_acquire)))</div>
<div class="line"><a name="l00191"></a><span class="lineno"> 191</span>&#160; {</div>
<div class="line"><a name="l00192"></a><span class="lineno"> 192</span>&#160; <span class="comment">// the queue is empty or</span></div>
<div class="line"><a name="l00193"></a><span class="lineno"> 193</span>&#160; <span class="comment">// a producer thread has allocate space in the queue but is </span></div>
<div class="line"><a name="l00194"></a><span class="lineno"> 194</span>&#160; <span class="comment">// waiting to commit the data into it</span></div>
<div class="line"><a name="l00195"></a><span class="lineno"> 195</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line"><a name="l00196"></a><span class="lineno"> 196</span>&#160; }</div>
<div class="line"><a name="l00197"></a><span class="lineno"> 197</span>&#160; </div>
<div class="line"><a name="l00198"></a><span class="lineno"> 198</span>&#160; <span class="comment">// retrieve the data from the queue</span></div>
<div class="line"><a name="l00199"></a><span class="lineno"> 199</span>&#160; value = m_bufferPtr[idx]; <span class="comment">//但是,这里的方法不适合。如果只支持移动怎么办?</span></div>
<div class="line"><a name="l00200"></a><span class="lineno"> 200</span>&#160; </div>
<div class="line"><a name="l00201"></a><span class="lineno"> 201</span>&#160; <span class="comment">// try to perfrom now the CAS operation on the read index. If we succeed</span></div>
<div class="line"><a name="l00202"></a><span class="lineno"> 202</span>&#160; <span class="comment">// a_data already contains what m_readIndex pointed to before we </span></div>
<div class="line"><a name="l00203"></a><span class="lineno"> 203</span>&#160; <span class="comment">// increased it</span></div>
<div class="line"><a name="l00204"></a><span class="lineno"> 204</span>&#160; <span class="keywordflow">if</span> (m_readIndex.compare_exchange_strong(currentReadIndex, nextIndex(currentReadIndex), std::memory_order_acq_rel))</div>
<div class="line"><a name="l00205"></a><span class="lineno"> 205</span>&#160; {</div>
<div class="line"><a name="l00206"></a><span class="lineno"> 206</span>&#160; <span class="comment">// got here. The value was retrieved from the queue. Note that the</span></div>
<div class="line"><a name="l00207"></a><span class="lineno"> 207</span>&#160; <span class="comment">// data inside the m_queue array is not deleted nor reseted</span></div>
<div class="line"><a name="l00208"></a><span class="lineno"> 208</span>&#160;<span class="preprocessor"> #ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE</span></div>
<div class="line"><a name="l00209"></a><span class="lineno"> 209</span>&#160; m_count.fetch_sub(1);</div>
<div class="line"><a name="l00210"></a><span class="lineno"> 210</span>&#160;<span class="preprocessor"> #endif</span></div>
<div class="line"><a name="l00211"></a><span class="lineno"> 211</span>&#160; <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
<div class="line"><a name="l00212"></a><span class="lineno"> 212</span>&#160; }</div>
<div class="line"><a name="l00213"></a><span class="lineno"> 213</span>&#160; </div>
<div class="line"><a name="l00214"></a><span class="lineno"> 214</span>&#160; <span class="comment">// it failed retrieving the element off the queue. Someone else must</span></div>
<div class="line"><a name="l00215"></a><span class="lineno"> 215</span>&#160; <span class="comment">// have read the element stored at countToIndex(currentReadIndex)</span></div>
<div class="line"><a name="l00216"></a><span class="lineno"> 216</span>&#160; <span class="comment">// before we could perform the CAS operation </span></div>
<div class="line"><a name="l00217"></a><span class="lineno"> 217</span>&#160; } <span class="comment">// keep looping to try again!</span></div>
<div class="line"><a name="l00218"></a><span class="lineno"> 218</span>&#160; }</div>
<div class="line"><a name="l00219"></a><span class="lineno"> 219</span>&#160;}</div>
</div><!-- fragment --></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
制作者 &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.17
</small></address>
</body>
</html>