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 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 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 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 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 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