#pragma once

// マクロ
#ifndef _WIN32_WINNT
	#define _WIN32_WINNT 0x0500
#endif

// インクルードヘッダ
#include <windows.h>
#include <winuser.h>				// winuserヘッダ
#include <process.h>				// スレッド利用

#include <iostream>
using namespace std;

///////////////////////////////////////////////////
// [クラス] fkut_ThreadBase(基底クラス)
// [目  的] Win32上におけるスレッド処理を行う
//          スレッドは独立して動作するもうひとつのmain関数として設計する
// [使い方] 1. 当クラスを継承した派生クラスを作成
//          2. 派生クラスでmain()関数をオーバーライド
//          3. 大元のスレッドでインスタンスを生成（初期化）
//          4. start()呼出(スレッド開始）
///////////////////////////////////////////////////
class fkut_ThreadBase {
public:
	// [コンストラクタ・デストラクタ]
	fkut_ThreadBase();					// コンストラクタ
	virtual ~fkut_ThreadBase();			// デストラクタ

	// [ユーザ関数]
	void start();						// 開始関数(KLFace2スレッドを開始する)
	void end();							// 終了関数(KLFace2スレッドを終了する)
	virtual void main();				// 動的メイン関数（スレッド主処理）

	// [プロパティ]
	bool		 isRunning();			// 実行状態確認関数(trueならば実行中)
	unsigned int getThreadID();			// スレッドIDを取得する

	static void lock();					// ロック開始
	static void unlock();				// ロック解除

protected:
	// [変数]
	HANDLE			threadHandle;		// (protected)スレッドハンドル
	unsigned int	threadID;			// (protected)スレッドID	
	bool			isStart;			// (protected)開始フラグ
	bool			isEndWait;			// (protected)終了待ちフラグ

	static int		numThreads;			// スレッド本数カウント用変数

private:
	// [システム関数]
	void EndThread();					// スレッド終了関数
	static void InitializeLock();		// ロックデータの初期化
	static void DeleteLock();			// ロックデータの削除

	//////////////////////////////////////////////
	// [関　数] 動的メイン関数
	// [目　的] 別スレッドで起動するメイン関数。
	//			与えられたthisポインタのクラスメンバを呼び出し、スレッドを開始する
	// [引　数] void* thisPtr		: thisポインタ
	//////////////////////////////////////////////
	static unsigned int __stdcall DynamicMain(void* thisPtr);

};

// lock()〜unlock()を楽するためのちょっとしたテクニック
class fkut_CriticalSection {
public:
	fkut_CriticalSection(void)
	{
		fkut_ThreadBase::lock();
	};
	~fkut_CriticalSection()
	{
		fkut_ThreadBase::unlock();
	};
};
