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