{"id":10619,"date":"2025-02-10T15:01:19","date_gmt":"2025-02-10T15:01:19","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=10619"},"modified":"2025-07-03T14:34:20","modified_gmt":"2025-07-03T14:34:20","slug":"a-lock-free-stack-a-complete-implementation","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/a-lock-free-stack-a-complete-implementation\/","title":{"rendered":"A Lock-Free Stack: A Complete Implementation"},"content":{"rendered":"\n<p>My last lock-free stack implementation was incomplete. It only supported push operations. Let&#8217;s change this. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"711\" height=\"491\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2025\/01\/Time26Concurrency.png\" alt=\"\" class=\"wp-image-10580\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2025\/01\/Time26Concurrency.png 711w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2025\/01\/Time26Concurrency-300x207.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2025\/01\/Time26Concurrency-705x487.png 705w\" sizes=\"auto, (max-width: 711px) 100vw, 711px\" \/><\/figure>\n\n\n\n<p>The following paragraph about sequential consistency is optional. You can easily ignore it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sequential Consistency <\/h2>\n\n\n\n<p>In my examples, I use the default memory ordering: <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/sequential-consistency\/\">sequential consistency<\/a>. The reason is simple. Sequential consistency provides the strongest guarantees of all memory ordering and is, therefore, easier to use than the other memory orders. Sequential consistency is an ideal starting point when designing lock-free data structures. In further optimization steps, you can weaken the memory ordering and apply <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/acquire-release-semantic\/\">acquire-release semantics<\/a> or <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/relaxed-semantics\/\">relaxed semantics<\/a>.<\/p>\n\n\n\n<p><br>Depending on the architecture, weakening the memory ordering may not pay off. For example, the<br>x86 memory model is one of the strongest memory models of all modern architectures. As a result,<br>breaking the sequential consistency and applying a weaker memory ordering might not give the<br>performance improvements you hoped for. On the contrary, ARMv8, PowerPC, Itanium, and, in<br>particular, DEC alpha may pay off when breaking the sequential consistency.<\/p>\n\n\n\n<p>The simplified stack version from the last article has two issues. First, it does not have a <code>pull <\/code>  operation, and second, it releases no memory.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Complete Implementation<\/h2>\n\n\n\n<p>Typically, a stack supports the member functions <code>push<\/code>, <code>pop<\/code>, and <code>top<\/code>. Implementing the <code>pop <\/code>and <code>top<\/code> member functions thread-safe, does not guarantee that the invocation of <code>top <\/code>followed by <code>pop <\/code>is threadsafe. It may happen that one thread<code> t1<\/code> called <code>stack.top()<\/code> and is interleaved by another thread <code>t2<\/code> that called <code>stack.top() <\/code>and then<code> stack.pop()<\/code>. Now, the final <code>pop <\/code>call is based on the wrong stack size.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">No Memory Reclamation<\/h3>\n\n\n\n<p>Consequentially, the following implementation combines the two member functions <code>top <\/code>and <code>pop <\/code>into one: <code>topAndPop<\/code>.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ lockFreeStackWithLeaks.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;atomic&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;future&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;stdexcept&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span><span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">LockFreeStack<\/span> {\n <span style=\"color: #9999FF\">private:<\/span>\n    <span style=\"color: #006699; font-weight: bold\">struct<\/span> Node {\n        T data;\n        Node<span style=\"color: #555555\">*<\/span> next;\n        Node(T d)<span style=\"color: #555555\">:<\/span> data(d), next(nullptr){ }\n    };\n    std<span style=\"color: #555555\">::<\/span>atomic<span style=\"color: #555555\">&lt;<\/span>Node<span style=\"color: #555555\">*&gt;<\/span> head;\n <span style=\"color: #9999FF\">public:<\/span>\n    LockFreeStack() <span style=\"color: #555555\">=<\/span> <span style=\"color: #006699; font-weight: bold\">default<\/span>;\n    LockFreeStack(<span style=\"color: #006699; font-weight: bold\">const<\/span> LockFreeStack<span style=\"color: #555555\">&amp;<\/span>) <span style=\"color: #555555\">=<\/span> <span style=\"color: #006699; font-weight: bold\">delete<\/span>;\n    LockFreeStack<span style=\"color: #555555\">&amp;<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span><span style=\"color: #555555\">=<\/span> (<span style=\"color: #006699; font-weight: bold\">const<\/span> LockFreeStack<span style=\"color: #555555\">&amp;<\/span>) <span style=\"color: #555555\">=<\/span> <span style=\"color: #006699; font-weight: bold\">delete<\/span>;\n   \n    <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">push<\/span>(T val) {\n        Node<span style=\"color: #555555\">*<\/span> <span style=\"color: #006699; font-weight: bold\">const<\/span> newNode <span style=\"color: #555555\">=<\/span> <span style=\"color: #006699; font-weight: bold\">new<\/span> Node(val);\n        newNode<span style=\"color: #555555\">-&gt;<\/span>next <span style=\"color: #555555\">=<\/span> head.load();\n        <span style=\"color: #006699; font-weight: bold\">while<\/span>( <span style=\"color: #555555\">!<\/span>head.compare_exchange_strong(newNode<span style=\"color: #555555\">-&gt;<\/span>next, newNode) );\n    }\n\n    T <span style=\"color: #CC00FF\">topAndPop<\/span>() {\n        Node<span style=\"color: #555555\">*<\/span> oldHead <span style=\"color: #555555\">=<\/span> head.load();                                                 <span style=\"color: #0099FF; font-style: italic\">\/\/ 1<\/span>\n        <span style=\"color: #006699; font-weight: bold\">while<\/span>( oldHead <span style=\"color: #555555\">&amp;&amp;<\/span> <span style=\"color: #555555\">!<\/span>head.compare_exchange_strong(oldHead, oldHead<span style=\"color: #555555\">-&gt;<\/span>next) ) {  <span style=\"color: #0099FF; font-style: italic\">\/\/ 2<\/span>\n            <span style=\"color: #006699; font-weight: bold\">if<\/span> ( <span style=\"color: #555555\">!<\/span>oldHead ) <span style=\"color: #006699; font-weight: bold\">throw<\/span> std<span style=\"color: #555555\">::<\/span>out_of_range(<span style=\"color: #CC3300\">&quot;The stack is empty!&quot;<\/span>);          <span style=\"color: #0099FF; font-style: italic\">\/\/ 3<\/span>\n        }\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> oldHead<span style=\"color: #555555\">-&gt;<\/span>data;                                                        <span style=\"color: #0099FF; font-style: italic\">\/\/ 4<\/span>\n    }\n};\n   \n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>(){\n\n    LockFreeStack<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> lockFreeStack;\n    \n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> fut <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>async([<span style=\"color: #555555\">&amp;<\/span>lockFreeStack]{ lockFreeStack.push(<span style=\"color: #FF6600\">2011<\/span>); });\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> fut1 <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>async([<span style=\"color: #555555\">&amp;<\/span>lockFreeStack]{ lockFreeStack.push(<span style=\"color: #FF6600\">2014<\/span>); });\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> fut2 <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>async([<span style=\"color: #555555\">&amp;<\/span>lockFreeStack]{ lockFreeStack.push(<span style=\"color: #FF6600\">2017<\/span>); });\n    \n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> fut3 <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>async([<span style=\"color: #555555\">&amp;<\/span>lockFreeStack]{ <span style=\"color: #006699; font-weight: bold\">return<\/span> lockFreeStack.topAndPop(); });\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> fut4 <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>async([<span style=\"color: #555555\">&amp;<\/span>lockFreeStack]{ <span style=\"color: #006699; font-weight: bold\">return<\/span> lockFreeStack.topAndPop(); });\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> fut5 <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>async([<span style=\"color: #555555\">&amp;<\/span>lockFreeStack]{ <span style=\"color: #006699; font-weight: bold\">return<\/span> lockFreeStack.topAndPop(); });\n    \n    fut.get(), fut1.get(), fut2.get();                            <span style=\"color: #0099FF; font-style: italic\">\/\/ 5  <\/span>\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> fut3.get() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> fut4.get() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> fut5.get() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n}\n<\/pre><\/div>\n\n\n\n<p>The member function <code>topAndPop <\/code>returns the top element of the stack. It reads the head element of the stack (line 1) and makes the next node the new head if <code>oldHead <\/code>is not a <code>nullptr <\/code>(line 2). <code>oldhead <\/code>is a <code>nullptr <\/code>if the stack is empty. I throw an exception if the stack is empty (line 3). Returning a special non-value or returning a <code>std::optional<\/code> is also a valid option. Copying the value has a downside. If the copy constructor of the value throws an exception such as <code>std::bad_alloc<\/code>, the value is lost. Finally, the member functions returns the head element (line 4).<br><\/p>\n\n\n\n<p>The calls<code> fut.get(), fut1.get(), fut2.get() <\/code>(line 5) ensure that the associated promise runs. If you don\u2019t specify the launch policy the promise may run lazily in the caller\u2019s thread. Lazily means that the promise will be executed if and only if the future asks for its result with <code>get <\/code>or <code>wait<\/code>. You can also launch the promise in a separate thread:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">auto<\/span> fut <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>async(std<span style=\"color: #555555\">::<\/span>launch<span style=\"color: #555555\">::<\/span>asnyc, [<span style=\"color: #555555\">&amp;<\/span>conStack]{ conStack.push(<span style=\"color: #FF6600\">2011<\/span>); });\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> fut1 <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>async(std<span style=\"color: #555555\">::<\/span>launch<span style=\"color: #555555\">::<\/span>asnyc, [<span style=\"color: #555555\">&amp;<\/span>conStack]{ conStack.push(<span style=\"color: #FF6600\">2014<\/span>); });\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> fut2 <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>async(std<span style=\"color: #555555\">::<\/span>launch<span style=\"color: #555555\">::<\/span>asnyc, [<span style=\"color: #555555\">&amp;<\/span>conStack]{ conStack.push(<span style=\"color: #FF6600\">2017<\/span>); });\n<\/pre><\/div>\n\n\n\n<p>Finally, the output of the program:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"446\" height=\"218\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2025\/02\/lockFreeStackWithLeaks.png\" alt=\"\" class=\"wp-image-10624\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2025\/02\/lockFreeStackWithLeaks.png 446w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2025\/02\/lockFreeStackWithLeaks-300x147.png 300w\" sizes=\"auto, (max-width: 446px) 100vw, 446px\" \/><\/figure>\n\n\n\n<p>Although the presented lock-free stack supports <code>push<\/code> and <code>topAndPop<\/code>, it has a serious issue: it leaks memory. You may ask: Why can\u2019t the <code>oldHead <\/code>just be removed after the call <code>head.compare_exchange_strong(oldHead, oldHead->next)<\/code> (line 2) in the member function <code>topAndPop<\/code>? The answer is that another thread may use <code>oldHead<\/code>. Let\u2019s analyze the member functions <code>push <\/code>and <code>topAndPop<\/code>. Concurrent execution of <code>push <\/code>is no issue because the call<code> !head.compare_exchange_strong(newNode->next, newNode)<\/code> atomically updates <code>newNode->next<\/code> to the new head. It is also valid if only one <code>topAndPop <\/code>call happens. The issue arises when more <code>topAndPop <\/code>calls interleave with or without a <code>push<\/code> call. Deleting the <code>oldHead <\/code>while another thread uses it would be disastrous because the deletion of <code>oldHead <\/code>must always happen before or after its update to the new head: <code>oldHead->next<\/code> (line 2).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next?<\/h2>\n\n\n\n<p>Thanks to RCU and Hazard Pointers, I can solve the memory leaks in my next post. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>My last lock-free stack implementation was incomplete. It only supported push operations. Let&#8217;s change this. The following paragraph about sequential consistency is optional. You can easily ignore it. Sequential Consistency In my examples, I use the default memory ordering: sequential consistency. The reason is simple. Sequential consistency provides the strongest guarantees of all memory ordering [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":10580,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[559],"tags":[563],"class_list":["post-10619","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c26-blog","tag-hazard-pointers"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10619","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=10619"}],"version-history":[{"count":5,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10619\/revisions"}],"predecessor-version":[{"id":10636,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10619\/revisions\/10636"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/10580"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=10619"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=10619"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=10619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}