-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathatomic_cas_reader_writer.cpp
67 lines (65 loc) · 2.04 KB
/
atomic_cas_reader_writer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <thread>
#include <array>
#include <xact/AtomicU64.h>
#include <xact/FixedAtomicU64Group.h>
using xact::AtomicU64;
using AtomGroup = xact::FixedAtomicU64Group<4>;
using namespace std;
int main() {
static const size_t kAtoms = 4;
static const size_t kIncrements = 100000;
std::array<xact::AtomicU64, kAtoms> atoms {0, 1, 2, 3};
std::thread reader([&atoms]() {
AtomGroup group{{&atoms[0], &atoms[1], &atoms[2], &atoms[3]}};
array<uint64_t, kAtoms> values;
for (;;) {
if (group.loadAll(values)) {
for (size_t i = 1; i < kAtoms; i++) {
// When a `loadAll` succeeds, that means we have
// a consistent snapshot. Because the writer is incrementing
// all elements by one, the original relationship between
// the values will always be preserved.
assert(values[i-1] == values[i] - 1);
}
if (values[0] >= kIncrements) {
// once the writer has finished incrementing, exit
break;
}
}
}
});
std::thread writer([&atoms]() {
AtomGroup group{{&atoms[0], &atoms[1], &atoms[2], &atoms[3]}};
array<uint64_t, kAtoms> currentValues;
array<uint64_t, kAtoms> targetValues;
size_t numSuccesses {0};
while (numSuccesses < kIncrements) {
for (;;) {
if (group.loadAll(currentValues)) {
for (size_t i = 0; i < kAtoms; i++) {
targetValues[i] = currentValues[i] + 1;
}
// CAS is overkill for a fetch-add operation -
// normally you would use `fetchAdd` here.
if (group.compareExchange(currentValues, targetValues)) {
numSuccesses++;
break;
}
}
}
}
});
reader.join();
writer.join();
array<uint64_t, kAtoms> finalValues;
AtomGroup group{{&atoms[0], &atoms[1], &atoms[2], &atoms[3]}};
for (;;) {
if (group.loadAll(finalValues)) {
break;
}
}
for (size_t i = 1; i < kAtoms; i++) {
assert(finalValues[i-1] == finalValues[i] - 1);
}
assert(finalValues[0] == kIncrements);
}