forked from OSchip/llvm-project
343 lines
9.2 KiB
C++
343 lines
9.2 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.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
//++
|
||
|
// File: MIUtilThreadBaseStd.cpp
|
||
|
//
|
||
|
// Overview: CMIUtilThread implementation.
|
||
|
// CMIUtilThreadActiveObjBase implementation.
|
||
|
// CMIUtilThreadMutex implementation.
|
||
|
//
|
||
|
// Environment: Compilers: Visual C++ 12.
|
||
|
// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
|
||
|
// Libraries: See MIReadmetxt.
|
||
|
//
|
||
|
// Copyright: None.
|
||
|
//--
|
||
|
|
||
|
// Include compiler configuration
|
||
|
#include "MICmnConfig.h"
|
||
|
|
||
|
// 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( 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< 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( 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();
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------
|
||
|
//---------------------------------------------------------------------------------------
|
||
|
//---------------------------------------------------------------------------------------
|
||
|
|
||
|
//
|
||
|
CMIUtilThread::CMIUtilThread( void )
|
||
|
: m_pThread( nullptr )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//++ ------------------------------------------------------------------------------------
|
||
|
// 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 pointer
|
||
|
CMIUtilThreadLock _lock( m_mutex );
|
||
|
if( m_pThread == nullptr )
|
||
|
return false;
|
||
|
else
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//++ ------------------------------------------------------------------------------------
|
||
|
// 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 )
|
||
|
{
|
||
|
// Create the std thread, which starts immediately
|
||
|
m_pThread = new std::thread( vpFn, vpArg );
|
||
|
|
||
|
// 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();
|
||
|
}
|
||
|
|