<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">

<title>Strong Compare and Exchange</title>
</head>

<body>
<h1>Strong Compare and Exchange</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N2748 = 08-0258 - 2008-08-24
</p>

<p>
Lawrence Crowl, Lawrence@Crowl.org, crowl@google.com
</p>


<h2>Problem</h2>

<p>
The current C++ compare-and-exchange operation
was designed for maximal efficiency in the typical case
where it is used in a loop to achieve an atomic update
based on the value in the atomic variable.
</p>

<pre><code>
expected = current.load();
do desired = function(expected);
while (!current.compare_exchange(expected, desired));
</code></pre>

<p>
To achieve good efficiency on load-locked-store-conditional machines,
the operation is defined to be <dfn>spurious</dfn>,
that is the operation may fail
even when the <code>expected</code> value remains unchanged.
</p>

<p>
However,
there are some cases,
such as concurrently driving a state machine,
where a compare-and-exchange without spurious failure
would lead to simpler and more efficient code.
Of course, one can implement a non-spurious compare-and-exchange
with a spurious compare-and-exchange
via a function with a loop.
Unfortunately, this approach fails to take full advantage of machines
that provide non-spurious compare-and-exchange in hardware.
</p>


<h2>Solution</h2>

<p>
The solution proposed is the consensus of the concurrency subgroup meeting
in Sophia-Antipolis in June 2008.
It is
to provide both weak (spurious) and strong (non-spurious) compare-and-exchange.
</p>

<p>
We anticipate that most code
that naturally wraps the compare-exchange in a loop
will use the weak form
while most code
that naturally does not wrap the compare-exchange in a loop
will use the strong form.
</p>

<p>
To make this choice clear to programmers,
the concurrency subcommittee directed
that neither form be syntactically simpler than the other.
</p>


<h2>Wording</h2>

<p>
The changes to the wording
involve replacing each of the existing <code>compare_exchange</code> functions
with equivalent <code>compare_exchange_weak</code>
and <code>compare_exchange_strong</code> functions.
The semantic description of the functions
changes to incorporate the distinction.
</p>


<h3>20.7 Memory [memory]</h3>

<p>
In the header <code>&lt;memory&gt;</code> synopsis,
edit as follows.
</p>

<blockquote>
<p>...</p>

<pre>
<code>template&lt;class T&gt;
  bool atomic_compare_exchange<ins>_weak</ins>(shared_ptr&lt;T&gt; *p, shared_ptr&lt;T&gt; *v, shared_ptr&lt;T&gt; w);</code>
<code>template&lt;class T&gt;
  bool atomic_compare_exchange<ins>_weak</ins>_explicit(shared_ptr&lt;T&gt; *p, shared_ptr&lt;T&gt; *v, shared_ptr&lt;T&gt; w,
                                        memory_order success, memory_order failure);</code>
<ins><code>template&lt;class T&gt;
  bool atomic_compare_exchange_strong(shared_ptr&lt;T&gt; *p, shared_ptr&lt;T&gt; *v, shared_ptr&lt;T&gt; w);</code></ins>
<ins><code>template&lt;class T&gt;
  bool atomic_compare_exchange_strong_explicit(shared_ptr&lt;T&gt; *p, shared_ptr&lt;T&gt; *v, shared_ptr&lt;T&gt; w,
                                        memory_order success, memory_order failure);</code></ins>
</pre>

<p>...</p>
</blockquote>


<h3>20.7.12.5 shared_ptr atomic access [util.smartptr.shared.atomic]</h3>

<p>
Edit the description of <code>atomic_compare_exchange</code>
for <code>shared_ptr</code> in paragraphs 17 through 22 as follows.
</p>

<blockquote>

<pre>
<code>template&lt;class T&gt;
  bool atomic_compare_exchange<ins>_weak</ins>(shared_ptr&lt;T&gt; *p, shared_ptr&lt;T&gt; *v, shared_ptr&lt;T&gt; w);</code>
</pre>

<p>
<i>Returns:</i>
<code>atomic_compare_exchange<ins>_weak</ins>_explicit(p, v, w, memory_order_seq_cst, memory_order_seq_cst)</code>.
</p>

<pre>
<ins><code>template&lt;class T&gt;
  bool atomic_compare_exchange_strong(shared_ptr&lt;T&gt; *p, shared_ptr&lt;T&gt; *v, shared_ptr&lt;T&gt; w);</code></ins>
