Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tthread.h"
Toshihiro Shimizu 890ddd
#define _WIN32_WINNT 0x0400
Toshihiro Shimizu 890ddd
#include <windows.h></windows.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using std::list<tthread *="">;</tthread>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TThreadGroupImp;
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//    TMutex & TMutexImp
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TMutexImp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	HANDLE id;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TMutexImp();
Toshihiro Shimizu 890ddd
	~TMutexImp();
Toshihiro Shimizu 890ddd
	void lock();
Toshihiro Shimizu 890ddd
	void unlock();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TThreadGroupImp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	list<tthread *=""> threads;</tthread>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TThreadGroupImp();
Toshihiro Shimizu 890ddd
	~TThreadGroupImp();
Toshihiro Shimizu 890ddd
	void add(TThread *);
Toshihiro Shimizu 890ddd
	void remove(TThread *);
Toshihiro Shimizu 890ddd
	void wait();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TMutexImp::TMutexImp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	id = CreateMutex(NULL, FALSE, NULL);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TMutexImp::~TMutexImp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	BOOL rc = CloseHandle(id);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TMutexImp::lock()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	DWORD rc = WaitForSingleObject(id, INFINITE);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TMutexImp::unlock()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	BOOL rc = ReleaseMutex(id);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TMutex::TMutex()
Toshihiro Shimizu 890ddd
	: m_imp(new TMutexImp())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TMutex::~TMutex()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TMutex::lock()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->lock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TMutex::unlock()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//    TThread & TThreadImp
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TThreadImp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	friend class TThreadGroupImp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	HANDLE threadId;
Toshihiro Shimizu 890ddd
	HANDLE mainThread;
Toshihiro Shimizu 890ddd
	int m_refCount;
Toshihiro Shimizu 890ddd
	TMutex secureLock;
Toshihiro Shimizu 890ddd
	bool isRunning;
Toshihiro Shimizu 890ddd
	TThreadGroupImp *owner;
Toshihiro Shimizu 890ddd
	TThread *thread;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//some static stuff
Toshihiro Shimizu 890ddd
	static TUINT32 nThreads;
Toshihiro Shimizu 890ddd
	static TMutex mutex;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThreadImp();
Toshihiro Shimizu 890ddd
	~TThreadImp();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void start();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool setThreadPriority(TThread::TThreadPriority p);
