1// C includes
2#include <stdio.h>
3#include <stdint.h>
4#include <stdlib.h>
5
6// C++ includes
7#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 eClearBits
21};
22
23uint32_t mask_access (MaskAction action, uint32_t mask = 0);
24
25uint32_t
26mask_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 (format: "%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(action: eGet) & thread_mask)
58 {
59 // random micro second sleep from zero to 3 seconds
60 int usec = distribution(generator);
61 printf (format: "%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(rtime: duration);
65 printf (format: "%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index); // Set break point at this line.
66 }
67 printf (format: "%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 alive
82 mask_access (action: eAssign, mask: thread_mask_1 | thread_mask_2 | thread_mask_3); // And that line.
83
84 // Create 3 threads
85 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(action: eGet) != 0)
91 {
92 printf (format: "Enter thread index to kill or ENTER for all:\n");
93 fflush (stdout);
94 // Kill threads by index, or ENTER for all threads
95
96 if (fgets (s: line, n: sizeof(line), stdin))
97 {
98 if (line[0] == '\n' || line[0] == '\r' || line[0] == '\0')
99 {
100 printf (format: "Exiting all threads...\n");
101 break;
102 }
103 int32_t index = strtoul (nptr: line, NULL, base: 0);
104 switch (index)
105 {
106 case 1: mask_access (action: eClearBits, mask: thread_mask_1); break;
107 case 2: mask_access (action: eClearBits, mask: thread_mask_2); break;
108 case 3: mask_access (action: eClearBits, mask: thread_mask_3); break;
109 }
110 continue;
111 }
112
113 break;
114 }
115
116 // Clear all thread bits to they all exit
117 mask_access (action: eClearBits, UINT32_MAX);
118
119 // Join all of our threads
120 g_thread_1.join();
121 g_thread_2.join();
122 g_thread_3.join();
123
124 return 0;
125}
126

source code of lldb/test/API/python_api/lldbutil/iter/main.cpp