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 //===----------------------------------------------------------------------===//
10 // Third Party Headers:
14 #include "MICmnThreadMgrStd.h"
15 #include "MIUtilThreadBaseStd.h"
18 //------------------------------------------------------------------------------------
19 // Details: Constructor.
25 CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase()
26 : m_references(0), m_bHasBeenKilled(false) {}
29 //------------------------------------------------------------------------------------
30 // Details: Destructor.
36 CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase() {
37 // Make sure our thread is not alive before we die
42 //------------------------------------------------------------------------------------
43 // Details: Check if an object is already running.
46 // Return: MIstatus::success - Functional succeeded.
47 // MIstatus::failure - Functional failed.
50 bool CMIUtilThreadActiveObjBase::ThreadIsActive() {
51 // Create a new thread to occupy this threads Run() function
52 return m_thread.IsActive();
56 //------------------------------------------------------------------------------------
57 // Details: Set up *this thread.
60 // Return: MIstatus::success - Functional succeeded.
61 // MIstatus::failure - Functional failed.
64 bool CMIUtilThreadActiveObjBase::ThreadExecute() {
65 // Create a new thread to occupy this threads Run() function
66 return m_thread.Start(ThreadEntry, this);
70 //------------------------------------------------------------------------------------
71 // Details: Acquire a reference to CMIUtilThreadActiveObjBase.
74 // Return: MIstatus::success - Functional succeeded.
75 // MIstatus::failure - Functional failed.
78 bool CMIUtilThreadActiveObjBase::Acquire() {
79 // Access to this function is serial
80 CMIUtilThreadLock serial(m_mutex);
82 // >0 == *this thread is alive
85 return MIstatus::success;
89 //------------------------------------------------------------------------------------
90 // Details: Release a reference to CMIUtilThreadActiveObjBase.
93 // Return: MIstatus::success - Functional succeeded.
94 // MIstatus::failure - Functional failed.
97 bool CMIUtilThreadActiveObjBase::Release() {
98 // Access to this function is serial
99 CMIUtilThreadLock serial(m_mutex);
101 // 0 == kill off *this thread
104 return MIstatus::success;
108 //------------------------------------------------------------------------------------
109 // Details: Force this thread to stop, regardless of references
112 // Return: MIstatus::success - Functional succeeded.
113 // MIstatus::failure - Functional failed.
116 bool CMIUtilThreadActiveObjBase::ThreadKill() {
117 // Access to this function is serial
118 CMIUtilThreadLock serial(m_mutex);
120 // Set this thread to killed status
121 m_bHasBeenKilled = true;
123 return MIstatus::success;
127 //------------------------------------------------------------------------------------
128 // Details: Proxy to thread join.
131 // Return: MIstatus::success - Functional succeeded.
132 // MIstatus::failure - Functional failed.
135 bool CMIUtilThreadActiveObjBase::ThreadJoin() { return m_thread.Join(); }
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
144 // Return: MIuint - 0 = success.
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);
154 // Start the management routine of this object
155 pActive->ThreadManage();
162 //------------------------------------------------------------------------------------
163 // Details: This function forms a small management routine, to handle the
170 void CMIUtilThreadActiveObjBase::ThreadManage() {
175 // Scope the lock while we access m_isDying
177 // Lock down access to the interface
178 CMIUtilThreadLock serial(m_mutex);
180 // Quit the run loop if we are dying
181 if (m_references == 0)
184 // Execute the run routine
185 if (!ThreadRun(bAlive))
186 // Thread's run function failed (MIstatus::failure)
189 // We will die if we have been signaled to die
190 bAlive &= !m_bHasBeenKilled;
193 // Execute the finish routine just before we die
194 // to give the object a chance to clean up
200 //---------------------------------------------------------------------------------------
201 //---------------------------------------------------------------------------------------
202 //---------------------------------------------------------------------------------------
205 CMIUtilThread::CMIUtilThread() : m_pThread(nullptr), m_bIsActive(false) {}
208 //------------------------------------------------------------------------------------
209 // Details: CMIUtilThread destructor.
215 CMIUtilThread::~CMIUtilThread() { Join(); }
218 //------------------------------------------------------------------------------------
219 // Details: Wait for thread to stop.
222 // Return: MIstatus::success - Functional succeeded.
223 // MIstatus::failure - Functional failed.
226 bool CMIUtilThread::Join() {
227 if (m_pThread != nullptr) {
228 // Wait for this thread to die
231 // Scope the thread lock while we modify the pointer
233 CMIUtilThreadLock _lock(m_mutex);
239 return MIstatus::success;
243 //------------------------------------------------------------------------------------
244 // Details: Is the thread doing work.
247 // Return: bool - True = Yes active, false = not active.
250 bool CMIUtilThread::IsActive() {
251 // Lock while we access the thread status
252 CMIUtilThreadLock _lock(m_mutex);
257 //------------------------------------------------------------------------------------
258 // Details: Finish this thread
264 void CMIUtilThread::Finish() {
265 // Lock while we access the thread status
266 CMIUtilThreadLock _lock(m_mutex);
271 //------------------------------------------------------------------------------------
272 // Details: Set up *this thread.
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.
280 bool CMIUtilThread::Start(FnThreadProc vpFn, void *vpArg) {
281 // Lock while we access the thread pointer and status
282 CMIUtilThreadLock _lock(m_mutex);
284 // Create the std thread, which starts immediately and update its status
285 m_pThread = new std::thread(vpFn, vpArg);
288 // We expect to always be able to create one
289 assert(m_pThread != nullptr);
291 return MIstatus::success;
294 //---------------------------------------------------------------------------------------
295 //---------------------------------------------------------------------------------------
296 //---------------------------------------------------------------------------------------
299 //------------------------------------------------------------------------------------
300 // Details: Take resource.
306 void CMIUtilThreadMutex::Lock() { m_mutex.lock(); }
309 //------------------------------------------------------------------------------------
310 // Details: Release resource.
316 void CMIUtilThreadMutex::Unlock() { m_mutex.unlock(); }
319 //------------------------------------------------------------------------------------
320 // Details: Take resource if available. Immediately return in either case.
323 // Return: True - mutex has been locked.
324 // False - mutex could not be locked.
327 bool CMIUtilThreadMutex::TryLock() { return m_mutex.try_lock(); }