Blob Blame Raw


#include "tthread.h"
#define _WIN32_WINNT 0x0400
#include <windows.h>

using std::list<TThread *>;

class TThreadGroupImp;
//---------------------------------------------------------------------------
//    TMutex & TMutexImp
//---------------------------------------------------------------------------

class TMutexImp
{
	HANDLE id;

public:
	TMutexImp();
	~TMutexImp();
	void lock();
	void unlock();
};

//---------------------------------------------------------------------------

class TThreadGroupImp
{
	list<TThread *> threads;

public:
	TThreadGroupImp();
	~TThreadGroupImp();
	void add(TThread *);
	void remove(TThread *);
	void wait();
};
//---------------------------------------------------------------------------

TMutexImp::TMutexImp()
{
	id = CreateMutex(NULL, FALSE, NULL);
}

//---------------------------------------------------------------------------

TMutexImp::~TMutexImp()
{
	BOOL rc = CloseHandle(id);
}
//---------------------------------------------------------------------------

void TMutexImp::lock()
{
	DWORD rc = WaitForSingleObject(id, INFINITE);
}

//---------------------------------------------------------------------------

void TMutexImp::unlock()
{
	BOOL rc = ReleaseMutex(id);
}

//---------------------------------------------------------------------------

TMutex::TMutex()
	: m_imp(new TMutexImp())
{
}

//---------------------------------------------------------------------------

TMutex::~TMutex()
{
	delete m_imp;
}
//---------------------------------------------------------------------------

void TMutex::lock()
{
	m_imp->lock();
}

//---------------------------------------------------------------------------

