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
/*******************************************************************************
* tests/thread_barrier_test.cpp
*
* Part of tlx - http://panthema.net/tlx
*
* Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
*
* All rights reserved. Published under the Boost Software License, Version 1.0
******************************************************************************/
// this makes sleep_for() available in older GCC versions
#define _GLIBCXX_USE_NANOSLEEP
// this makes yield() available in older GCC versions
#define _GLIBCXX_USE_SCHED_YIELD
#include <random>
#include <thread>
#include <tlx/die.hpp>
#include <tlx/simple_vector.hpp>
#include <tlx/thread_barrier_mutex.hpp>
#include <tlx/thread_barrier_spin.hpp>
template <typename ThreadBarrier>
static void TestWaitFor(int count, int slowThread = -1) {
int maxWaitTime = 10000;
ThreadBarrier barrier(count);
tlx::simple_vector<uint8_t> flags(count);
tlx::simple_vector<std::thread> threads(count);
for (int i = 0; i < count; i++) {
flags[i] = false;
}
for (int t = 0; t < count; t++) {
threads[t] = std::thread(
[maxWaitTime, count, slowThread, &barrier, &flags, t] {
for (size_t r = 0; r < 100; ++r) {
std::minstd_rand0 rng(t + r);
rng();
if (slowThread == -1) {
std::this_thread::sleep_for(
std::chrono::microseconds(rng() % maxWaitTime));
}
else if (t == slowThread) {
std::this_thread::sleep_for(
std::chrono::microseconds(rng() % maxWaitTime));
}
// every thread sets a flag
flags[t] = true;
barrier.wait();
for (int i = 0; i < count; i++) {
// check flags
die_unequal(flags[i], true);
}
barrier.wait_yield(
[&]() {
// reset flags
for (int i = 0; i < count; i++) {
flags[i] = false;
}
});
}
});
}
for (int t = 0; t < count; t++) {
threads[t].join();
}
}
int main() {
int count = 8;
// run with 8 threads, one slow one
for (int i = 0; i < count; i++) {
TestWaitFor<tlx::ThreadBarrierMutex>(count, i);
}
// run with 32 threads
TestWaitFor<tlx::ThreadBarrierMutex>(32);
#if !defined(TLX_HAVE_THREAD_SANITIZER)
// run with 8 threads, one slow one
for (int i = 0; i < count; i++) {
TestWaitFor<tlx::ThreadBarrierSpin>(count, i);
}
// run with 32 threads
TestWaitFor<tlx::ThreadBarrierSpin>(32);
#endif // !defined(TLX_HAVE_THREAD_SANITIZER)
return 0;
}
/******************************************************************************/