//===-- MIUtilThreadBaseStd.cpp ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // Copyright: None. //-- // Third Party Headers: #include // In-house headers: #include "MIUtilThreadBaseStd.h" #include "MICmnThreadMgrStd.h" //++ ------------------------------------------------------------------------------------ // Details: Constructor. // Type: None. // Args: None. // Return: None. // Throws: None. //-- CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase(void) : m_references(0) , m_bHasBeenKilled(false) { } //++ ------------------------------------------------------------------------------------ // Details: Destructor. // Type: None. // Args: None. // Return: None. // Throws: None. //-- CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase(void) { // Make sure our thread is not alive before we die m_thread.Join(); } //++ ------------------------------------------------------------------------------------ // Details: Check if an object is already running. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIUtilThreadActiveObjBase::ThreadIsActive(void) { // Create a new thread to occupy this threads Run() function return m_thread.IsActive(); } //++ ------------------------------------------------------------------------------------ // Details: Set up *this thread. // Type: Mrthod. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIUtilThreadActiveObjBase::ThreadExecute(void) { // Create a new thread to occupy this threads Run() function return m_thread.Start(ThreadEntry, this); } //++ ------------------------------------------------------------------------------------ // Details: Aquire a reference to CMIUtilThreadActiveObjBase. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIUtilThreadActiveObjBase::Acquire(void) { // Access to this function is serial CMIUtilThreadLock serial(m_mutex); // >0 == *this thread is alive m_references++; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Release a reference to CMIUtilThreadActiveObjBase. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIUtilThreadActiveObjBase::Release(void) { // Access to this function is serial CMIUtilThreadLock serial(m_mutex); // 0 == kill off *this thread m_references--; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Force this thread to stop, regardless of references // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIUtilThreadActiveObjBase::ThreadKill(void) { // Access to this function is serial CMIUtilThreadLock serial(m_mutex); // Set this thread to killed status m_bHasBeenKilled = true; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Proxy to thread join. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIUtilThreadActiveObjBase::ThreadJoin(void) { return m_thread.Join(); } //++ ------------------------------------------------------------------------------------ // Details: This function is the entry point of this object thread. // It is a trampoline to an instances operation manager. // Type: Static method. // Args: vpThisClass - (R) From the system (our CMIUtilThreadActiveObjBase from the ctor). // Return: MIuint - 0 = success. // Throws: None. //-- MIuint CMIUtilThreadActiveObjBase::ThreadEntry(void *vpThisClass) { // The argument is a pointer to a CMIUtilThreadActiveObjBase class // as passed from the initialize function, so we can safely cast it. assert(vpThisClass != nullptr); CMIUtilThreadActiveObjBase *pActive = reinterpret_cast(vpThisClass); // Start the management routine of this object pActive->ThreadManage(); // Thread death return 0; } //++ ------------------------------------------------------------------------------------ // Details: This function forms a small management routine, to handle the thread's running. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- void CMIUtilThreadActiveObjBase::ThreadManage(void) { bool bAlive = true; // Infinite loop while (bAlive) { // Scope the lock while we access m_isDying { // Lock down access to the interface CMIUtilThreadLock serial(m_mutex); // Quit the run loop if we are dying if (m_references == 0) break; } // Execute the run routine if (!ThreadRun(bAlive)) // Thread's run function failed (MIstatus::failure) break; // We will die if we have been signaled to die bAlive &= !m_bHasBeenKilled; } // Execute the finish routine just before we die // to give the object a chance to clean up ThreadFinish(); m_thread.Finish(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- // CMIUtilThread::CMIUtilThread(void) : m_pThread(nullptr) , m_bIsActive(false) { } //++ ------------------------------------------------------------------------------------ // Details: CMIUtilThread destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMIUtilThread::~CMIUtilThread(void) { Join(); } //++ ------------------------------------------------------------------------------------ // Details: Wait for thread to stop. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIUtilThread::Join(void) { if (m_pThread != nullptr) { // Wait for this thread to die m_pThread->join(); // Scope the thread lock while we modify the pointer { CMIUtilThreadLock _lock(m_mutex); delete m_pThread; m_pThread = nullptr; } } return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Is the thread doing work. // Type: Method. // Args: None. // Return: bool - True = Yes active, false = not active. // Throws: None. //-- bool CMIUtilThread::IsActive(void) { // Lock while we access the thread status CMIUtilThreadLock _lock(m_mutex); return m_bIsActive; } //++ ------------------------------------------------------------------------------------ // Details: Finish this thread // Type: Method. // Args: None. // Return: None. // Throws: None. //-- void CMIUtilThread::Finish(void) { // Lock while we access the thread status CMIUtilThreadLock _lock(m_mutex); m_bIsActive = false; } //++ ------------------------------------------------------------------------------------ // Details: Set up *this thread. // Type: Method. // Args: vpFn (R) - Function pointer to thread's main function. // vpArg (R) - Pointer arguments to pass to the thread. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIUtilThread::Start(FnThreadProc vpFn, void *vpArg) { // Lock while we access the thread pointer and status CMIUtilThreadLock _lock(m_mutex); // Create the std thread, which starts immediately and update its status m_pThread = new std::thread(vpFn, vpArg); m_bIsActive = true; // We expect to always be able to create one assert(m_pThread != nullptr); return MIstatus::success; } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ // Details: Take resource. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- void CMIUtilThreadMutex::Lock(void) { m_mutex.lock(); } //++ ------------------------------------------------------------------------------------ // Details: Release resource. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- void CMIUtilThreadMutex::Unlock(void) { m_mutex.unlock(); } //++ ------------------------------------------------------------------------------------ // Details: Take resource if available. Immediately return in either case. // Type: Method. // Args: None. // Return: True - mutex has been locked. // False - mutex could not be locked. // Throws: None. //-- bool CMIUtilThreadMutex::TryLock(void) { return m_mutex.try_lock(); }