87. Atomic update — Kill the Compare-and-Swap Loop
Every Rust developer who’s written lock-free code has written the same compare_exchange loop. Rust 1.95 finally gives atomics an update method that does it for you.
The old way
Atomically doubling a counter used to mean writing a retry loop yourself:
| |
It works, but it’s boilerplate — and easy to get wrong (use the wrong ordering, forget to retry, etc.).
The new way: update
| |
One line. No loop. No chance of forgetting to retry on contention.
The method takes two orderings (one for the store on success, one for the load on failure) and a closure that transforms the current value. It handles the compare-and-swap retry loop internally.
It returns the previous value
Just like fetch_add and friends, update returns the value before the update:
| |
This makes it perfect for “fetch-and-modify” patterns where you need the old value.
Works on all atomic types
update isn’t just for AtomicUsize — it’s available on AtomicBool, AtomicIsize, AtomicUsize, and AtomicPtr too:
| |
When to use update vs fetch_add
If your operation is a simple add, sub, or bitwise op, the specialized fetch_* methods are still better — they compile down to a single atomic instruction on most architectures.
Use update when your transformation is more complex: clamping, toggling state machines, applying arbitrary functions. Anywhere you’d previously hand-roll a CAS loop.
Summary
| Method | Use when |
|---|---|
fetch_add, fetch_or, etc. | Simple arithmetic/bitwise ops |
update | Arbitrary transformations (Rust 1.95+) |
| Manual CAS loop | Never again (mostly) |
Available on stable since Rust 1.95.0 for AtomicBool, AtomicIsize, AtomicUsize, and AtomicPtr.