forked from changkun/modern-cpp-tutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path7.8.memory.order.cpp
More file actions
110 lines (96 loc) · 2.59 KB
/
7.8.memory.order.cpp
File metadata and controls
110 lines (96 loc) · 2.59 KB
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//
// 7.8.memory.order.cpp
// chapter 7 parallelism and concurrency
// modern c++ tutorial
//
// created by changkun at changkun.de
// https://github.com/changkun/modern-cpp-tutorial
//
#include <atomic>
#include <thread>
#include <vector>
#include <iostream>
using namespace std;
using namespace std::chrono;
atomic<int> counter = {0};
const int N = 10000;
void relaxed_order() {
cout << "relaxed_order: " << endl;
vector<thread> vt;
for (int i = 0; i < N; ++i) {
vt.emplace_back([](){
counter.fetch_add(1, memory_order_relaxed);
});
}
auto t1 = high_resolution_clock::now();
for (auto& t : vt) {
t.join();
}
auto t2 = high_resolution_clock::now();
auto duration = ( t2 - t1 ).count();
cout << "relaxed order speed: " << duration / N << "ns" << endl;
}
void release_consume_order() {
cout << "release_consume_order: " << endl;
atomic<int*> ptr;
int v;
thread producer([&]() {
int* p = new int(42);
v = 1024;
ptr.store(p, memory_order_release);
});
thread consumer([&]() {
int* p;
while(!(p = ptr.load(memory_order_consume)));
cout << "p: " << *p << endl;
cout << "v: " << v << endl;
});
producer.join();
consumer.join();
}
void release_acquire_order() {
cout << "release_acquire_order: " << endl;
int v;
atomic<int> flag = {0};
thread release([&]() {
v = 42;
flag.store(1, memory_order_release);
});
thread acqrel([&]() {
int expected = 1; // must before compare_exchange_strong
while(!flag.compare_exchange_strong(expected, 2, memory_order_acq_rel)) {
expected = 1; // must after compare_exchange_strong
}
// flag has changed to 2
});
thread acquire([&]() {
while(flag.load(memory_order_acquire) < 2);
cout << "v: " << v << endl; // must be 42
});
release.join();
acqrel.join();
acquire.join();
}
void sequential_consistent_order() {
cout << "sequential_consistent_order: " << endl;
vector<thread> vt;
for (int i = 0; i < N; ++i) {
vt.emplace_back([](){
counter.fetch_add(1, memory_order_seq_cst);
});
}
auto t1 = high_resolution_clock::now();
for (auto& t : vt) {
t.join();
}
auto t2 = high_resolution_clock::now();
auto duration = ( t2 - t1 ).count();
cout << "sequential consistent speed: " << duration / N << "ns" << endl;
}
int main() {
relaxed_order();
release_consume_order();
release_acquire_order();
sequential_consistent_order();
return 0;
}