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