2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
|
|
|
|
#include "tthread.h"
|
|
|
|
#define _WIN32_WINNT 0x0400
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
class TThreadGroupImp;
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// TMutex & TMutexImp
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
class TMutexImp {
|
|
|
|
HANDLE id;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
TMutexImp();
|
|
|
|
~TMutexImp();
|
|
|
|
void lock();
|
|
|
|
void unlock();
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
class TThreadGroupImp {
|
2020-11-13 10:40:58 +13:00
|
|
|
std::list<TThread *> threads;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
TThreadGroupImp();
|
|
|
|
~TThreadGroupImp();
|
|
|
|
void add(TThread *);
|
|
|
|
void remove(TThread *);
|
|
|
|
void wait();
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TMutexImp::TMutexImp() { id = CreateMutex(NULL, FALSE, NULL); }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TMutexImp::~TMutexImp() { BOOL rc = CloseHandle(id); }
|
2016-03-19 06:57:51 +13:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TMutexImp::lock() { DWORD rc = WaitForSingleObject(id, INFINITE); }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TMutexImp::unlock() { BOOL rc = ReleaseMutex(id); }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TMutex::TMutex() : m_imp(new TMutexImp()) {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TMutex::~TMutex() { delete m_imp; }
|
2016-03-19 06:57:51 +13:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TMutex::lock() { m_imp->lock(); }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TMutex::unlock() { m_imp->unlock(); }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// TThread & TThreadImp
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
class TThreadImp {
|
2016-03-19 06:57:51 +13:00
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
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; }
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
TUINT32 TThreadImp::nThreads = 0;
|
2016-06-15 18:43:10 +12:00
|
|
|
TMutex TThreadImp::mutex = TMutex();
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TThreadImp::TThreadImp()
|
2016-06-15 18:43:10 +12:00
|
|
|
: isRunning(false)
|
|
|
|
, threadId(0)
|
|
|
|
, owner(0)
|
|
|
|
, mainThread(0)
|
|
|
|
, thread(0)
|
|
|
|
, secureLock()
|
|
|
|
, m_refCount(0) {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TThreadImp::~TThreadImp() {
|
|
|
|
if (threadId) CloseHandle(threadId);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
static TUINT32 __stdcall fun(void *data) {
|
|
|
|
TThreadImp *t = (TThreadImp *)data;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
t->secureLock.lock();
|
|
|
|
if (t->isRunning) {
|
|
|
|
t->secureLock.unlock();
|
|
|
|
assert(!"thread is already running");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
t->isRunning = true;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
t->secureLock.unlock();
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
t->thread->run();
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
t->decNThreads();
|
|
|
|
if (t->owner) t->owner->remove(t->thread);
|
|
|
|
t->thread->release();
|
|
|
|
return 0;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TThreadImp::start() {
|
|
|
|
TThreadImp::incNThreads();
|
|
|
|
threadId = CreateThread(0, 0, fun, this, 0, 0);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
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);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool TThreadImp::setPreferredProcessor(int processorId) {
|
|
|
|
DWORD rc = SetThreadIdealProcessor(threadId, processorId);
|
|
|
|
return (rc != -1);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TThread::TThread() : m_imp(new TThreadImp()) { m_imp->thread = this; }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TThread::~TThread() { delete m_imp; }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TThread::start() {
|
|
|
|
addRef();
|
|
|
|
m_imp->start();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TThread::addRef() {
|
|
|
|
m_imp->mutex.lock();
|
|
|
|
m_imp->m_refCount++;
|
|
|
|
m_imp->mutex.unlock();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
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;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
int TThread::getRefCount() { return m_imp->m_refCount; }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool TThread::setPreferredProcessor(int processorId) {
|
|
|
|
return m_imp->setPreferredProcessor(processorId);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool TThread::setThreadPriority(TThread::TThreadPriority p) {
|
|
|
|
return m_imp->setThreadPriority(p);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//=======================
|
|
|
|
// TThreadGroupImp
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TThreadGroupImp::TThreadGroupImp() {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TThreadGroupImp::~TThreadGroupImp() {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
2016-06-15 18:43:10 +12:00
|
|
|
void TThreadGroupImp::add(TThread *t) {
|
|
|
|
threads.push_back(t);
|
|
|
|
t->m_imp->setOwner(this);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TThreadGroupImp::remove(TThread *t) {
|
|
|
|
threads.remove(t);
|
|
|
|
t->m_imp->setOwner(0);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TThreadGroupImp::wait() {
|
|
|
|
DWORD count = threads.size();
|
|
|
|
if (count == 0) return;
|
|
|
|
HANDLE *hThreads = new HANDLE[count];
|
|
|
|
int id = 0;
|
2020-11-13 10:40:58 +13:00
|
|
|
for (std::list<TThread *>::iterator it = threads.begin(); it != threads.end();
|
2016-06-15 18:43:10 +12:00
|
|
|
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();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TThreadGroup::TThreadGroup()
|
2016-06-15 18:43:10 +12:00
|
|
|
: m_imp(new TThreadGroupImp())
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
{}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TThreadGroup::~TThreadGroup() { delete m_imp; }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TThreadGroup::add(TThread *t) { m_imp->add(t); }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TThreadGroup::wait() { m_imp->wait(); }
|