14
14
15
15
using namespace std ::chrono_literals;
16
16
17
+ // We have a single thread created by std::jthread consuming the stop_token:
18
+ // polling for stop_requested.
19
+ void BM_stop_token_single_thread_polling_stop_requested (benchmark::State& state) {
20
+ auto thread_func = [&](std::stop_token st, std::atomic<std::uint64_t >* loop_count) {
21
+ while (!st.stop_requested ()) {
22
+ // doing some work
23
+ loop_count->fetch_add (1 , std::memory_order_relaxed);
24
+ }
25
+ };
26
+
27
+ std::atomic<std::uint64_t > loop_count (0 );
28
+ std::uint64_t total_loop_test_param = state.range (0 );
29
+
30
+ auto thread = support::make_test_jthread (thread_func, &loop_count);
31
+
32
+ for (auto _ : state) {
33
+ auto start_total = loop_count.load (std::memory_order_relaxed);
34
+
35
+ while (loop_count.load (std::memory_order_relaxed) - start_total < total_loop_test_param) {
36
+ std::this_thread::yield ();
37
+ }
38
+ }
39
+ }
40
+
41
+ BENCHMARK (BM_stop_token_single_thread_polling_stop_requested)->RangeMultiplier(2 )->Range(1 << 10 , 1 << 24 );
42
+
43
+ // We have multiple threads polling for stop_requested of the same stop_token.
44
+ void BM_stop_token_multi_thread_polling_stop_requested (benchmark::State& state) {
45
+ std::atomic<bool > start{false };
46
+
47
+ auto thread_func = [&start](std::atomic<std::uint64_t >* loop_count, std::stop_token st) {
48
+ start.wait (false );
49
+ while (!st.stop_requested ()) {
50
+ // doing some work
51
+ loop_count->fetch_add (1 , std::memory_order_relaxed);
52
+ }
53
+ };
54
+
55
+ constexpr size_t thread_count = 20 ;
56
+
57
+ std::uint64_t total_loop_test_param = state.range (0 );
58
+
59
+ std::vector<std::atomic<std::uint64_t >> loop_counts (thread_count);
60
+ std::stop_source ss;
61
+ std::vector<std::jthread> threads;
62
+ threads.reserve (thread_count);
63
+
64
+ for (size_t i = 0 ; i < thread_count; ++i) {
65
+ threads.emplace_back (support::make_test_jthread (thread_func, &loop_counts[i], ss.get_token ()));
66
+ }
67
+
68
+ auto get_total_loop = [&loop_counts] {
69
+ std::uint64_t total = 0 ;
70
+ for (const auto & loop_count : loop_counts) {
71
+ total += loop_count.load (std::memory_order_relaxed);
72
+ }
73
+ return total;
74
+ };
75
+
76
+ start = true ;
77
+ start.notify_all ();
78
+
79
+ for (auto _ : state) {
80
+ auto start_total = get_total_loop ();
81
+
82
+ while (get_total_loop () - start_total < total_loop_test_param) {
83
+ std::this_thread::yield ();
84
+ }
85
+ }
86
+
87
+ ss.request_stop ();
88
+ }
89
+
90
+ BENCHMARK (BM_stop_token_multi_thread_polling_stop_requested)->RangeMultiplier(2 )->Range(1 << 10 , 1 << 24 );
91
+
17
92
// We have a single thread created by std::jthread consuming the stop_token:
18
93
// registering/deregistering callbacks, one at a time.
19
94
void BM_stop_token_single_thread_reg_unreg_callback (benchmark::State& state) {
@@ -59,11 +134,11 @@ void BM_stop_token_async_reg_unreg_callback(benchmark::State& state) {
59
134
std::atomic<bool > start{false };
60
135
61
136
std::uint64_t total_reg_test_param = state.range (0 );
137
+ std::vector<std::atomic<std::uint64_t >> reg_counts (thread_count);
62
138
63
139
std::stop_source ss;
64
140
std::vector<std::jthread> threads;
65
141
threads.reserve (thread_count);
66
- std::vector<std::atomic<std::uint64_t >> reg_counts (thread_count);
67
142
68
143
auto thread_func = [&start](std::atomic<std::uint64_t >* count, std::stop_token st) {
69
144
std::vector<std::optional<std::stop_callback<dummy_stop_callback>>> cbs (concurrent_request_count);
@@ -84,8 +159,8 @@ void BM_stop_token_async_reg_unreg_callback(benchmark::State& state) {
84
159
85
160
auto get_total_reg = [&] {
86
161
std::uint64_t total = 0 ;
87
- for (const auto & reg_counts : reg_counts) {
88
- total += reg_counts .load (std::memory_order_relaxed);
162
+ for (const auto & reg_count : reg_counts) {
163
+ total += reg_count .load (std::memory_order_relaxed);
89
164
}
90
165
return total;
91
166
};
0 commit comments