</pre>

<p>
<ins><i>Returns:</i>
<code>atomic_compare_exchange_strong_explicit(p, v, w, memory_order_seq_cst, memory_order_seq_cst)</code>.</ins>
</p>

<pre>
<code>template&lt;class T&gt;
  bool atomic_compare_exchange<ins>_weak</ins>_explicit(shared_ptr&lt;T&gt; *p, shared_ptr&lt;T&gt; *v, shared_ptr&lt;T&gt; w,
                                        memory_order success, memory_order failure);</code>
<ins><code>template&lt;class T&gt;
  bool atomic_compare_exchange_strong_explicit(shared_ptr&lt;T&gt; *p, shared_ptr&lt;T&gt; *v, shared_ptr&lt;T&gt; w,
                                        memory_order success, memory_order failure);</code></ins>
</pre>

<p>
<i>Requires:</i>
<code>failure</code> shall not be
<code>memory_order_release</code>, <code>memory_order_acq_rel</code>,
or stronger than <code>success</code>.
</p>

<p>
<i>Effects:</i>
If <code>*p</code> is equivalent to <code>*v</code>,
assigns <code>w</code> to <code>*p</code>
and has synchronization semantics
corresponding to to the value of <code>success</code>,
otherwise assigns <code>*p</code> to <code>*v</code>
and has synchronization semantics
corresponding to to the value of <code>failure</code>.
</p>

<p>
<i>Returns:</i>
<code>true</code> if <code>*p</code> was equivalent to <code>*v</code>,
<code>false</code> otherwise.
</p>

<p>
<i>Throws:</i>
nothing.
</p>

<p>
<i>Remarks:</i>
two <code>shared_ptr</code> objects are equivalent
if they store the same pointer value and share ownership.
</p>

<p>
<ins><i>Remarks:</i>
The weak forms may fail spuriously.
See 29.4 [atomics.types.operations].</ins>
</p>
</blockquote>


<h3>Chapter 29 Atomic operations library [atomics]</h3>

<p>
In the header <code>&lt;cstdattomic&gt;</code> synopsis,
edit as follows.
</p>

<blockquote>
<p>...</p>

<pre>
<code>bool atomic_compare_exchange<ins>_weak</ins>(volatile atomic_bool*, bool*, bool);</code>
<code>bool atomic_compare_exchange<ins>_weak</ins>_explicit(volatile atomic_bool*, bool*, bool,
                                      memory_order, memory_order);</code>
<ins><code>bool atomic_compare_exchange_strong(volatile atomic_bool*, bool*, bool);</code></ins>
<ins><code>bool atomic_compare_exchange_strong_explicit(volatile atomic_bool*, bool*, bool,
                                      memory_order, memory_order);</code></ins>
</pre>

<p>...</p>

<pre>
<code>bool atomic_compare_exchange<ins>_weak</ins>(volatile atomic_</code><var>itype</var><code> *, </code><var>integral</var><code> *, </code><var>integral</var><code>);</code>
<code>bool atomic_compare_exchange<ins>_weak</ins>_explicit(volatile atomic_</code><var>itype</var><code> *, </code><var>integral</var><code> *,
                                      </code><var>integral</var><code>, memory_order, memory_order);</code>
<ins><code>bool atomic_compare_exchange_strong(volatile atomic_</code><var>itype</var><code> *, </code><var>integral</var><code> *, </code><var>integral</var><code>);</code></ins>
<ins><code>bool atomic_compare_exchange_strong_explicit(volatile atomic_</code><var>itype</var><code> *, </code><var>integral</var><code> *,
                                      </code><var>integral</var><code>, memory_order, memory_order);</code></ins>
</pre>

<p>...</p>

<pre>
<code>bool atomic_compare_exchange<ins>_weak</ins>(volatile atomic_address*, void**, void*);</code>
<code>bool atomic_compare_exchange<ins>_weak</ins>_explicit(volatile atomic_address*, void**, void*,
                                      memory_order, memory_order);</code>
<ins><code>bool atomic_compare_exchange_strong(volatile atomic_address*, void**, void*);</code></ins>
<ins><code>bool atomic_compare_exchange_strong_explicit(volatile atomic_address*, void**, void*,
                                      memory_order, memory_order);</code></ins>
</pre>

<p>...</p>
</blockquote>


<h3>29.3.1 Integral Types [atomics.types.integral]</h3>

