| //===-- MIUtilThreadBaseStd.cpp ---------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // Third Party Headers: |
| #include <assert.h> |
| |
| // In-house headers: |
| #include "MIUtilThreadBaseStd.h" |
| #include "MICmnThreadMgrStd.h" |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Constructor. |
| // Type: None. |
| // Args: None. |
| // Return: None. |
| // Throws: None. |
| //-- |
| CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase() |
| : m_references(0) |
| , m_bHasBeenKilled(false) |
| { |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Destructor. |
| // Type: None. |
| // Args: None. |
| // Return: None. |
| // Throws: None. |
| //-- |
| CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase() |
| { |
| // 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() |
| { |
| // Create a new thread to occupy this threads Run() function |
| return m_thread.IsActive(); |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Set up *this thread. |
| // Type: Method. |
| // Args: None. |
| // Return: MIstatus::success - Functional succeeded. |
| // MIstatus::failure - Functional failed. |
| // Throws: None. |
| //-- |
| bool |
| CMIUtilThreadActiveObjBase::ThreadExecute() |
| { |
| // Create a new thread to occupy this threads Run() function |
| return m_thread.Start(ThreadEntry, this); |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Acquire a reference to CMIUtilThreadActiveObjBase. |
| // Type: Method. |
| // Args: None. |
| // Return: MIstatus::success - Functional succeeded. |
| // MIstatus::failure - Functional failed. |
| // Throws: None. |
| //-- |
| bool |
| CMIUtilThreadActiveObjBase::Acquire() |
| { |
| // 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() |
| { |
| // 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() |
| { |
| // 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() |
| { |
| 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<CMIUtilThreadActiveObjBase *>(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() |
| { |
| 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() |
| : m_pThread(nullptr) |
| , m_bIsActive(false) |
| { |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: CMIUtilThread destructor. |
| // Type: Method. |
| // Args: None. |
| // Return: None. |
| // Throws: None. |
| //-- |
| CMIUtilThread::~CMIUtilThread() |
| { |
| 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() |
| { |
| 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() |
| { |
| // 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() |
| { |
| // 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() |
| { |
| m_mutex.lock(); |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Release resource. |
| // Type: Method. |
| // Args: None. |
| // Return: None. |
| // Throws: None. |
| //-- |
| void |
| CMIUtilThreadMutex::Unlock() |
| { |
| 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() |
| { |
| return m_mutex.try_lock(); |
| } |