1 //===-- main.cpp ------------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <chrono> 10 #include <condition_variable> 11 #include <cstdio> 12 #include <random> 13 #include <thread> 14 15 std::default_random_engine g_random_engine{std::random_device{}()}; 16 std::uniform_int_distribution<> g_distribution{0, 3000000}; 17 std::condition_variable g_condition_variable; 18 std::mutex g_mutex; 19 int g_count; 20 21 char *g_char_ptr = nullptr; 22 23 void 24 barrier_wait() 25 { 26 std::unique_lock<std::mutex> lock{g_mutex}; 27 if (--g_count > 0) 28 g_condition_variable.wait(lock); 29 else 30 g_condition_variable.notify_all(); 31 } 32 33 void 34 do_bad_thing_with_location(char *char_ptr, char new_val) 35 { 36 *char_ptr = new_val; 37 } 38 39 uint32_t 40 access_pool (bool flag = false) 41 { 42 static std::mutex g_access_mutex; 43 if (!flag) 44 g_access_mutex.lock(); 45 46 char old_val = *g_char_ptr; 47 if (flag) 48 do_bad_thing_with_location(g_char_ptr, old_val + 1); 49 50 if (!flag) 51 g_access_mutex.unlock(); 52 return *g_char_ptr; 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 // random micro second sleep from zero to 3 seconds 67 int usec = g_distribution(g_random_engine); 68 printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); 69 std::this_thread::sleep_for(std::chrono::microseconds{usec}); 70 71 if (count < 7) 72 val = access_pool (); 73 else 74 val = access_pool (true); 75 76 printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count); 77 } 78 printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); 79 } 80 81 82 int main (int argc, char const *argv[]) 83 { 84 g_count = 4; 85 std::thread threads[3]; 86 87 g_char_ptr = new char{}; 88 89 // Create 3 threads 90 for (auto &thread : threads) 91 thread = std::thread{thread_func, std::distance(threads, &thread)}; 92 93 printf ("Before turning all three threads loose...\n"); // Set break point at this line. 94 barrier_wait(); 95 96 // Join all of our threads 97 for (auto &thread : threads) 98 thread.join(); 99 100 delete g_char_ptr; 101 102 return 0; 103 } 104