<p>
In the synopsis, edit as follows.
</p>

<blockquote>
<p>...</p>

<pre>
<code>bool compare_exchange<ins>_weak</ins>(bool&amp;, bool, memory_order, memory_order) volatile;</code>
<code>bool compare_exchange<ins>_weak</ins>(bool&amp;, bool, memory_order = memory_order_seq_cst) volatile;</code>
<ins><code>bool compare_exchange_strong(bool&amp;, bool, memory_order, memory_order) volatile;</code></ins>
<ins><code>bool compare_exchange_strong(bool&amp;, bool, memory_order = memory_order_seq_cst) volatile;</code></ins>
</pre>

<p>...</p>

<pre>
<code>bool atomic_compare_exchange<ins>_weak</ins>(volatile atomic_bool*, bool*, bool);</code>
<code>bool atomic_compare_exchange<ins>_weak</ins>_explicit(volatile atomic_bool*, bool*, bool,
                                      memory_order, memory_order);</code>
<ins><code>bool atomic_compare_exchange_strong(volatile atomic_bool*, bool*, bool);</code></ins>
<ins><code>bool atomic_compare_exchange_strong_explicit(volatile atomic_bool*, bool*, bool,
                                      memory_order, memory_order);</code></ins>
</pre>

<p>...</p>

<pre>
<code>bool compare_exchange<ins>_weak</ins>(</code><var>integral</var><code>&amp;, </code><var>integral</var><code>, memory_order, memory_order);</code>
<code>bool compare_exchange<ins>_weak</ins>(</code><var>integral</var><code>&amp;, </code><var>integral</var><code>, memory_order = memory_order_seq_cst);</code>
<ins><code>bool compare_exchange_strong(</code><var>integral</var><code>&amp;, </code><var>integral</var><code>, memory_order, memory_order);</code></ins>
<ins><code>bool compare_exchange_strong(</code><var>integral</var><code>&amp;, </code><var>integral</var><code>, memory_order = memory_order_seq_cst);</code></ins>
</pre>

<p>...</p>

<pre>
<code>bool atomic_compare_exchange<ins>_weak</ins>(volatile atomic_</code><var>itype</var><code> *, </code><var>integral</var><code> *, </code><var>integral</var><code>);</code>
<code>bool atomic_compare_exchange<ins>_weak</ins>_explicit(volatile atomic_</code><var>itype</var><code> *, </code><var>integral</var><code> *,
                                      </code><var>integral</var><code>, memory_order, memory_order);</code>
<ins><code>bool atomic_compare_exchange_strong(volatile atomic_</code><var>itype</var><code> *, </code><var>integral</var><code> *, </code><var>integral</var><code>);</code></ins>
<ins><code>bool atomic_compare_exchange_strong_explicit(volatile atomic_</code><var>itype</var><code> *, </code><var>integral</var><code> *,
                                      </code><var>integral</var><code>, memory_order, memory_order);</code></ins>
</pre>

<p>...</p>
</blockquote>

<h3>29.3.2 Address Type [atomics.types.address]</h3>

<p>
In the synopsis, edit as follows.
</p>

<blockquote>
<p>...</p>

<pre>
<code>bool compare_exchange<ins>_weak</ins>(void*&amp;, void*, memory_order, memory_order) volatile;</code>
<code>bool compare_exchange<ins>_weak</ins>(void*&amp;, void*, memory_order = memory_order_seq_cst) volatile;</code>
<ins><code>bool compare_exchange_strong(void*&amp;, void*, memory_order, memory_order) volatile;</code></ins>
<ins><code>bool compare_exchange_strong(void*&amp;, void*, memory_order = memory_order_seq_cst) volatile;</code></ins>
</pre>

<p>...</p>

<pre>
<code>bool atomic_compare_exchange<ins>_weak</ins>(volatile atomic_address*, void**, void*);</code>
<code>bool atomic_compare_exchange<ins>_weak</ins>_explicit(volatile atomic_address*, void**, void*,
                                      memory_order, memory_order);</code>
<ins><code>bool atomic_compare_exchange_strong(volatile atomic_address*, void**, void*);</code></ins>
<ins><code>bool atomic_compare_exchange_strong_explicit(volatile atomic_address*, void**, void*,
                                      memory_order, memory_order);</code></ins>
</pre>

<p>...</p>
</blockquote>


<h3>29.3.3 Generic Types [atomics.types.generic]</h3>

