126 lines · cpp
1// C includes2#include <stdio.h>3#include <stdint.h>4#include <stdlib.h>5 6// C++ includes7#include <chrono>8#include <mutex>9#include <random>10#include <thread>11 12std::thread g_thread_1;13std::thread g_thread_2;14std::thread g_thread_3;15std::mutex g_mask_mutex;16 17enum MaskAction {18 eGet,19 eAssign,20 eClearBits21};22 23uint32_t mask_access (MaskAction action, uint32_t mask = 0);24 25uint32_t26mask_access (MaskAction action, uint32_t mask)27{28 static uint32_t g_mask = 0;29 30 std::lock_guard<std::mutex> lock(g_mask_mutex);31 switch (action)32 {33 case eGet:34 break;35 36 case eAssign:37 g_mask |= mask;38 break;39 40 case eClearBits:41 g_mask &= ~mask;42 break;43 }44 return g_mask;45}46 47void *48thread_func (void *arg)49{50 uint32_t thread_index = *((uint32_t *)arg);51 uint32_t thread_mask = (1u << (thread_index));52 printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index);53 54 std::default_random_engine generator;55 std::uniform_int_distribution<int> distribution(0, 3000000);56 57 while (mask_access(eGet) & thread_mask)58 {59 // random micro second sleep from zero to 3 seconds60 int usec = distribution(generator);61 printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec);62 63 std::chrono::microseconds duration(usec);64 std::this_thread::sleep_for(duration);65 printf ("%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index); // Set break point at this line.66 }67 printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index);68 return NULL;69}70 71 72int main (int argc, char const *argv[])73{74 uint32_t thread_index_1 = 1;75 uint32_t thread_index_2 = 2;76 uint32_t thread_index_3 = 3;77 uint32_t thread_mask_1 = (1u << thread_index_1);78 uint32_t thread_mask_2 = (1u << thread_index_2);79 uint32_t thread_mask_3 = (1u << thread_index_3);80 81 // Make a mask that will keep all threads alive82 mask_access (eAssign, thread_mask_1 | thread_mask_2 | thread_mask_3); // And that line.83 84 // Create 3 threads85 g_thread_1 = std::thread(thread_func, (void*)&thread_index_1);86 g_thread_2 = std::thread(thread_func, (void*)&thread_index_2);87 g_thread_3 = std::thread(thread_func, (void*)&thread_index_3);88 89 char line[64];90 while (mask_access(eGet) != 0)91 {92 printf ("Enter thread index to kill or ENTER for all:\n");93 fflush (stdout);94 // Kill threads by index, or ENTER for all threads95 96 if (fgets (line, sizeof(line), stdin))97 {98 if (line[0] == '\n' || line[0] == '\r' || line[0] == '\0')99 {100 printf ("Exiting all threads...\n");101 break;102 }103 int32_t index = strtoul (line, NULL, 0);104 switch (index)105 {106 case 1: mask_access (eClearBits, thread_mask_1); break;107 case 2: mask_access (eClearBits, thread_mask_2); break;108 case 3: mask_access (eClearBits, thread_mask_3); break;109 }110 continue;111 }112 113 break;114 }115 116 // Clear all thread bits to they all exit117 mask_access (eClearBits, UINT32_MAX);118 119 // Join all of our threads120 g_thread_1.join();121 g_thread_2.join();122 g_thread_3.join();123 124 return 0;125}126