| |
| |
| #include "tthread.h" |
| #define _WIN32_WINNT 0x0400 |
| #include <windows.h> |
| |
| using std::list<TThread *>; |
| |
| class TThreadGroupImp; |
| |
| |
| |
| |
| 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(); } |
| |
| |
| |
| |
| |
| |
| class TThreadImp { |
| public: |
| friend class TThreadGroupImp; |
| |
| HANDLE threadId; |
| HANDLE mainThread; |
| int m_refCount; |
| TMutex secureLock; |
| bool isRunning; |
| TThreadGroupImp *owner; |
| TThread *thread; |
| |
| |
| 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() {} |
| |
| |
| 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)) { |
| |
| } |
| if (rc >= WAIT_ABANDONED_0 && rc <= (WAIT_ABANDONED_0 + count - 1)) { |
| |
| } |
| if (rc == WAIT_TIMEOUT) { |
| |
| } |
| |
| if (rc == WAIT_FAILED) { |
| |
| } |
| |
| 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(); } |
| |