llvm-project/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp

358 lines
9.7 KiB
C++

//===-- 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();
}