Newer
Older
PrismSoftware / ECTrainer2 / BaseProcess.cpp
#include "BaseProcess.h"

// コンストラクタ
BaseProcess::BaseProcess(void* pUD) 
	: _pUserdata(pUD)
	, _messageQueReady(false)
	, _threadHandle(NULL)
	, _threadID(0)
	, _mainThread(false)
	, _fpsMeasureTime(5000)
{
}

// スレッド起動
bool BaseProcess::Launch() {
	_threadHandle = ::CreateThread(NULL, 0, this->ThreadEntry, this, 0, &_threadID);
	return (_threadHandle != NULL);
}

// 初期化
bool BaseProcess::Init() {
	return true;
}

// スレッド本体
bool BaseProcess::MainLoop() {
	if (_threadID == 0) {
		_mainThread = true;
		_threadID = ::GetCurrentThreadId();	// メインスレッドID取得
	}

	// ループ直前処理
	if (!this->InitLoop()) return false;

	// メッセージループ
	MSG msg;
	DWORD beginTime = ::GetTickCount();
	int fpsCounter = 0;
	while (1) {
		if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
			if (!::GetMessage(&msg, NULL, 0, 0)) break;
			if (!this->EventProc(msg)) break;

			if (_mainThread) { // メインスレッドではウインドウプロシージャにディスパッチする
				::TranslateMessage(&msg);
				::DispatchMessage(&msg);
			}
		} else {
			if (this->Routine()) {
				// FPS処理
				++fpsCounter;
				DWORD current = ::GetTickCount();
				if (current - beginTime >= _fpsMeasureTime) {
					double fps = fpsCounter * 1000.0 / (current - beginTime);
					fpsCounter = 0;
					beginTime = current;
					this->FPS(fps);
				}
			}
		}
		_messageQueReady = true;
	}
	return true;
}

// スレッド起動点
DWORD WINAPI BaseProcess::ThreadEntry(LPVOID lpParameter) {
	if (!((BaseProcess*)lpParameter)->MainLoop()) return 1;
	return 0;
}

// スレッド終了待ち 正常終了でハンドル閉じる
bool BaseProcess::WaitForExit(DWORD timeOut) {
	if (!_threadHandle) return false;
	bool rv = (::WaitForSingleObject(_threadHandle, timeOut) == WAIT_OBJECT_0);
	if (rv) ::CloseHandle(_threadHandle);
	return rv;
}

// メッセージを送る(非同期)
bool BaseProcess::PostMsg(int msgid, WPARAM wp, LPARAM lp) {
	if (!_messageQueReady || !_threadID) return false;	// メッセージキューの準備確認
	::PostThreadMessage(_threadID, msgid, wp, lp);
	return true;
}