<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Memory-Ordering on Opensource internals</title><link>https://articles.9j.nz/tags/memory-ordering/</link><description>Posts filed under Memory-Ordering on Opensource internals.</description><generator>Hugo</generator><language>en-US</language><managingEditor>Jay Hubbert</managingEditor><lastBuildDate>Wed, 21 Oct 2026 03:57:00 +0000</lastBuildDate><atom:link href="https://articles.9j.nz/tags/memory-ordering/index.xml" rel="self" type="application/rss+xml"/><item><title>A Memory Ordering Bug in DataFusion's Hash Join, Found by Model Checking Rather Than Testing</title><link>https://articles.9j.nz/posts/how-datafusion-model-checks-its-join-concurrency/</link><pubDate>Wed, 21 Oct 2026 03:57:00 +0000</pubDate><dc:creator>Jay Hubbert</dc:creator><guid isPermaLink="true">https://articles.9j.nz/posts/how-datafusion-model-checks-its-join-concurrency/</guid><category>datafusion</category><category>joins</category><category>concurrency</category><category>memory-ordering</category><category>internals</category><description>The probe partitions of a hash join must share two facts, and reading one without ordering it against the other produced wrong results — a bug loom found and a concurrency test never would.</description><content:encoded>&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; The probe partitions of a partitioned hash join have to agree&#10;on two facts: which one finishes last (it emits the build-side rows), and&#10;what they collectively saw (did anyone see a NULL join key?). Reading&#10;the second without ordering it against the first produced &lt;em&gt;wrong&#10;results&lt;/em&gt;. The fix is a single &lt;code&gt;AcqRel&lt;/code&gt; counter decrement, and the bug it&#10;fixed could not be found by a concurrent test — it was found by&#10;&lt;a href="https://docs.rs/loom"&gt;loom&lt;/a&gt;, a model checker that enumerates every&#10;interleaving the memory model allows.&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;Concurrency bugs in query engines are usually found the hard way: a&#10;query that returns wrong answers once a week, in production, on a&#10;machine with 64 cores. DataFusion has taken the other approach for one&#10;particular protocol: model check it.&lt;/p&gt;&#10;&lt;h2 id="the-protocol"&gt;The protocol&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;datafusion/physical-plan/src/joins/hash_join/probe_completion.rs&lt;/code&gt; is a&#10;small file with a very carefully written module doc. The setup:&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;The probe partitions of one &lt;code&gt;HashJoinExec&lt;/code&gt; run concurrently over a shared&#10;build side. Two facts have to cross partition boundaries:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;which partition emits the build-side rows in the final stage, namely the&#10;last one to finish, and&lt;/li&gt;&#10;&lt;li&gt;what the partitions collectively saw, which the null-aware &lt;code&gt;NOT IN&lt;/code&gt; rules&#10;need: did any partition see a row, and did any see a NULL join key.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;So there are N probe tasks, each streaming a slice of the probe side, all&#10;sharing one build side. When a probe row&amp;rsquo;s key is NULL, the null-aware&#10;&lt;code&gt;NOT IN&lt;/code&gt; semantics say the &lt;em&gt;whole&lt;/em&gt; result is NULL — but only if some&#10;&lt;em&gt;other&lt;/em&gt; partition saw a NULL. And exactly one partition — the last to&#10;finish — has to emit the build-side rows for the &lt;code&gt;LeftMark&lt;/code&gt; case.&lt;/p&gt;&#10;&lt;p&gt;The state is three atomics:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;rust&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ProbeCompletion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Probe partitions that have not finished yet.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;running&lt;/span&gt;: &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Set once any probe partition has seen a row.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;saw_row&lt;/span&gt;: &lt;span class="nc"&gt;Flag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Set once any probe partition has seen a NULL join key.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;saw_null_key&lt;/span&gt;: &lt;span class="nc"&gt;Flag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;h2 id="the-bug"&gt;The bug&lt;/h2&gt;&#10;&lt;p&gt;Here is the module doc&amp;rsquo;s account of what went wrong:&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;[&lt;code&gt;ProbeCompletion&lt;/code&gt;] owns both, because reading the second without ordering&#10;it against the first produced wrong results. A partition that read the NULL&#10;flag &lt;em&gt;before&lt;/em&gt; decrementing the counter could observe &lt;code&gt;false&lt;/code&gt;, have a&#10;sibling record a NULL and finish, then become the last partition itself and&#10;emit build rows that &lt;code&gt;NOT IN&lt;/code&gt; must suppress.&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;Read that sequence carefully, because it is a textbook time-of-check /&#10;time-of-use across threads:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Partition A reads &lt;code&gt;saw_null_key&lt;/code&gt; → &lt;code&gt;false&lt;/code&gt;. (It read the flag &lt;em&gt;before&lt;/em&gt;&#10;decrementing the counter.)&lt;/li&gt;&#10;&lt;li&gt;Partition B records a NULL key → &lt;code&gt;saw_null_key = true&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;Partition B finishes, decrements the counter.&lt;/li&gt;&#10;&lt;li&gt;Partition A decrements the counter — and is now the last partition.&lt;/li&gt;&#10;&lt;li&gt;Partition A emits build-side rows, believing no NULL was seen.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;But a NULL &lt;em&gt;was&lt;/em&gt; seen, so &lt;code&gt;NOT IN&lt;/code&gt; should have suppressed those rows. The&#10;query returns wrong results.&lt;/p&gt;&#10;&lt;p&gt;And it is a &lt;em&gt;narrow&lt;/em&gt; window: partition A must read the flag, then&#10;partition B must record and finish, then A must decrement and find itself&#10;last. That is a few instructions wide, and it needs a specific&#10;interleaving on a machine with many cores.&lt;/p&gt;&#10;&lt;h2 id="the-invariant"&gt;The invariant&lt;/h2&gt;&#10;&lt;p&gt;The fix is to state the property precisely and then design the type so&#10;that the property is hard to violate:&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;The invariant is therefore: &lt;strong&gt;whichever caller observes itself to be last&#10;sees every fact recorded by every other partition.&lt;/strong&gt; It rests on two&#10;properties, and the type is shaped to keep both.&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;em&gt;Order.&lt;/em&gt; The facts are reachable only through the value returned by&#10;[&lt;code&gt;ProbeCompletion::report_completed&lt;/code&gt;], so no caller can read them before&#10;its own decrement.&lt;/li&gt;&#10;&lt;li&gt;&lt;em&gt;Visibility.&lt;/em&gt; That decrement is &lt;code&gt;AcqRel&lt;/code&gt;, so the last partition&#10;synchronizes with the release of every partition that finished before&#10;it. Were the counter &lt;code&gt;Relaxed&lt;/code&gt;, nothing would order a sibling&amp;rsquo;s store&#10;before the final load even when the decrement happened first.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;Property 1 is &lt;em&gt;structural&lt;/em&gt;: the summary is not a field you can read. It&#10;comes back from &lt;code&gt;report_completed&lt;/code&gt;, and the only way to get it is to have&#10;decremented. You cannot read the flags early because there is no API to&#10;read them early.&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;rust&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// What every probe partition together saw, as observed by the last one to&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// finish.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;///&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// Obtainable only from [`ProbeCompletion::report_completed`], which is what&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// stops the final stage from reading the shared state too early.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#[derive(Debug, Clone, Copy, PartialEq, Eq)]&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ProbeSideSummary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Some probe partition saw a row. An entirely empty probe side is not the&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// same as one that matched nothing: `NULL NOT IN (empty)` is TRUE.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;non_empty&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Some probe partition saw a NULL join key.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;has_null&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Property 2 is the memory ordering:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;rust&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;report_completed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ProbeSideSummary&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// `fetch_sub` returns the value from *before* the decrement,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// so `1` means this call is the one that took it to zero.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;was_last&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;running&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch_sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;::&lt;span class="n"&gt;AcqRel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;was_last&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProbeSideSummary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;non_empty&lt;/span&gt;: &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;saw_row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;::&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;has_null&lt;/span&gt;: &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;saw_null_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;::&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;The &lt;code&gt;AcqRel&lt;/code&gt; decrement does double duty. It &lt;em&gt;releases&lt;/em&gt; this partition&amp;rsquo;s&#10;own stores (so other partitions that finish later can see them), and it&#10;&lt;em&gt;acquires&lt;/em&gt; the stores of the partitions that finished earlier (so the last&#10;partition sees their facts). The subsequent &lt;code&gt;Relaxed&lt;/code&gt; loads are then safe,&#10;because the acquire side of the decrement has already established the&#10;happens-before relationship.&lt;/p&gt;&#10;&lt;p&gt;The &lt;code&gt;Relaxed&lt;/code&gt; stores during the run are fine too:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;rust&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// Records what one probe partition saw in one batch.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;///&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// `Relaxed` suffices: the `AcqRel` decrement in&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// [`Self::report_completed`] publishes these stores to the last&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// partition.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;record_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;non_empty&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;has_null&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;non_empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;saw_row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;::&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;has_null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;saw_null_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;::&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Relaxed stores plus one AcqRel fence at the end is the standard&#10;&amp;ldquo;accumulate in a relaxed manner, publish once&amp;rdquo; pattern, and it is much&#10;cheaper than an acquire-release store on every batch.&lt;/p&gt;&#10;&lt;h2 id="the-hint-that-may-lag"&gt;The hint that may lag&lt;/h2&gt;&#10;&lt;p&gt;There is also a &lt;em&gt;hint&lt;/em&gt; interface, and it is explicitly allowed to be&#10;stale:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;rust&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// Whether some partition has already recorded a NULL join key.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;///&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// A hint for skipping work during the probe phase, which may lag&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// behind sibling partitions. It must never decide what the final&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// stage emits; use the [`ProbeSideSummary`] from&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// [`Self::report_completed`] for that.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;saw_null_key_hint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;saw_null_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;::&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;A &lt;em&gt;hint&lt;/em&gt; is allowed to be wrong in one direction (it may miss a NULL that&#10;was just recorded) but not the other (it may never report a NULL that was&#10;not recorded). The test says exactly that:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;rust&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// The hint may lag, but it must never report a NULL that was not&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// recorded.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;So the type system and the naming (&lt;code&gt;hint&lt;/code&gt; vs &lt;code&gt;summary&lt;/code&gt;) encode the&#10;difference between &amp;ldquo;an optimisation that may be conservative&amp;rdquo; and &amp;ldquo;the&#10;fact you must use for correctness&amp;rdquo;.&lt;/p&gt;&#10;&lt;h2 id="the-model-check"&gt;The model check&lt;/h2&gt;&#10;&lt;p&gt;Now the part that makes this a great story. The module doc:&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;Neither property can be pinned down by an ordinary concurrent test: the&#10;window is a few instructions wide, and on x86 a &lt;code&gt;Relaxed&lt;/code&gt; decrement lowers&#10;to the same instruction as an &lt;code&gt;AcqRel&lt;/code&gt; one. Both are model-checked in&#10;&lt;code&gt;loom_tests&lt;/code&gt; instead.&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;That last point is the one that makes model checking &lt;em&gt;necessary&lt;/em&gt; rather&#10;than merely nice. On x86, &lt;code&gt;fetch_sub&lt;/code&gt; with &lt;code&gt;Relaxed&lt;/code&gt; and with &lt;code&gt;AcqRel&lt;/code&gt;&#10;compile to the &lt;strong&gt;same machine instruction&lt;/strong&gt; (&lt;code&gt;lock xadd&lt;/code&gt;). The difference&#10;is only visible to the &lt;em&gt;memory model&lt;/em&gt; — to the compiler&amp;rsquo;s and CPU&amp;rsquo;s&#10;permission to reorder and to the hardware&amp;rsquo;s cache-coherence visibility.&lt;/p&gt;&#10;&lt;p&gt;Which means:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;A test on x86 might not catch it, because the hardware is strong enough&#10;to make the bug invisible.&lt;/li&gt;&#10;&lt;li&gt;A test on ARM might catch it by accident, but only sometimes.&lt;/li&gt;&#10;&lt;li&gt;A &lt;em&gt;model checker&lt;/em&gt; catches it deterministically, because it simulates&#10;the weak-memory model rather than running on real hardware.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;The &lt;code&gt;loom&lt;/code&gt; model checker enumerates every interleaving and every store&#10;visibility the memory model allows, and fails if the protocol violates&#10;the invariant. And the tests fail if the decrement is weakened to&#10;&lt;code&gt;Relaxed&lt;/code&gt;:&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;These instantiate the protocol over loom&amp;rsquo;s atomics (see the&#10;&lt;a href="self"&gt;module docs&lt;/a&gt;) and let loom enumerate the interleavings and store&#10;visibility the memory model allows. They fail if the decrement in&#10;&lt;code&gt;report_completed&lt;/code&gt; is weakened to &lt;code&gt;Relaxed&lt;/code&gt;.&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="one-copy-of-the-protocol-two-instantiations"&gt;One copy of the protocol, two instantiations&lt;/h2&gt;&#10;&lt;p&gt;The way the code makes the model check &lt;em&gt;meaningful&lt;/em&gt; is a macro:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;rust&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// Defines [`ProbeCompletion`] over the given atomic types.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;///&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// [loom] can only explore its own atomics, so the protocol is written once&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// here and instantiated twice: over [`std::sync::atomic`] for the join, and&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// over `loom::sync::atomic` for the model in `loom_tests`. Both share this&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// single copy of the orderings and the call sequence, which is what lets&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// the model speak for the real thing. Keep it that way: a second copy of these&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// orderings would not be covered.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;macro_rules&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;define_probe_completion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;: &lt;span class="cp"&gt;$counter&lt;/span&gt;:&lt;span class="nc"&gt;ty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;: &lt;span class="cp"&gt;$flag&lt;/span&gt;:&lt;span class="nc"&gt;ty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;This is the crucial bit. If the production code and the model were two&#10;separate implementations, the model would be checking a &lt;em&gt;different&lt;/em&gt;&#10;program and proving nothing. By making the protocol a macro parameterised&#10;only by the atomic types, the &lt;em&gt;orderings&lt;/em&gt; — the actual subject of the&#10;model — are literally the same source text in both.&lt;/p&gt;&#10;&lt;p&gt;The doc is emphatic: &amp;ldquo;Keep it that way: a second copy of these orderings&#10;would not be covered.&amp;rdquo;&lt;/p&gt;&#10;&lt;h2 id="running-it"&gt;Running it&lt;/h2&gt;&#10;&lt;p&gt;The loom tests are behind a cfg flag, because loom is &lt;em&gt;slow&lt;/em&gt; — it&#10;explores an exponential space:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;rust&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;/// RUSTFLAGS=&amp;#34;--cfg datafusion_loom&amp;#34; cargo test -p datafusion-physical-plan --lib loom_tests&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;So the model check is not in the normal test run. It is a separate&#10;invocation, run deliberately.&lt;/p&gt;&#10;&lt;h2 id="the-catch"&gt;The catch&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Loom is exponential.&lt;/strong&gt; It explores the full interleaving space, so the&#10;test is limited to a small number of participants. It proves the&#10;&lt;em&gt;protocol&lt;/em&gt; correct for a small case, not the whole join.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;The model is per-atomic-type.&lt;/strong&gt; Loom only understands its own atomics,&#10;which is why the macro exists. Any state the protocol touches that is&#10;&lt;em&gt;not&lt;/em&gt; an atomic — a &lt;code&gt;Mutex&lt;/code&gt;, say — is outside the model.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;The &lt;code&gt;Relaxed&lt;/code&gt; stores are only safe because of the &lt;code&gt;AcqRel&lt;/code&gt; decrement.&lt;/strong&gt;&#10;Change the decrement to &lt;code&gt;Relaxed&lt;/code&gt; and the model check fails. Change the&#10;stores to &lt;code&gt;Relaxed&lt;/code&gt; (they already are) and nothing breaks. The ordering&#10;discipline is a single point of failure, which is why the model check&#10;exists.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;The &lt;code&gt;hint&lt;/code&gt; interface is a permanent footgun.&lt;/strong&gt; It is one field access&#10;away from being used for something it must not decide. The naming and&#10;the doc comment are the only defences.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="why-it-matters"&gt;Why it matters&lt;/h2&gt;&#10;&lt;p&gt;This file is a good template for how to handle a subtle concurrency&#10;protocol in a codebase that people actually contribute to:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;State the invariant in one sentence&lt;/strong&gt;, in the module doc, in bold.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Make the wrong thing impossible to express&lt;/strong&gt; — the summary is only&#10;obtainable through the operation that establishes the ordering.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Use the cheapest memory ordering that is correct&lt;/strong&gt;, and explain why&#10;the more expensive one is not needed.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Model check it&lt;/strong&gt;, and make the model check the &lt;em&gt;same code&lt;/em&gt; as&#10;production.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Point 4 is the one that generalises. &amp;ldquo;Add a concurrency test&amp;rdquo; is the&#10;usual advice and it is often wrong: a test can only find the interleaving&#10;it happens to hit, and on a strong memory model the bug may not exist at&#10;the hardware level at all. A model checker explores the space the&#10;&lt;em&gt;language&lt;/em&gt; permits, which is the space you actually have to be correct in.&lt;/p&gt;&#10;</content:encoded></item></channel></rss>