Skip to content

Commit 06306a0

Browse files
committed
Simplify repro.
1 parent bce4e4b commit 06306a0

File tree

2 files changed

+7
-37
lines changed

2 files changed

+7
-37
lines changed

build_repro.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
g++ -Iinclude -std=c++17 repro.cpp lib/source.cpp -O2 -lstdc++ -lpthread -lm -o repro_with_sem_front
2-
g++ -Iinclude -std=c++17 repro.cpp lib/source.cpp -D__NO_SEM_FRONT -O2 -lstdc++ -lpthread -lm -o repro_with_no_sem_front
1+
g++ -Iinclude -std=c++17 repro.cpp lib/source.cpp -g -O2 -lstdc++ -lpthread -lm -o repro_with_sem_front
2+
g++ -Iinclude -std=c++17 repro.cpp lib/source.cpp -g -O2 -lstdc++ -lpthread -lm -D__NO_SEM_FRONT -o repro_with_no_sem_front

repro.cpp

+5-35
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
#include <functional>
99
#include <optional>
1010

11-
#define LOG(...) std::cout << __VA_ARGS__ "\n"
12-
1311
struct thread_group {
1412
private:
1513
std::vector<std::thread> members;
@@ -54,26 +52,6 @@ struct concurrent_bounded_queue {
5452
items_produced.release();
5553
}
5654

57-
// Attempt to dequeue one entry.
58-
std::optional<T> try_dequeue()
59-
{
60-
std::optional<T> tmp;
61-
if (!items_produced.try_acquire())
62-
return tmp;
63-
// This sleep is a stand-in for a log statement in the actual code. The bug
64-
// reproduces without the delay after acquiring and before locking, but it
65-
// reproduces much less frequently.
66-
std::this_thread::sleep_for(std::chrono::nanoseconds(500));
67-
{
68-
std::scoped_lock l(items_mtx);
69-
assert(!items.empty());
70-
tmp = std::move(items.front());
71-
items.pop();
72-
}
73-
remaining_space.release();
74-
return tmp;
75-
}
76-
7755
// Attempt to dequeue one entry with a timeout.
7856
template <typename Rep, typename Period>
7957
std::optional<T> try_dequeue_for(
@@ -113,7 +91,6 @@ int main()
11391

11492
constexpr std::size_t num_threads = 8;
11593

116-
std::latch l(num_threads + 1);
11794
thread_group tg(num_threads,
11895
[&]
11996
{
@@ -124,25 +101,18 @@ int main()
124101
(*f)();
125102
}
126103
}
127-
// Clear out the queue.
128-
while (true) {
129-
auto f = tasks.try_dequeue();
130-
if (f) {
131-
assert(*f);
132-
(*f)();
133-
} else
134-
// We weren't able to dequeue anything; the queue's empty.
135-
break;
136-
}
137-
l.arrive_and_wait();
138104
}
139105
);
140106

141107
for (std::size_t i = 0; i < num_enqueues_per_run; ++i)
142108
tasks.enqueue([&] { ++count; });
143109

144-
stop_requested.store(true, std::memory_order_relaxed);
110+
std::latch l(num_threads + 1);
111+
for (std::size_t i = 0; i < num_threads; ++i)
112+
tasks.enqueue([&] { l.arrive_and_wait(); });
145113
l.arrive_and_wait();
114+
115+
stop_requested.store(true, std::memory_order_relaxed);
146116
}
147117

148118
assert(num_runs * num_enqueues_per_run == count);

0 commit comments

Comments
 (0)