{"id":10563,"date":"2025-01-27T12:23:43","date_gmt":"2025-01-27T12:23:43","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=10563"},"modified":"2025-07-03T14:30:34","modified_gmt":"2025-07-03T14:30:34","slug":"deferred-reclamation-in-c26-read-copy-update-and-hazard-pointers","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/deferred-reclamation-in-c26-read-copy-update-and-hazard-pointers\/","title":{"rendered":"Deferred Reclamation in C++26: Read-Copy Update and Hazard Pointers"},"content":{"rendered":"\n<p>Before I dive into lock-free programming, there&#8217;s a little bit of theory necessary.<\/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>A common problem in concurrency is the so-called ABA problem. That means you read a variable twice, which returns the same value each time, A. Therefore, you conclude that nothing changed in between. But you forgot the B.<\/p>\n\n\n\n<p>Let me first use a simple scenario to introduce the problem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"An_Analogy\"><\/span>An Analogy<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The scenario involves you sitting in a car and waiting for the traffic light to turn green. In our case, green stands for B, and red for A. What\u2019s happening?<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>You look at the traffic light, and it is red (A).<\/li>\n\n\n\n<li>Because you are bored, you begin to check the news on your smartphone and forget the time.<\/li>\n\n\n\n<li>You look once more at the traffic light. Damn, is still red (A).<\/li>\n<\/ol>\n\n\n\n<p>Of course, the traffic light became green (B) between your two checks. Therefore, what seems to be one red phase was two.<\/p>\n\n\n\n<p>What does this mean for threads (processes)? Now, once more formal.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Thread 1 reads a variable var with value A.<\/li>\n\n\n\n<li>Thread 1 is preempted, and thread 2 runs.<\/li>\n\n\n\n<li>Thread 2 changes the variable var from A to B to A.<\/li>\n\n\n\n<li>Thread 1 starts to execute and checks the value of variable var; because the value of variable var is the same, thread 1 continues with its work,<\/li>\n<\/ol>\n\n\n\n<p>Often, that is a no-brainer. You can ignore it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Atomic_Multiplication\"><\/span>Atomic Multiplication<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Have a look at it here. The function <code>fetch_mult <\/code>(1) multiplies a<code> std::atomic&lt;T&gt;&amp;<\/code> shared by <code>mult<\/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\">\/\/ fetch_mult.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;atomic&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&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>\nT fetch_mult(std<span style=\"color: #555555\">::<\/span>atomic<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;&amp;<\/span> shared, T mult){                          <span style=\"color: #0099FF; font-style: italic\">\/\/ 1<\/span>\n  T oldValue <span style=\"color: #555555\">=<\/span> shared.load();                                          <span style=\"color: #0099FF; font-style: italic\">\/\/ 2<\/span>\n  <span style=\"color: #006699; font-weight: bold\">while<\/span> (<span style=\"color: #555555\">!<\/span>shared.compare_exchange_strong(oldValue, oldValue <span style=\"color: #555555\">*<\/span> mult));  <span style=\"color: #0099FF; font-style: italic\">\/\/ 3<\/span>\n  <span style=\"color: #006699; font-weight: bold\">return<\/span> oldValue;\n}\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> main(){\n  std<span style=\"color: #555555\">::<\/span>atomic<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> myInt{<span style=\"color: #FF6600\">5<\/span>};\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> myInt <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;          \n  fetch_mult(myInt,<span style=\"color: #FF6600\">5<\/span>);\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> myInt <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;         \n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><code>shared.compare_exchange_strong(expected, desired)<\/code>(3) has the following behavior:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If the comparison returns <code>false<\/code>, <code>expected <\/code>is set to <code>shared<\/code><\/li>\n\n\n\n<li>If the atomic comparison of <code>shared <\/code>with <code>expected <\/code>returns <code>true<\/code>, <code>shared <\/code>is set in the same atomic operation to <code>expected<\/code><\/li>\n<\/ul>\n\n\n\n<p>The key observation is that there is a small time window between the reading of the old value<code> T<\/code> <code>oldValue = shared.load <\/code>(2) and the&nbsp;comparison with the new value (3). Therefore, another thread can kick in and change the <code>oldValue <\/code>from <code>oldValue <\/code>to <code>anotherValue <\/code>to <code>oldValue <\/code>back. The <code>anotherValue <\/code>is the B in ABA. <\/p>\n\n\n\n<p>Let me exemplify ABA in a lock-free data structure.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"A_lock-free_Stack\"><\/span>A lock-free Stack<span class=\"ez-toc-section-end\"><\/span><\/h1>\n\n\n\n<p> I will use a lock-free stack implemented as a single linked list. The stack supports only two operations.&nbsp;<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Pops the top object and returns a pointer to it.<\/li>\n\n\n\n<li>Pushes the object specified&nbsp;to stack.<\/li>\n<\/ol>\n\n\n\n<p>Let me describe the pop operation in pseudo-code to give you an idea of the ABA problem. The pop operation performs the following steps in a loop until it is successful.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Get the head node: <strong>head<\/strong><\/li>\n\n\n\n<li>Get the subsequent node: <strong>headNext<\/strong><\/li>\n\n\n\n<li>Make <strong>headNext<\/strong> to the new head if <strong>head<\/strong> is still the head of the stack<\/li>\n<\/ul>\n\n\n\n<p>Here are the first two nodes of the stack:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Stack: TOP -&gt; head -&gt; headNext -&gt; ...\n<\/pre>\n\n\n\n<p>Let\u2019s construct the ABA problem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ABA_in_action\"><\/span>ABA in action<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Let\u2019s start with the following stack:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Stack: TOP -&gt; A -&gt; B -&gt; C\n<\/pre>\n\n\n\n<p>Thread 1 is active and wants to pop the head of stack.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Thread 1 stores\n<ul class=\"wp-block-list\">\n<li>head = A<\/li>\n\n\n\n<li>headNext = B<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Before thread 1 finishes the pop algorithm, thread 2 kicks in.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Thread 2 pops A<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">    Stack: TOP -&gt; B -&gt; C\n<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>&nbsp;Thread 2 pops B and deletes B<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">    Stack: TOP -&gt; C\n<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Thread 2 pushes A back<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">    Stack: TOP -&gt; A -&gt; C\n<\/pre>\n\n\n\n<p>Thread 1 is rescheduled to check if A == head. Because A == head, headNext, which is B, becomes the new head. But B was already deleted. Therefore, the program has undefined behavior.<\/p>\n\n\n\n<p>There are a few remedies for the ABA problem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Remedy_for_ABA\"><\/span>Remedy for ABA<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The conceptual problem of ABA is relatively easy to understand. A node such as B == headNext was deleted, although another node, A == head, was referring to it. The solution to our problem is to eliminate the premature deletion of the node. Here are a few remedies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Tagged_state_reference\"><\/span>Tagged state reference<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>You can add a tag indicating how often the node has been successfully modified. However, the compare and swap method will eventually fail, although the check returns true.&nbsp;<\/p>\n\n\n\n<p>The next three techniques are based on the idea of deferred reclamation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Garbage_collection\"><\/span>Garbage collection<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Garbage collection guarantees that the variables will only be deleted if they are not needed anymore. That sounds promising but has a big drawback. Most garbage collectors are not lock-free. Therefore, you have a lock-free data structure, but the overall system is not lock-free.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Hazard_pointers\"><\/span>Hazard pointers<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>From <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hazard_pointer\">Wikipedia: Hazard Pointers<\/a>:<\/p>\n\n\n\n<p>In a hazard-pointer system, each thread keeps a list<a href=\"https:\/\/en.wikipedia.org\/wiki\/List_%28computing%29\"><\/a> of hazard pointers indicating which nodes the thread is accessing. (This \u201clist\u201d may be limited to only one or two elements in many systems.) Nodes on the hazard pointer list must not be modified or deallocated by any other thread. \u2026&nbsp;When a thread wishes to remove a node, it places it on a list of nodes \u201cto be freed later\u201d but does not deallocate the node\u2019s memory until no other thread\u2019s hazard list contains the pointer. A dedicated garbage-collection thread can do this manual garbage collection (if the list \u201cto be freed later\u201d is shared by all the threads); alternatively, cleaning up the \u201cto be freed\u201d list can be done by each worker thread as part of an operation such as \u201cpop\u201d.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"RCU\"><\/span>RCU<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>RCU stands for <strong>R<\/strong>ead <strong>C<\/strong>opy<strong> U<\/strong>pdate, a synchronization technique for almost read-only data structures created by Paul McKenney and used in the Linux Kernel since 2002.&nbsp;<\/p>\n\n\n\n<p>The idea is quite simple and follows the acronym. To modify data, you make a copy of the data and modify that copy. On the contrary, all readers work with the original data. You can safely replace the data structure with the copy if there is no reader.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Whats_Next\"><\/span>What\u2019s Next?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p> In my next post, I will implement a lock-free stack with deferred reclamation.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Before I dive into lock-free programming, there&#8217;s a little bit of theory necessary. A common problem in concurrency is the so-called ABA problem. That means you read a variable twice, which returns the same value each time, A. Therefore, you conclude that nothing changed in between. But you forgot the B. Let me first use [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":10313,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[559],"tags":[563,564],"class_list":["post-10563","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c26-blog","tag-hazard-pointers","tag-rcu"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10563","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=10563"}],"version-history":[{"count":8,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10563\/revisions"}],"predecessor-version":[{"id":10582,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10563\/revisions\/10582"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/10313"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=10563"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=10563"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=10563"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}