xref: /llvm-project/lldb/test/API/python_api/lldbutil/iter/main.cpp (revision fdea9a4ec9b0d9585b8fe8a612686d9f44f40ddc)
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