1*99451b44SJordan Rupprecht #include <chrono>
2*99451b44SJordan Rupprecht #include <condition_variable>
3*99451b44SJordan Rupprecht #include <cstdio>
4*99451b44SJordan Rupprecht #include <random>
5*99451b44SJordan Rupprecht #include <thread>
6*99451b44SJordan Rupprecht
7*99451b44SJordan Rupprecht std::default_random_engine g_random_engine{std::random_device{}()};
8*99451b44SJordan Rupprecht std::uniform_int_distribution<> g_distribution{0, 3000000};
9*99451b44SJordan Rupprecht std::condition_variable g_condition_variable;
10*99451b44SJordan Rupprecht std::mutex g_mutex;
11*99451b44SJordan Rupprecht int g_count;
12*99451b44SJordan Rupprecht
13*99451b44SJordan Rupprecht char *g_char_ptr = nullptr;
14*99451b44SJordan Rupprecht
15*99451b44SJordan Rupprecht void
barrier_wait()16*99451b44SJordan Rupprecht barrier_wait()
17*99451b44SJordan Rupprecht {
18*99451b44SJordan Rupprecht std::unique_lock<std::mutex> lock{g_mutex};
19*99451b44SJordan Rupprecht if (--g_count > 0)
20*99451b44SJordan Rupprecht g_condition_variable.wait(lock);
21*99451b44SJordan Rupprecht else
22*99451b44SJordan Rupprecht g_condition_variable.notify_all();
23*99451b44SJordan Rupprecht }
24*99451b44SJordan Rupprecht
25*99451b44SJordan Rupprecht void
do_bad_thing_with_location(char * char_ptr,char new_val)26*99451b44SJordan Rupprecht do_bad_thing_with_location(char *char_ptr, char new_val)
27*99451b44SJordan Rupprecht {
28*99451b44SJordan Rupprecht *char_ptr = new_val;
29*99451b44SJordan Rupprecht }
30*99451b44SJordan Rupprecht
31*99451b44SJordan Rupprecht uint32_t
access_pool(bool flag=false)32*99451b44SJordan Rupprecht access_pool (bool flag = false)
33*99451b44SJordan Rupprecht {
34*99451b44SJordan Rupprecht static std::mutex g_access_mutex;
35*99451b44SJordan Rupprecht if (!flag)
36*99451b44SJordan Rupprecht g_access_mutex.lock();
37*99451b44SJordan Rupprecht
38*99451b44SJordan Rupprecht char old_val = *g_char_ptr;
39*99451b44SJordan Rupprecht if (flag)
40*99451b44SJordan Rupprecht do_bad_thing_with_location(g_char_ptr, old_val + 1);
41*99451b44SJordan Rupprecht
42*99451b44SJordan Rupprecht if (!flag)
43*99451b44SJordan Rupprecht g_access_mutex.unlock();
44*99451b44SJordan Rupprecht return *g_char_ptr;
45*99451b44SJordan Rupprecht }
46*99451b44SJordan Rupprecht
47*99451b44SJordan Rupprecht void
thread_func(uint32_t thread_index)48*99451b44SJordan Rupprecht thread_func (uint32_t thread_index)
49*99451b44SJordan Rupprecht {
50*99451b44SJordan Rupprecht printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index);
51*99451b44SJordan Rupprecht
52*99451b44SJordan Rupprecht barrier_wait();
53*99451b44SJordan Rupprecht
54*99451b44SJordan Rupprecht uint32_t count = 0;
55*99451b44SJordan Rupprecht uint32_t val;
56*99451b44SJordan Rupprecht while (count++ < 15)
57*99451b44SJordan Rupprecht {
58*99451b44SJordan Rupprecht // random micro second sleep from zero to 3 seconds
59*99451b44SJordan Rupprecht int usec = g_distribution(g_random_engine);
60*99451b44SJordan Rupprecht printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec);
61*99451b44SJordan Rupprecht std::this_thread::sleep_for(std::chrono::microseconds{usec});
62*99451b44SJordan Rupprecht
63*99451b44SJordan Rupprecht if (count < 7)
64*99451b44SJordan Rupprecht val = access_pool ();
65*99451b44SJordan Rupprecht else
66*99451b44SJordan Rupprecht val = access_pool (true);
67*99451b44SJordan Rupprecht
68*99451b44SJordan Rupprecht printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count);
69*99451b44SJordan Rupprecht }
70*99451b44SJordan Rupprecht printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index);
71*99451b44SJordan Rupprecht }
72*99451b44SJordan Rupprecht
73*99451b44SJordan Rupprecht
main(int argc,char const * argv[])74*99451b44SJordan Rupprecht int main (int argc, char const *argv[])
75*99451b44SJordan Rupprecht {
76*99451b44SJordan Rupprecht g_count = 4;
77*99451b44SJordan Rupprecht std::thread threads[3];
78*99451b44SJordan Rupprecht
79*99451b44SJordan Rupprecht g_char_ptr = new char{};
80*99451b44SJordan Rupprecht
81*99451b44SJordan Rupprecht // Create 3 threads
82*99451b44SJordan Rupprecht for (auto &thread : threads)
83*99451b44SJordan Rupprecht thread = std::thread{thread_func, std::distance(threads, &thread)};
84*99451b44SJordan Rupprecht
85*99451b44SJordan Rupprecht printf ("Before turning all three threads loose...\n"); // Set break point at this line.
86*99451b44SJordan Rupprecht barrier_wait();
87*99451b44SJordan Rupprecht
88*99451b44SJordan Rupprecht // Join all of our threads
89*99451b44SJordan Rupprecht for (auto &thread : threads)
90*99451b44SJordan Rupprecht thread.join();
91*99451b44SJordan Rupprecht
92*99451b44SJordan Rupprecht delete g_char_ptr;
93*99451b44SJordan Rupprecht
94*99451b44SJordan Rupprecht return 0;
95*99451b44SJordan Rupprecht }
96