Artifact ad2ee82f907cec8e41bcc0d82fa57024803b21e6
#ifndef _KILIB_THREAD_H_
#define _KILIB_THREAD_H_
#include "types.h"
#ifndef __ccdoc__
namespace ki {
#endif
	
//=========================================================================
//@{ @pkg ki.Core //@}
//@{
//	マルチスレッドの管理
//
//	まだ何もしません
//@}
//=========================================================================
class ThreadManager
{
public:
	//@{ 実行可能オブジェクトをに起動をかける //@}
	void Run( class Runnable& r );
	//@{ 複数スレッドが走っているかどうか? //@}
	bool isMT() const;
private:
	ThreadManager();
private:
	int threadNum_;
	static ThreadManager* pUniqueInstance_;
private:
	static DWORD WINAPI ThreadStubFunc(void*);
private:
	friend void APIENTRY Startup();
	friend inline ThreadManager& thd();
	NOCOPY(ThreadManager);
};
//-------------------------------------------------------------------------
//@{ 唯一のスレッド管理オブジェクトを返す //@}
inline ThreadManager& thd()
	{ return *ThreadManager::pUniqueInstance_; }
inline bool ThreadManager::isMT() const
	{ return 0 != threadNum_; }
//=========================================================================
//@{
//	実行可能オブジェクト基底
//@}
//=========================================================================
class Runnable
{
protected:
	Runnable();
	virtual ~Runnable();
	virtual void StartThread() = 0;
	void PleaseExit();
	bool isExitRequested() const;
	bool isRunning() const;
private:
	void FinalizeThread();
	friend class ThreadManager;
	HANDLE hEvent_;
	HANDLE hThread_;
};
//=========================================================================
//@{
//	マルチスレッド・ポリシー1
//
//	このクラスから派生すると、AutoLock クラスを使えるようになります。
//	このクラスに this ポインタを渡すことで排他状態に入り、デストラクタで
//	抜け出せるようになります。NoLockable::AutoLock は実際は何もしません。
//@}
//=========================================================================
class NoLockable
{
protected:
	struct AutoLock
	{
		AutoLock( NoLockable* host ) {}
	};
};
//=========================================================================
//@{
//	マルチスレッド・ポリシー2
//
//	このクラスから派生すると、AutoLock クラスを使えるようになります。
//	このクラスに this ポインタを渡すことで排他状態に入り、デストラクタで
//	抜け出せるようになります。EzLockable::AutoLock は、シングルスレッドで
//	動作するときがほとんどというアプリケーション向けに、高速だけれど
//	不完全な排他制御を行います。2本目のスレッド立ち上げの瞬間が危ない。
//@}
//=========================================================================
class EzLockable
{
protected:
	EzLockable()
		{ ::InitializeCriticalSection( &csection_ ); }
	~EzLockable()
		{ ::DeleteCriticalSection( &csection_ ); }
	struct AutoLock
	{
		AutoLock( EzLockable* host )
		{
			if( NULL != (pCs_=(thd().isMT() ? &host->csection_ : NULL)) )
				::EnterCriticalSection( pCs_ );
		}
		~AutoLock()
		{
			if( pCs_ )
				::LeaveCriticalSection( pCs_ );
		}
	private:
		NOCOPY(AutoLock);
	    CRITICAL_SECTION* pCs_;
	};
private:
	CRITICAL_SECTION csection_;
	#ifdef __DMC__
		friend struct EzLockable::AutoLock;
	#else
		friend struct AutoLock;
	#endif
};
//=========================================================================
//@{
//	マルチスレッド・ポリシー3
//
//	このクラスから派生すると、AutoLock クラスを使えるようになります。
//	このクラスに this ポインタを渡すことで排他状態に入り、デストラクタで
//	抜け出せるようになります。Lockable::AutoLock は、完全な排他制御を
//	行います。万全を期すならかならずこのクラスを用いましょう。
//@}
//=========================================================================
class Lockable
{
protected:
	Lockable()
		{ ::InitializeCriticalSection( &csection_ ); }
	~Lockable()
		{ ::DeleteCriticalSection( &csection_ ); }
	struct AutoLock
	{
		AutoLock( Lockable* host )
		{
			pCs_ = &host->csection_;
			::EnterCriticalSection( pCs_ );
		}
		~AutoLock()
		{
			::LeaveCriticalSection( pCs_ );
		}
	private:
		NOCOPY(AutoLock);
	    CRITICAL_SECTION* pCs_;
	};
	friend struct AutoLock;
private:
	CRITICAL_SECTION csection_;
};
//=========================================================================
}      // namespace ki
#endif // _KILIB_THREAD_H_