-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
![grafik](https://github.com/jeremy-rifkin/wheatley-mirror/assets/22040976/43486c95-e0fa-4e60-ad8a-82758d90f7da) --------- Co-authored-by: Jeremy Rifkin <51220084+jeremy-rifkin@users.noreply.github.com>
- Loading branch information
1 parent
d20083c
commit 2aa8e83
Showing
1 changed file
with
36 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# What Is an Atomic Compare-And-Swap (CAS)? | ||
|
||
[CAS](https://en.wikipedia.org/wiki/Compare-and-swap) | ||
allows | ||
*[read-modify-write operations](https://en.wikipedia.org/wiki/Read%E2%80%93modify%E2%80%93write)* | ||
for atomics. | ||
It's often the foundation of | ||
*[lock-free algorithms](https://en.wikipedia.org/wiki/Non-blocking_algorithm)*. | ||
In C++, this takes the form of | ||
**[std::atomic::compare_exchange_xxx](https://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange)**: | ||
```cpp | ||
bool atomic<T>::compare_exchange(T& expected, T desired) { | ||
T old = load(); // All of this happens atomically. | ||
// For weak exchanges, this test can fail spuriously: | ||
if (old == expected) { store(desired); return true; } | ||
else { expected = old; return false; } | ||
} | ||
``` | ||
|
||
## Example - Lock-Free Singly Linked List Stack Push | ||
```cpp | ||
struct node { int val; std::atomic<node*> next; }; | ||
std::atomic<node*> top; | ||
|
||
void push(int val) { | ||
node* element = new node{ val, nullptr }; | ||
node* old_top = top; | ||
do { | ||
element->next = old_top; | ||
} while(!top.compare_exchange_weak(old_top, element)); | ||
} | ||
``` | ||
Each iteration, `old_top` is loaded from `top`. | ||
In the time that we set `element->next = old_top` another thread might have updated `top`, | ||
which makes the exchange fail. | ||
We keep retrying until we *safely* exchange `top` with the `element`. |