[cpp-threads] Failed compare-and-swap

Lawrence Crowl Lawrence at Crowl.org
Wed Aug 1 02:13:30 BST 2007


On 7/31/07, Herb Sutter <hsutter at microsoft.com> wrote:
> The point well illustrated by these examples is that if CAS returns
> the old value (rather than a bool) it can be used to perform an
> atomic load.

The compare-and-swap operation in N2324 does both to reduce the
coding burden in C++ and to handle both forms of hardware operations.

    old_value = atomic_var.load();
    do new_value = function( old_value );
    while ( ! atomic_var.compare_swap( old_value, new_value ) );

> If we allow that, then it should have the same default acquire
> semantics as a load (unless overridden in the weak/relaxed atomics
> of course).

On Tue, Jul 31, 2007 at 09:18:56PM +0200, Alexander Terekhov wrote:
> Model it on load-locked/reserved+compare+store-conditional and let
> application specify both leading and trailing unidirectional
> hoist/sink constraints with an option to specify different trailing
> constraints for success and failure on compare. And let it also
> indicate whether validation (store of loaded value) is needed on
> compare failure as well.

On 7/31/07, Paul E. McKenney <paulmck at linux.vnet.ibm.com> wrote:
> That makes quite a bit of sense, at first glance, anyway.  Then the
> unadorned version (atomic_compare_swap() in N2324) would be sequentially
> consistent in either case, and the atomic_compare_swap_explicit() would
> take an additional memory_order argument for the failure case:
>
> bool atomic_compare_swap_explicit( volatile atomic_bool*, bool*, bool,
>                                    memory_order, memory_order );
>
> Implementations are of course free to provide stronger ordering than
> requested, if desired.

Just to be clear on the evolving specification:

   extern "C"
   bool atomic_compare_swap_explicit(
      volatile atomic_int* the_atomic,
      int* the_old_value,
      int the_new_value,
      memory_order failure_order,
      memory_order success_order );

   bool atomic_int::compare_swap(
      int& the_old_value,
      int the_new_value,
      memory_order failure_order = memory_order_seq_cst,
      memory_order success_order = memory_order_seq_cst );

The failure_order parameter applies when the write does not happen,
and may use the "read" subset of memory_order (relaxed, acquire,
seq_cst).

The success_order parameter applies when the write does happen (and
hence the read also happened and may use any of the memory_order
values.

(I chose the parameter order because one is more likely to weaken
failure_order than the success_order.)

In the event of failure, there is still value dependence on the load.

-- 
Lawrence Crowl



More information about the cpp-threads mailing list