Toshihiro Shimizu 890ddd
	bool setPreferredProcessor(int processorId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static void incNThreads()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		mutex.lock();
Toshihiro Shimizu 890ddd
		nThreads++;
Toshihiro Shimizu 890ddd
		mutex.unlock();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	static void decNThreads()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		mutex.lock();
Toshihiro Shimizu 890ddd
		nThreads--;
Toshihiro Shimizu 890ddd
		mutex.unlock();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void setOwner(TThreadGroupImp *_owner) { owner = _owner; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TUINT32 TThreadImp::nThreads = 0;
Toshihiro Shimizu 890ddd
TMutex TThreadImp::mutex = TMutex();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThreadImp::TThreadImp()
Toshihiro Shimizu 890ddd
	: isRunning(false), threadId(0), owner(0), mainThread(0), thread(0), secureLock(), m_refCount(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThreadImp::~TThreadImp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (threadId)
Toshihiro Shimizu 890ddd
		CloseHandle(threadId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static TUINT32 __stdcall fun(void *data)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThreadImp *t = (TThreadImp *)data;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	t->secureLock.lock();
Toshihiro Shimizu 890ddd
	if (t->isRunning) {
Toshihiro Shimizu 890ddd
		t->secureLock.unlock();
Toshihiro Shimizu 890ddd
		assert(!"thread is already running");
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	t->isRunning = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	t->secureLock.unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	t->thread->run();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	t->decNThreads();
Toshihiro Shimizu 890ddd
	if (t->owner)
Toshihiro Shimizu 890ddd
		t->owner->remove(t->thread);
Toshihiro Shimizu 890ddd
	t->thread->release();
Toshihiro Shimizu 890ddd
	return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TThreadImp::start()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThreadImp::incNThreads();
Toshihiro Shimizu 890ddd
	threadId = CreateThread(0, 0, fun, this, 0, 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TThreadImp::setThreadPriority(TThread::TThreadPriority p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int priority;
Toshihiro Shimizu 890ddd
	switch (p) {
Toshihiro Shimizu 890ddd
	case TThread::TIME_CRITICAL:
Toshihiro Shimizu 890ddd
		priority = THREAD_PRIORITY_TIME_CRITICAL;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TThread::HIGHEST:
Toshihiro Shimizu 890ddd
		priority = THREAD_PRIORITY_HIGHEST;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TThread::ABOVE_NORMAL:
Toshihiro Shimizu 890ddd
		priority = THREAD_PRIORITY_ABOVE_NORMAL;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TThread::NORMAL:
Toshihiro Shimizu 890ddd
		priority = THREAD_PRIORITY_NORMAL;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TThread::BELOW_NORMAL:
Toshihiro Shimizu 890ddd
		priority = THREAD_PRIORITY_BELOW_NORMAL;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TThread::LOWEST:
Toshihiro Shimizu 890ddd
		priority = THREAD_PRIORITY_LOWEST;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TThread::IDLE:
Toshihiro Shimizu 890ddd
		priority = THREAD_PRIORITY_IDLE;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		priority = THREAD_PRIORITY_NORMAL;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return !!SetThreadPriority(threadId, priority);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TThreadImp::setPreferredProcessor(int processorId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	DWORD rc = SetThreadIdealProcessor(threadId, processorId);
Toshihiro Shimizu 890ddd
	return (rc != -1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThread::TThread()
Toshihiro Shimizu 890ddd
	: m_imp(new TThreadImp())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->thread = this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThread::~TThread()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TThread::start()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	addRef();
Toshihiro Shimizu 890ddd
	m_imp->start();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TThread::addRef()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->mutex.lock();
Toshihiro Shimizu 890ddd
	m_imp->m_refCount++;
Toshihiro Shimizu 890ddd
	m_imp->mutex.unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TThread::release()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bool kill = false;
Toshihiro Shimizu 890ddd
	m_imp->mutex.lock();
Toshihiro Shimizu 890ddd
	m_imp->m_refCount--;
Toshihiro Shimizu 890ddd
	if (m_imp->m_refCount <= 0)
Toshihiro Shimizu 890ddd
		kill = true;
Toshihiro Shimizu 890ddd
	m_imp->mutex.unlock();
Toshihiro Shimizu 890ddd
	if (kill)
Toshihiro Shimizu 890ddd
		delete this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TThread::getRefCount()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_refCount;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TThread::setPreferredProcessor(int processorId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->setPreferredProcessor(processorId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TThread::setThreadPriority(TThread::TThreadPriority p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->setThreadPriority(p);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=======================
Toshihiro Shimizu 890ddd
//    TThreadGroupImp
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThreadGroupImp::TThreadGroupImp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThreadGroupImp::~TThreadGroupImp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
void TThreadGroupImp::add(TThread *t)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	threads.push_back(t);
Toshihiro Shimizu 890ddd
	t->m_imp->setOwner(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TThreadGroupImp::remove(TThread *t)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	threads.remove(t);
Toshihiro Shimizu 890ddd
	t->m_imp->setOwner(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TThreadGroupImp::wait()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	DWORD count = threads.size();
Toshihiro Shimizu 890ddd
	if (count == 0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	HANDLE *hThreads = new HANDLE[count];
Toshihiro Shimizu 890ddd
	int id = 0;
Toshihiro Shimizu 890ddd
	for (list<tthread *="">::iterator it = threads.begin(); it != threads.end(); it++, id++) {</tthread>
Toshihiro Shimizu 890ddd
		TThread *t = *it;
Toshihiro Shimizu 890ddd
		if (t->m_imp->threadId == 0)
Toshihiro Shimizu 890ddd
			t->start();
Toshihiro Shimizu 890ddd
		hThreads[id] = t->m_imp->threadId;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DWORD rc = WaitForMultipleObjects(count, hThreads, FALSE, INFINITE);
Toshihiro Shimizu 890ddd
	if (rc >= WAIT_OBJECT_0 && rc <= (WAIT_OBJECT_0 + count - 1)) {
Toshihiro Shimizu 890ddd
		// cout << "obj #" << rc << endl;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (rc >= WAIT_ABANDONED_0 && rc <= (WAIT_ABANDONED_0 + count - 1)) {
Toshihiro Shimizu 890ddd
		// cout << "obj #" << rc << " abandoned" << endl;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (rc == WAIT_TIMEOUT) {
Toshihiro Shimizu 890ddd
		// cout << "timeout" << endl;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (rc == WAIT_FAILED) {
Toshihiro Shimizu 890ddd
		// cout << "failed" << endl;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	delete[] hThreads;
Toshihiro Shimizu 890ddd
	wait();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThreadGroup::TThreadGroup()
Toshihiro Shimizu 890ddd
	: m_imp(new TThreadGroupImp())
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThreadGroup::~TThreadGroup()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TThreadGroup::add(TThread *t)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->add(t);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TThreadGroup::wait()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->wait();
Toshihiro Shimizu 890ddd
}