]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/lldb-mi/MIUtilThreadBaseStd.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / tools / lldb-mi / MIUtilThreadBaseStd.cpp
1 //===-- MIUtilThreadBaseStd.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // Third Party Headers:
11 #include <assert.h>
12
13 // In-house headers:
14 #include "MICmnThreadMgrStd.h"
15 #include "MIUtilThreadBaseStd.h"
16
17 //++
18 //------------------------------------------------------------------------------------
19 // Details: Constructor.
20 // Type:    None.
21 // Args:    None.
22 // Return:  None.
23 // Throws:  None.
24 //--
25 CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase()
26     : m_references(0), m_bHasBeenKilled(false) {}
27
28 //++
29 //------------------------------------------------------------------------------------
30 // Details: Destructor.
31 // Type:    None.
32 // Args:    None.
33 // Return:  None.
34 // Throws:  None.
35 //--
36 CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase() {
37   // Make sure our thread is not alive before we die
38   m_thread.Join();
39 }
40
41 //++
42 //------------------------------------------------------------------------------------
43 // Details: Check if an object is already running.
44 // Type:    Method.
45 // Args:    None.
46 // Return:  MIstatus::success - Functional succeeded.
47 //          MIstatus::failure - Functional failed.
48 // Throws:  None.
49 //--
50 bool CMIUtilThreadActiveObjBase::ThreadIsActive() {
51   // Create a new thread to occupy this threads Run() function
52   return m_thread.IsActive();
53 }
54
55 //++
56 //------------------------------------------------------------------------------------
57 // Details: Set up *this thread.
58 // Type:    Method.
59 // Args:    None.
60 // Return:  MIstatus::success - Functional succeeded.
61 //          MIstatus::failure - Functional failed.
62 // Throws:  None.
63 //--
64 bool CMIUtilThreadActiveObjBase::ThreadExecute() {
65   // Create a new thread to occupy this threads Run() function
66   return m_thread.Start(ThreadEntry, this);
67 }
68
69 //++
70 //------------------------------------------------------------------------------------
71 // Details: Acquire a reference to CMIUtilThreadActiveObjBase.
72 // Type:    Method.
73 // Args:    None.
74 // Return:  MIstatus::success - Functional succeeded.
75 //          MIstatus::failure - Functional failed.
76 // Throws:  None.
77 //--
78 bool CMIUtilThreadActiveObjBase::Acquire() {
79   // Access to this function is serial
80   CMIUtilThreadLock serial(m_mutex);
81
82   // >0 == *this thread is alive
83   m_references++;
84
85   return MIstatus::success;
86 }
87
88 //++
89 //------------------------------------------------------------------------------------
90 // Details: Release a reference to CMIUtilThreadActiveObjBase.
91 // Type:    Method.
92 // Args:    None.
93 // Return:  MIstatus::success - Functional succeeded.
94 //          MIstatus::failure - Functional failed.
95 // Throws:  None.
96 //--
97 bool CMIUtilThreadActiveObjBase::Release() {
98   // Access to this function is serial
99   CMIUtilThreadLock serial(m_mutex);
100
101   // 0 == kill off *this thread
102   m_references--;
103
104   return MIstatus::success;
105 }
106
107 //++
108 //------------------------------------------------------------------------------------
109 // Details: Force this thread to stop, regardless of references
110 // Type:    Method.
111 // Args:    None.
112 // Return:  MIstatus::success - Functional succeeded.
113 //          MIstatus::failure - Functional failed.
114 // Throws:  None.
115 //--
116 bool CMIUtilThreadActiveObjBase::ThreadKill() {
117   // Access to this function is serial
118   CMIUtilThreadLock serial(m_mutex);
119
120   // Set this thread to killed status
121   m_bHasBeenKilled = true;
122
123   return MIstatus::success;
124 }
125
126 //++
127 //------------------------------------------------------------------------------------
128 // Details: Proxy to thread join.
129 // Type:    Method.
130 // Args:    None.
131 // Return:  MIstatus::success - Functional succeeded.
132 //          MIstatus::failure - Functional failed.
133 // Throws:  None.
134 //--
135 bool CMIUtilThreadActiveObjBase::ThreadJoin() { return m_thread.Join(); }
136
137 //++
138 //------------------------------------------------------------------------------------
139 // Details: This function is the entry point of this object thread.
140 //          It is a trampoline to an instances operation manager.
141 // Type:    Static method.
142 // Args:    vpThisClass - (R) From the system (our CMIUtilThreadActiveObjBase
143 // from the ctor).
144 // Return:  MIuint - 0 = success.
145 // Throws:  None.
146 //--
147 MIuint CMIUtilThreadActiveObjBase::ThreadEntry(void *vpThisClass) {
148   // The argument is a pointer to a CMIUtilThreadActiveObjBase class
149   // as passed from the initialize function, so we can safely cast it.
150   assert(vpThisClass != nullptr);
151   CMIUtilThreadActiveObjBase *pActive =
152       reinterpret_cast<CMIUtilThreadActiveObjBase *>(vpThisClass);
153
154   // Start the management routine of this object
155   pActive->ThreadManage();
156
157   // Thread death
158   return 0;
159 }
160
161 //++
162 //------------------------------------------------------------------------------------
163 // Details: This function forms a small management routine, to handle the
164 // thread's running.
165 // Type:    Method.
166 // Args:    None.
167 // Return:  None.
168 // Throws:  None.
169 //--
170 void CMIUtilThreadActiveObjBase::ThreadManage() {
171   bool bAlive = true;
172
173   // Infinite loop
174   while (bAlive) {
175     // Scope the lock while we access m_isDying
176     {
177       // Lock down access to the interface
178       CMIUtilThreadLock serial(m_mutex);
179
180       // Quit the run loop if we are dying
181       if (m_references == 0)
182         break;
183     }
184     // Execute the run routine
185     if (!ThreadRun(bAlive))
186       // Thread's run function failed (MIstatus::failure)
187       break;
188
189     // We will die if we have been signaled to die
190     bAlive &= !m_bHasBeenKilled;
191   }
192
193   // Execute the finish routine just before we die
194   // to give the object a chance to clean up
195   ThreadFinish();
196
197   m_thread.Finish();
198 }
199
200 //---------------------------------------------------------------------------------------
201 //---------------------------------------------------------------------------------------
202 //---------------------------------------------------------------------------------------
203
204 //
205 CMIUtilThread::CMIUtilThread() : m_pThread(nullptr), m_bIsActive(false) {}
206
207 //++
208 //------------------------------------------------------------------------------------
209 // Details: CMIUtilThread destructor.
210 // Type:    Method.
211 // Args:    None.
212 // Return:  None.
213 // Throws:  None.
214 //--
215 CMIUtilThread::~CMIUtilThread() { Join(); }
216
217 //++
218 //------------------------------------------------------------------------------------
219 // Details: Wait for thread to stop.
220 // Type:    Method.
221 // Args:    None.
222 // Return:  MIstatus::success - Functional succeeded.
223 //          MIstatus::failure - Functional failed.
224 // Throws:  None.
225 //--
226 bool CMIUtilThread::Join() {
227   if (m_pThread != nullptr) {
228     // Wait for this thread to die
229     m_pThread->join();
230
231     // Scope the thread lock while we modify the pointer
232     {
233       CMIUtilThreadLock _lock(m_mutex);
234       delete m_pThread;
235       m_pThread = nullptr;
236     }
237   }
238
239   return MIstatus::success;
240 }
241
242 //++
243 //------------------------------------------------------------------------------------
244 // Details: Is the thread doing work.
245 // Type:    Method.
246 // Args:    None.
247 // Return:  bool - True = Yes active, false = not active.
248 // Throws:  None.
249 //--
250 bool CMIUtilThread::IsActive() {
251   // Lock while we access the thread status
252   CMIUtilThreadLock _lock(m_mutex);
253   return m_bIsActive;
254 }
255
256 //++
257 //------------------------------------------------------------------------------------
258 // Details: Finish this thread
259 // Type:    Method.
260 // Args:    None.
261 // Return:  None.
262 // Throws:  None.
263 //--
264 void CMIUtilThread::Finish() {
265   // Lock while we access the thread status
266   CMIUtilThreadLock _lock(m_mutex);
267   m_bIsActive = false;
268 }
269
270 //++
271 //------------------------------------------------------------------------------------
272 // Details: Set up *this thread.
273 // Type:    Method.
274 // Args:    vpFn    (R) - Function pointer to thread's main function.
275 //          vpArg   (R) - Pointer arguments to pass to the thread.
276 // Return:  MIstatus::success - Functional succeeded.
277 //          MIstatus::failure - Functional failed.
278 // Throws:  None.
279 //--
280 bool CMIUtilThread::Start(FnThreadProc vpFn, void *vpArg) {
281   // Lock while we access the thread pointer and status
282   CMIUtilThreadLock _lock(m_mutex);
283
284   // Create the std thread, which starts immediately and update its status
285   m_pThread = new std::thread(vpFn, vpArg);
286   m_bIsActive = true;
287
288   // We expect to always be able to create one
289   assert(m_pThread != nullptr);
290
291   return MIstatus::success;
292 }
293
294 //---------------------------------------------------------------------------------------
295 //---------------------------------------------------------------------------------------
296 //---------------------------------------------------------------------------------------
297
298 //++
299 //------------------------------------------------------------------------------------
300 // Details: Take resource.
301 // Type:    Method.
302 // Args:    None.
303 // Return:  None.
304 // Throws:  None.
305 //--
306 void CMIUtilThreadMutex::Lock() { m_mutex.lock(); }
307
308 //++
309 //------------------------------------------------------------------------------------
310 // Details: Release resource.
311 // Type:    Method.
312 // Args:    None.
313 // Return:  None.
314 // Throws:  None.
315 //--
316 void CMIUtilThreadMutex::Unlock() { m_mutex.unlock(); }
317
318 //++
319 //------------------------------------------------------------------------------------
320 // Details: Take resource if available. Immediately return in either case.
321 // Type:    Method.
322 // Args:    None.
323 // Return:  True    - mutex has been locked.
324 //          False   - mutex could not be locked.
325 // Throws:  None.
326 //--
327 bool CMIUtilThreadMutex::TryLock() { return m_mutex.try_lock(); }