#include "ThreadBase.h"

// クリティカルセクションをファイルスコープへパージ
static CRITICAL_SECTION cs;
// スレッド本数カウント用変数の実体化
int fkut_ThreadBase::numThreads = 0;

//////////////////////////////////////////////
// [関　数] 動的メイン関数
// [目　的] 別スレッドを作成し、動的メイン関数を開始する
//      　  また動的メイン関数が終了すると処理を戻し、スレッドを終了する
// [引　数] void* thisPtr		: thisポインタ
//////////////////////////////////////////////
unsigned int __stdcall fkut_ThreadBase::DynamicMain(void* thisPtr){
	// 引数のthisポインタを用いてクラスにアクセス
	reinterpret_cast<fkut_ThreadBase*>(thisPtr)->main();			// メイン開始
	// ※動的メイン関数が終了したら戻ってくる //
	reinterpret_cast<fkut_ThreadBase*>(thisPtr)->isEndWait = true;
	_endthreadex(0);
	return 0;
}

// fkut_ThreadBase /////////////////////////////

//////////////////////////////////////////////
// [関　数] コンストラクタ
// [目　的] メンバ変数の初期化
//////////////////////////////////////////////
fkut_ThreadBase::fkut_ThreadBase()
{
	isStart     = false;	// 開始フラグの初期化
	isEndWait	= false;	// スレッド終了フラグの初期化
	threadID    = NULL;		// スレッドIDの初期化

	// スレッドロックの準備
	if(!numThreads) InitializeLock();		
	numThreads++;
}

//////////////////////////////////////////////
// [関　数] (virtual)デストラクタ
// [目　的] 特になし
//////////////////////////////////////////////
fkut_ThreadBase::~fkut_ThreadBase()
{
	end();
	// スレッドロックの終了
	numThreads--;
	if(!numThreads) DeleteLock();	
}

//////////////////////////////////////////////
// [関　数] メインスレッド開始関数
// [目　的] KLFace2のメインスレッドを開始する
//////////////////////////////////////////////
void fkut_ThreadBase::start()
{
	if(isEndWait) end();
	if(!isStart){
		// スレッドの開始（static関数fkut_ThreadBase::DynamicMain()に処理を委譲）
		threadHandle = (HANDLE)_beginthreadex(NULL, 0,
			fkut_ThreadBase::DynamicMain, this, 0, &threadID);

		isStart		= true;		// 開始フラグをtrueに設定
		isEndWait	= false;	// スレッド終了フラグの初期化
	}
}

//////////////////////////////////////////////
// [関　数] スレッド終了関数
// [目　的] スレッド終了の指示をだす
//			この関数呼出し後、独立スレッドのループが終了する
//////////////////////////////////////////////
void fkut_ThreadBase::end()
{
	if(isStart){
		//cerr << "fkut_ThreadBase::End()開始" << endl;
		isEndWait = true;	// アプリ終了フラグをtrueに設定
		EndThread();
	}
}

//////////////////////////////////////////////
// [関　数] (virtual)動的メイン関数
// [目　的] スレッド内のメイン関数
//////////////////////////////////////////////
void fkut_ThreadBase::main()
{
	//cerr << "fkut_ThreadBase::Main()開始" << endl;
	// メッセージループ
	while(true){
		// 終了指示が出たらループから抜ける
		if(isEndWait) { break; }
		Sleep(1);
	}
	//cerr << "fkut_ThreadBase::Main()終了" << endl;
}

//////////////////////////////////////////////
// [関　数] 実行状態確認関数
// [目　的] スレッドの実行状態を確認する
// [戻り値] bool : true=実行中, false=終了
//////////////////////////////////////////////
bool fkut_ThreadBase::isRunning()
{
	if(isEndWait) {
		end();
		return false;
	}
	// isStartフラグを返す
	return isStart;
}

//////////////////////////////////////////////
// [関　数] スレッドIDの取得
// [目　的] スレッドの終了状態を確認する
// [戻り値] DWORD : スレッドのID
//////////////////////////////////////////////
unsigned int fkut_ThreadBase::getThreadID()
{
	return threadID;
}

//////////////////////////////////////////////
// [関　数] ロックの初期化
// [目　的] スレッド同期のためのロックを初期化する
//////////////////////////////////////////////
void fkut_ThreadBase::InitializeLock()
{
	// クリティカルセクションの初期化
	InitializeCriticalSection(&cs);
}

//////////////////////////////////////////////
// [関　数] ロックの初期化
// [目　的] スレッド同期のためのロックを終了する
//////////////////////////////////////////////
void fkut_ThreadBase::DeleteLock()
{
	// クリティカルセクションを削除する
	DeleteCriticalSection(&cs);
}

//////////////////////////////////////////////
// [関　数] ロック開始
// [目　的] スレッドを同期させるためロックを行う
//////////////////////////////////////////////
void fkut_ThreadBase::lock()
{
	// クリティカルセクションを開始する
	EnterCriticalSection(&cs);
}

//////////////////////////////////////////////
// [関　数] ロック解除
// [目　的] スレッド同期ロックを解除する
//////////////////////////////////////////////
void fkut_ThreadBase::unlock()
{
	// クリティカルセクションを解消する
	LeaveCriticalSection(&cs);
}

//////////////////////////////////////////////
// [関　数] スレッド終了関数
// [目　的] スレッドを終了させる
//////////////////////////////////////////////
void fkut_ThreadBase::EndThread()
{
	WaitForSingleObject(threadHandle, INFINITE);	// スレッド実終了待ち
	CloseHandle(threadHandle);						// スレッドの終了
	isStart = false;								// 開始フラグ=falseに
	threadHandle = NULL;							// クローズしたハンドルを消去
}
