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