1 //===-- MIUtilThreadBaseStd.cpp ---------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 // File: MIUtilThreadBaseStd.cpp
13 // Overview: CMIUtilThread implementation.
14 // CMIUtilThreadActiveObjBase implementation.
15 // CMIUtilThreadMutex implementation.
17 // Environment: Compilers: Visual C++ 12.
18 // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
19 // Libraries: See MIReadmetxt.
24 // Third Party Headers:
28 #include "MIUtilThreadBaseStd.h"
29 #include "MICmnThreadMgrStd.h"
31 //++ ------------------------------------------------------------------------------------
32 // Details: Constructor.
38 CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase(void)
40 , m_bHasBeenKilled(false)
44 //++ ------------------------------------------------------------------------------------
45 // Details: Destructor.
51 CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase(void)
53 // Make sure our thread is not alive before we die
57 //++ ------------------------------------------------------------------------------------
58 // Details: Check if an object is already running.
61 // Return: MIstatus::success - Functional succeeded.
62 // MIstatus::failure - Functional failed.
66 CMIUtilThreadActiveObjBase::ThreadIsActive(void)
68 // Create a new thread to occupy this threads Run() function
69 return m_thread.IsActive();
72 //++ ------------------------------------------------------------------------------------
73 // Details: Set up *this thread.
76 // Return: MIstatus::success - Functional succeeded.
77 // MIstatus::failure - Functional failed.
81 CMIUtilThreadActiveObjBase::ThreadExecute(void)
83 // Create a new thread to occupy this threads Run() function
84 return m_thread.Start(ThreadEntry, this);
87 //++ ------------------------------------------------------------------------------------
88 // Details: Aquire a reference to CMIUtilThreadActiveObjBase.
91 // Return: MIstatus::success - Functional succeeded.
92 // MIstatus::failure - Functional failed.
96 CMIUtilThreadActiveObjBase::Acquire(void)
98 // Access to this function is serial
99 CMIUtilThreadLock serial(m_mutex);
101 // >0 == *this thread is alive
104 return MIstatus::success;
107 //++ ------------------------------------------------------------------------------------
108 // Details: Release a reference to CMIUtilThreadActiveObjBase.
111 // Return: MIstatus::success - Functional succeeded.
112 // MIstatus::failure - Functional failed.
116 CMIUtilThreadActiveObjBase::Release(void)
118 // Access to this function is serial
119 CMIUtilThreadLock serial(m_mutex);
121 // 0 == kill off *this thread
124 return MIstatus::success;
127 //++ ------------------------------------------------------------------------------------
128 // Details: Force this thread to stop, regardless of references
131 // Return: MIstatus::success - Functional succeeded.
132 // MIstatus::failure - Functional failed.
136 CMIUtilThreadActiveObjBase::ThreadKill(void)
138 // Access to this function is serial
139 CMIUtilThreadLock serial(m_mutex);
141 // Set this thread to killed status
142 m_bHasBeenKilled = true;
144 return MIstatus::success;
147 //++ ------------------------------------------------------------------------------------
148 // Details: Proxy to thread join.
151 // Return: MIstatus::success - Functional succeeded.
152 // MIstatus::failure - Functional failed.
156 CMIUtilThreadActiveObjBase::ThreadJoin(void)
158 return m_thread.Join();
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.
170 CMIUtilThreadActiveObjBase::ThreadEntry(void *vpThisClass)
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);
177 // Start the management routine of this object
178 pActive->ThreadManage();
184 //++ ------------------------------------------------------------------------------------
185 // Details: This function forms a small management routine, to handle the thread's running.
192 CMIUtilThreadActiveObjBase::ThreadManage(void)
199 // Scope the lock while we access m_isDying
201 // Lock down access to the interface
202 CMIUtilThreadLock serial(m_mutex);
204 // Quit the run loop if we are dying
205 if (m_references == 0)
208 // Execute the run routine
209 if (!ThreadRun(bAlive))
210 // Thread's run function failed (MIstatus::failure)
213 // We will die if we have been signaled to die
214 bAlive &= !m_bHasBeenKilled;
217 // Execute the finish routine just before we die
218 // to give the object a chance to clean up
222 //---------------------------------------------------------------------------------------
223 //---------------------------------------------------------------------------------------
224 //---------------------------------------------------------------------------------------
227 CMIUtilThread::CMIUtilThread(void)
232 //++ ------------------------------------------------------------------------------------
233 // Details: CMIUtilThread destructor.
239 CMIUtilThread::~CMIUtilThread(void)
244 //++ ------------------------------------------------------------------------------------
245 // Details: Wait for thread to stop.
248 // Return: MIstatus::success - Functional succeeded.
249 // MIstatus::failure - Functional failed.
253 CMIUtilThread::Join(void)
255 if (m_pThread != nullptr)
257 // Wait for this thread to die
260 // Scope the thread lock while we modify the pointer
262 CMIUtilThreadLock _lock(m_mutex);
268 return MIstatus::success;
271 //++ ------------------------------------------------------------------------------------
272 // Details: Is the thread doing work.
275 // Return: bool - True = Yes active, false = not active.
279 CMIUtilThread::IsActive(void)
281 // Lock while we access the thread pointer
282 CMIUtilThreadLock _lock(m_mutex);
283 if (m_pThread == nullptr)
289 //++ ------------------------------------------------------------------------------------
290 // Details: Set up *this thread.
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.
299 CMIUtilThread::Start(FnThreadProc vpFn, void *vpArg)
301 // Create the std thread, which starts immediately
302 m_pThread = new std::thread(vpFn, vpArg);
304 // We expect to always be able to create one
305 assert(m_pThread != nullptr);
307 return MIstatus::success;
310 //---------------------------------------------------------------------------------------
311 //---------------------------------------------------------------------------------------
312 //---------------------------------------------------------------------------------------
314 //++ ------------------------------------------------------------------------------------
315 // Details: Take resource.
322 CMIUtilThreadMutex::Lock(void)
327 //++ ------------------------------------------------------------------------------------
328 // Details: Release resource.
335 CMIUtilThreadMutex::Unlock(void)
340 //++ ------------------------------------------------------------------------------------
341 // Details: Take resource if available. Immediately return in either case.
344 // Return: True - mutex has been locked.
345 // False - mutex could not be locked.
349 CMIUtilThreadMutex::TryLock(void)
351 return m_mutex.try_lock();