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