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