1414
1515using namespace std ::chrono_literals;
1616
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+
1792// We have a single thread created by std::jthread consuming the stop_token:
1893// registering/deregistering callbacks, one at a time.
1994void 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) {
59134 std::atomic<bool > start{false };
60135
61136 std::uint64_t total_reg_test_param = state.range (0 );
137+ std::vector<std::atomic<std::uint64_t >> reg_counts (thread_count);
62138
63139 std::stop_source ss;
64140 std::vector<std::jthread> threads;
65141 threads.reserve (thread_count);
66- std::vector<std::atomic<std::uint64_t >> reg_counts (thread_count);
67142
68143 auto thread_func = [&start](std::atomic<std::uint64_t >* count, std::stop_token st) {
69144 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) {
84159
85160 auto get_total_reg = [&] {
86161 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);
89164 }
90165 return total;
91166 };
0 commit comments