<p>
In the synopsis, edit as follows.
</p>

<blockquote>
<p>...</p>

<pre>
<code>bool compare_exchange<ins>_weak</ins>(T&amp;, T, memory_order, memory_order) volatile;</code>
<code>bool compare_exchange<ins>_weak</ins>(T&amp;, T, memory_order = memory_order_seq_cst) volatile;</code>
<ins><code>bool compare_exchange_strong(T&amp;, T, memory_order, memory_order) volatile;</code></ins>
<ins><code>bool compare_exchange_strong(T&amp;, T, memory_order = memory_order_seq_cst) volatile;</code></ins>
</pre>

<p>...</p>

<pre>
<code>bool compare_exchange<ins>_weak</ins>(T*&amp;, T*, memory_order, memory_order) volatile;</code>
<code>bool compare_exchange<ins>_weak</ins>(T*&amp;, T*, memory_order = memory_order_seq_cst) volatile;</code>
<ins><code>bool compare_exchange_strong(T*&amp;, T*, memory_order, memory_order) volatile;</code></ins>
<ins><code>bool compare_exchange_strong(T*&amp;, T*, memory_order = memory_order_seq_cst) volatile;</code></ins>
</pre>

<p>...</p>
</blockquote>

<h3>29.4 Operations on Atomic Types [atomics.types.operations]</h3>

<p>
Edit the <code>compare_exchange</code> synopses
after paragraph 15 as follows:
</p>

<blockquote>
<pre>
<code>bool atomic_compare_exchange<ins>_weak</ins>(volatile </code><var>A</var><code> *object, </code><var>C</var><code> *expected, </code><var>C</var><code> desired);</code>
<code>bool atomic_compare_exchange<ins>_weak</ins>_explicit(volatile </code><var>A</var><code> *object, </code><var>C</var><code> *expected, </code><var>C</var><code> desired,
    memory_order success, memory_order failure);</code>
<code>bool </code><var>A</var><code> ::compare_exchange<ins>_weak</ins>(</code><var>C</var><code> &amp; expected, </code><var>C</var><code> desired,
    memory_order success, memory_order failure) volatile;</code>
<code>bool </code><var>A</var><code> ::compare_exchange<ins>_weak</ins>(</code><var>C</var><code> &amp; expected, </code><var>C</var><code> desired,
    memory_order order = memory_order_seq_cst) volatile;</code>

<ins><code>bool atomic_compare_exchange_strong(volatile </code><var>A</var><code> *object, </code><var>C</var><code> *expected, </code><var>C</var><code> desired);</code></ins>
<ins><code>bool atomic_compare_exchange_strong_explicit(volatile </code><var>A</var><code> *object, </code><var>C</var><code> *expected, </code><var>C</var><code> desired,
    memory_order success, memory_order failure);</code></ins>
<ins><code>bool </code><var>A</var><code> ::compare_exchange_strong(</code><var>C</var><code> &amp; expected, </code><var>C</var><code> desired,
    memory_order success, memory_order failure) volatile;</code></ins>
<ins><code>bool </code><var>A</var><code> ::compare_exchange_strong(</code><var>C</var><code> &amp; expected, </code><var>C</var><code> desired,
    memory_order order = memory_order_seq_cst) volatile;</code></ins>
</pre>
</blockquote>

<p>
Edit paragraph 20 as follows.
</p>

<blockquote>
<p>
<i>Remark:</i>
The <ins>weak</ins> compare-and-exchange operations may fail spuriously,
that is, return <code>false</code>
while leaving the value pointed to by <code>expected</code> unchanged.
[<i>Note:</i>
This spurious failure
enables implementation of compare-and-exchange on a broader class of machines,
e.g. load-locked store-conditional machines.
&mdash;<i>end note</i>]
[<i>Example:</i>
A consequence of spurious failure
is that nearly all uses of <ins>weak</ins> compare-and-exchange
will be in a loop.
</p>
<pre><code>
   expected = current.load();
   do desired = function(expected);
   while (!current.compare_exchange<ins>_weak</ins>(expected, desired));
</code></pre>
<p>
<ins>When a compare-and-exchange is in a loop,
the weak version will yield better performance on some platforms.
When a weak compare-and-exchange would require a loop,
and a strong one would not,
the strong one is preferable.</ins>
&mdash;<i>end example</i>]
</p>
</blockquote>

</body>
</html>