void TMutex::unlock()
{
	m_imp->unlock();
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//    TThread & TThreadImp
//---------------------------------------------------------------------------

class TThreadImp
{
public:
	friend class TThreadGroupImp;

	HANDLE threadId;
	HANDLE mainThread;
	int m_refCount;
	TMutex secureLock;
	bool isRunning;
	TThreadGroupImp *owner;
	TThread *thread;

	//some static stuff
	static TUINT32 nThreads;
	static TMutex mutex;

	TThreadImp();
	~TThreadImp();

	void start();

	bool setThreadPriority(TThread::TThreadPriority p);
	bool setPreferredProcessor(int processorId);

	static void incNThreads()
	{
		mutex.lock();
		nThreads++;
		mutex.unlock();
	}
	static void decNThreads()
	{
		mutex.lock();
		nThreads--;
		mutex.unlock();
	}

	void setOwner(TThreadGroupImp *_owner) { owner = _owner; }
};

TUINT32 TThreadImp::nThreads = 0;
TMutex TThreadImp::mutex = TMutex();

//---------------------------------------------------------------------------

TThreadImp::TThreadImp()
	: isRunning(false), threadId(0), owner(0), mainThread(0), thread(0), secureLock(), m_refCount(0)
{
}

//---------------------------------------------------------------------------

TThreadImp::~TThreadImp()
{
	if (threadId)
		CloseHandle(threadId);
}

//---------------------------------------------------------------------------

static TUINT32 __stdcall fun(void *data)
{
	TThreadImp *t = (TThreadImp *)data;

	t->secureLock.lock();
	if (t->isRunning) {
		t->secureLock.unlock();
		assert(!"thread is already running");
		return 0;
	}
	t->isRunning = true;

	t->secureLock.unlock();

	t->thread->run();

	t->decNThreads();
	if (t->owner)
		t->owner->remove(t->thread);
	t->thread->release();
	return 0;
}

//---------------------------------------------------------------------------

void TThreadImp::start()
{
	TThreadImp::incNThreads();
	threadId = CreateThread(0, 0, fun, this, 0, 0);
}
//---------------------------------------------------------------------------

bool TThreadImp::setThreadPriority(TThread::TThreadPriority p)
{
	int priority;
	switch (p) {
	case TThread::TIME_CRITICAL:
		priority = THREAD_PRIORITY_TIME_CRITICAL;
		break;
	case TThread::HIGHEST:
		priority = THREAD_PRIORITY_HIGHEST;
		break;
	case TThread::ABOVE_NORMAL:
		priority = THREAD_PRIORITY_ABOVE_NORMAL;
		break;
	case TThread::NORMAL:
		priority = THREAD_PRIORITY_NORMAL;
		break;
	case TThread::BELOW_NORMAL:
		priority = THREAD_PRIORITY_BELOW_NORMAL;
		break;
	case TThread::LOWEST:
		priority = THREAD_PRIORITY_LOWEST;
		break;
	case TThread::IDLE:
		priority = THREAD_PRIORITY_IDLE;
		break;
	default:
		priority = THREAD_PRIORITY_NORMAL;
		break;
	}
	return !!SetThreadPriority(threadId, priority);
}

//---------------------------------------------------------------------------

bool TThreadImp::setPreferredProcessor(int processorId)
{
	DWORD rc = SetThreadIdealProcessor(threadId, processorId);
	return (rc != -1);
}

//---------------------------------------------------------------------------

TThread::TThread()
	: m_imp(new TThreadImp())
{
	m_imp->thread = this;
}

//---------------------------------------------------------------------------

TThread::~TThread()
{
	delete m_imp;
}

//---------------------------------------------------------------------------

void TThread::start()
{
	addRef();
	m_imp->start();
}

//---------------------------------------------------------------------------

void TThread::addRef()
{
	m_imp->mutex.lock();
	m_imp->m_refCount++;
	m_imp->mutex.unlock();
}

//---------------------------------------------------------------------------

void TThread::release()
{
	bool kill = false;
	m_imp->mutex.lock();
	m_imp->m_refCount--;
	if (m_imp->m_refCount <= 0)
		kill = true;
	m_imp->mutex.unlock();
	if (kill)
		delete this;
}

//---------------------------------------------------------------------------

int TThread::getRefCount()
{
	return m_imp->m_refCount;
}

//---------------------------------------------------------------------------

bool TThread::setPreferredProcessor(int processorId)
{
	return m_imp->setPreferredProcessor(processorId);
}

//---------------------------------------------------------------------------

bool TThread::setThreadPriority(TThread::TThreadPriority p)
{
	return m_imp->setThreadPriority(p);
}

//=======================
//    TThreadGroupImp

//---------------------------------------------------------------------------

TThreadGroupImp::TThreadGroupImp()
{
}

//---------------------------------------------------------------------------

TThreadGroupImp::~TThreadGroupImp()
{
}

//---------------------------------------------------------------------------
void TThreadGroupImp::add(TThread *t)
{
	threads.push_back(t);
	t->m_imp->setOwner(this);
}
//---------------------------------------------------------------------------

void TThreadGroupImp::remove(TThread *t)
{
	threads.remove(t);
	t->m_imp->setOwner(0);
}
//---------------------------------------------------------------------------

void TThreadGroupImp::wait()
{
	DWORD count = threads.size();
	if (count == 0)
		return;
	HANDLE *hThreads = new HANDLE[count];
	int id = 0;
	for (list<TThread *>::iterator it = threads.begin(); it != threads.end(); it++, id++) {
		TThread *t = *it;
		if (t->m_imp->threadId == 0)
			t->start();
		hThreads[id] = t->m_imp->threadId;
	}

	DWORD rc = WaitForMultipleObjects(count, hThreads, FALSE, INFINITE);
	if (rc >= WAIT_OBJECT_0 && rc <= (WAIT_OBJECT_0 + count - 1)) {
		// cout << "obj #" << rc << endl;
	}
	if (rc >= WAIT_ABANDONED_0 && rc <= (WAIT_ABANDONED_0 + count - 1)) {
		// cout << "obj #" << rc << " abandoned" << endl;
	}
	if (rc == WAIT_TIMEOUT) {
		// cout << "timeout" << endl;
	}

	if (rc == WAIT_FAILED) {
		// cout << "failed" << endl;
	}

	delete[] hThreads;
	wait();
}

//---------------------------------------------------------------------------

TThreadGroup::TThreadGroup()
	: m_imp(new TThreadGroupImp())

{
}

//---------------------------------------------------------------------------

TThreadGroup::~TThreadGroup()
{
	delete m_imp;
}

//---------------------------------------------------------------------------

void TThreadGroup::add(TThread *t)
{
	m_imp->add(t);
}

//---------------------------------------------------------------------------

void TThreadGroup::wait()
{
	m_imp->wait();
}