std::atomic::compare_exchange_weak, std::atomic::compare_exchange_strong - cppreference.com

##### cppreference.com

##### Search

Create account

##### Namespaces

- Page
- Discussion

##### Variants

##### Views

- View
- Edit
- History

##### Actions

# std::atomic::compare_exchange_weak, std::atomic::compare_exchange_strong

From cppreference.com
< cpp‎ | atomic‎ | atomic

Defined in header `<atomic>` |  |
| (1) | (since C++11)
bool compare_exchange_weak( T& expected, T desired, std::memory_order success, std::memory_order failure ); |  |
bool compare_exchange_weak( T& expected, T desired, std::memory_order success, std::memory_order failure ) volatile; |  |
| (2) | (since C++11)
bool compare_exchange_weak( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ); |  |
bool compare_exchange_weak( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ) volatile; |  |
| (3) | (since C++11)
bool compare_exchange_strong( T& expected, T desired, std::memory_order success, std::memory_order failure ); |  |
bool compare_exchange_strong( T& expected, T desired, std::memory_order success, std::memory_order failure ) volatile; |  |
| (4) | (since C++11)
bool compare_exchange_strong( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ); |  |
bool compare_exchange_strong( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ) volatile; |  |

Atomically compares the object representation of `*this` with the object representation of `expected`, as if by std::memcmp, and if those are bitwise-equal, replaces the former with `desired` (performs read-modify-write operation). Otherwise, loads the actual value stored in `*this` into `expected` (performs load operation). Copying is performed as if by std::memcpy.

The memory models for the read-modify-write and load operations are `success` and `failure` respectively. In the (2) and (4) versions `order` is used for both read-modify-write and load operations, except that std::memory_order_acquire and std::memory_order_relaxed are used for the load operation if order == std::memory_order_acq_rel, or order == std::memory_order_release respectively.

### [edit] Parameters

expected | - | reference to the value expected to be found in the atomic object
desired | - | the value to store in the atomic object if it is as expected
success | - | the memory synchronization ordering for the read-modify-write operation if the comparison succeeds. All values are permitted.
failure | - | the memory synchronization ordering for the load operation if the comparison fails. Cannot be std::memory_order_release or std::memory_order_acq_rel and cannot specify stronger ordering than `success` (until C++17)
order | - | the memory synchronization ordering for both operations

### [edit] Return value

true if the underlying atomic value was successfully changed, false otherwise.

### [edit] Exceptions

`noexcept` specification:
noexcept

### [edit] Notes

The weak forms (1-2) of the functions are allowed to fail spuriously, that is, act as if *this != expected even if they are equal. 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 unless the object representation of `T` may include padding bits, trap bits, or offers multiple object representations for the same value (e.g. floating-point NaN). In those cases, weak compare-and-exchange typically works because it quickly converges on some stable object representation.

### [edit] Example

Compare-and-exchange operations are often used as basic building blocks of lockfree data structures

Run this code

    #include <atomic>
    template<typename T>
    struct node
    {
        T data;
        node* next;
        node(const T& data) : data(data), next(nullptr) {}
    };

    template<typename T>
    class stack
    {
        std::atomic<node<T>*> head;
     public:
        void push(const T& data)
        {
          node<T>* new_node = new node<T>(data);

          // put the current value of head into new_node->next
          new_node->next = head.load(std::memory_order_relaxed);

          // now make new_node the new head, but if the head
          // is no longer what's stored in new_node->next
          // (some other thread must have inserted a node just now)
          // then put that new head into new_node->next and try again
          while(!head.compare_exchange_weak(new_node->next, new_node,
                                            std::memory_order_release,
                                            std::memory_order_relaxed))
              ; // the body of the loop is empty

    // Note: the above use is not thread-safe in at least
    // GCC prior to 4.8.3 (bug 60272), clang prior to 2014-05-05 (bug 18899)
    // MSVC prior to 2014-03-17 (bug 819819). The following is a workaround:
    //      node<T>* old_head = head.load(std::memory_order_relaxed);
    //      do {
    //          new_node->next = old_head;
    //       } while(!head.compare_exchange_weak(old_head, new_node,
    //                                           std::memory_order_release,
    //                                           std::memory_order_relaxed));
        }
    };
    int main()
    {
        stack<int> s;
        s.push(1);
        s.push(2);
        s.push(3);
    }

Demonstrates how compare_exchange_strong either changes the value of the atomic variable or the variable used for comparison.

| This section is incomplete Reason: more practical use of the strong CAS would be nice, such as where Concurrency in Action uses it

Run this code

    #include <atomic>
    #include <iostream>

    std::atomic<int>  ai;

    int  tst_val= 4;
    int  new_val= 5;
    bool exchanged= false;

    void valsout()
    {
        std::cout << "ai= " << ai
    	      << "  tst_val= " << tst_val
    	      << "  new_val= " << new_val
    	      << "  exchanged= " << std::boolalpha << exchanged
    	      << "\n";
    }

    int main()
    {
        ai= 3;
        valsout();

        // tst_val != ai   ==>  tst_val is modified
        exchanged= ai.compare_exchange_strong( tst_val, new_val );
        valsout();

        // tst_val == ai   ==>  ai is modified
        exchanged= ai.compare_exchange_strong( tst_val, new_val );
        valsout();
    }

Output:

    ai= 3  tst_val= 4  new_val= 5  exchanged= false
    ai= 3  tst_val= 3  new_val= 5  exchanged= false
    ai= 5  tst_val= 3  new_val= 5  exchanged= true

### [edit] See also

atomic_compare_exchange_weakatomic_compare_exchange_weak_explicitatomic_compare_exchange_strongatomic_compare_exchange_strong_explicit (C++11)(C++11)(C++11)(C++11) | atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not (function template) [edit]

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/atomic/atomic/compare_exchange&oldid=91532"
Categories:

- unconditionally noexcept
- Todo with reason

Hidden categories:

- Pages with unreviewed unconditional noexcept template
- Pages with unreviewed noexcept template