#include "Mix/Thread.h"

using namespace Mix;

Thread::Thread( void ) :
m_hThread( NULL ),
m_ID( 0 ),
m_SuspendCount( 0 ),
m_pFunc( NULL ),
m_pArgument( NULL )
{
}

Thread::~Thread( void )
{
}

Boolean Thread::Start( void( *pFunc )( void* ), void* pArgument, Boolean bSuspend )
{
	if( m_hThread != NULL )
	{
		return False;
	}

	//基本的な変数を設定
	m_pFunc = pFunc;
	m_pArgument = pArgument;
	if( bSuspend == True )
	{
		m_SuspendCount = 1;
	}

	//スレッドを作成
	uintptr_t uipHandle = ::_beginthreadex( NULL, 0, Entry, this, ( bSuspend == True )? CREATE_SUSPENDED : 0, &m_ID );
	if( uipHandle == 1L )
	{
		m_pFunc = NULL;
		m_pArgument = NULL;
		return False;
	}

	//スレッドハンドル
	m_hThread = reinterpret_cast<HANDLE>( uipHandle );

	return True;
}

void Thread::Join( void )
{
	if( m_hThread != NULL )
	{
		//サスペンド状態を解除する
		if( m_SuspendCount > 0 )
		{
			while( ::ResumeThread( m_hThread ) > 1 ){}
		}
		//終了を待機
		::WaitForSingleObject( m_hThread, INFINITE );
		::CloseHandle( m_hThread );
		//初期化
		m_hThread = NULL;
		m_ID = 0;
		m_SuspendCount = 0;
		m_pFunc = NULL;
		m_pArgument = NULL;
	}
}

void Thread::Resume( void )
{
	if( ( m_hThread != NULL ) &&
		( m_SuspendCount > 0 ) )
	{
		if( ::ResumeThread( m_hThread ) >= 0 )
		{
			--m_SuspendCount;
		}
	}
}

void Thread::Suspend( void )
{
	if( m_hThread != NULL )
	{
		::SuspendThread( m_hThread );
		++m_SuspendCount;
	}
}

UInt32 Thread::GetID( void ) const
{
	return m_ID;
}

UInt32 Thread::GetSuspendCount( void ) const
{
	return m_SuspendCount;
}

unsigned __stdcall Thread::Entry( void* pArg )
{
	Thread* pThread = reinterpret_cast<Thread*>( pArg );
	pThread->m_pFunc( pThread->m_pArgument );
	return 0;
}
