1. Problem It Solves
A read-check-write sequence on shared data can interleave between threads. Atomic compare-and-swap performs that conditional transition as one atomic operation: update only if the current value equals an expected value.
Focus on the smallest useful form, its observable behavior, and its safety boundary.
2. Prerequisites
Days 7 and 41-42: atomics, threads, shared state, memory ordering names, and synchronization.
3. Core Idea
CAS asks, is state still what I observed? On success it writes the desired value. On failure it leaves the atomic unchanged and overwrites expected with the value actually observed.
Identify the objects and types, today's operation, and the printed result. This connects syntax to behavior.
4. Minimal Syntax
int expected = 0;
bool changed = state.compare_exchange_strong(expected, 1);5. How It Works
The first strong CAS compares atomic state zero with expected zero and requests state one.
It succeeds atomically; a second attempt expecting zero fails because the current state is already one.
The sample prints success, final state one, second failure, and the failure-updated expected value one.
6. Common Mistakes
Ignoring that failure modifies
expectedcan break retry loops or compare against a stale assumption.Do not copy the pattern without checking desired transition, expected-value update, weak versus strong choice, retry loop, memory order, and progress requirements. A program may compile while still having the wrong lifetime, ownership, invalidation, ordering, or performance behavior.
7. When to Use It
Use it when a small shared state transition must be conditional and lock-free design is justified.
Avoid it when the invariant spans multiple independent objects or a mutex would be simpler and easier to verify.
8. Simple Example
An atomic state moves from idle zero to running one. Repeating the same expected transition shows the failure path and the changed expected argument.
The .cpp file uses fixed data. Predict its output, compile it, then change one value and test the prediction.
Complete sample code
Source file
cpp14/43_atomic_operations_compare_and_swap/main.cpp
#include <atomic>
#include <iostream>
int main() {
std::atomic<int> state{0};
int expected = 0;
const bool first = state.compare_exchange_strong(expected, 1);
std::cout << "first success: " << first << "\n";
std::cout << "state: " << state.load() << "\n";
expected = 0;
const bool second = state.compare_exchange_strong(expected, 2);
std::cout << "second success: " << second << "\n";
std::cout << "observed state: " << expected << "\n";
}
9. Key Takeaways
CAS atomically couples comparison and update, with an in/out expected argument.
CAS asks, is state still what I observed? On success it writes the desired value. On failure it leaves the atomic unchanged and overwrites
expectedwith the value actually observed.The compiler or library follows a precise rule; verify desired transition, expected-value update, weak versus strong choice, retry loop, memory order, and progress requirements.
Prefer the smallest form that communicates intent and measure costs when performance matters.
10. Self-Check Questions
Easy — What is the main purpose of Atomic Operations and Compare-and-Swap?
Medium — What values do
stateandexpectedhold after the second CAS fails?Hard — Why is
compare_exchange_weakcommonly placed in a retry loop even when the observed value appears equal?