///////////////// 頭文件 Thread.h//////////////////////////////
/**************
Multi-threading-related Classes
2011-11-03 Add By AYA
Support Windows platform only
**************/
#ifndef THREAD_H_2011_11_03
#define THREAD_H_2011_11_03
#include <list>
#include <string>
#ifdef WIN32
#include <windows.h>
#endif
class ThreadException {
public:
ThreadException (const char* msg)
: mMsg (msg) {
}
const char* what () const {
return mMsg.c_str ();
}
private:
std::string mMsg;
};
///////////////// Lock & LockGuide //////////////////////////////
class Lock {
public:
Lock ();
~Lock ();
public:
void Enter ();
void Leave ();
private:
CRITICAL_SECTION mSection;
};
class LockGuide {
public:
LockGuide (Lock& _Lock)
:mLock (_Lock) {
mLock.Enter();
}
~LockGuide () {
mLock.Leave ();
}
private:
Lock& mLock;
};
/////////////// Signal ///////////////////////////////
class Signal {
public:
Signal ();
~Signal ();
public:
bool Wait (unsigned int Timeout = INFINITE);
void WakeUp ();
private:
HANDLE mHandle;
};
////////////// Job /////////////////////////////////
class Job {
public:
virtual void Do () = 0;
};
///////////////// Thread ///////////////////////////
class Thread {
friend class ThreadPool;
public:
Thread (ThreadPool& Pool);
virtual ~Thread ();
public:
void Attach (Job* _Job);
private:
/// Only called by ThreadPool
void Die ();
private:
static DWORD WINAPI Routine (LPVOID Parameter);
private:
DWORD mThreadID;
HANDLE mHandle;
Lock mLock;
Signal mSignal;
Signal mDieSignal;
Job* mCurrJob;
ThreadPool& mPool;
bool mIsDie;
};
///////////////// ThreadPool /////////////////////////
class ThreadPool {
friend class Thread;
public:
ThreadPool ();
~ThreadPool ();
public:
bool Alloc (unsigned int ThreadNum);
bool IsBusy ();
void Release (); /// WARNING: ALL THREADS MUST BE IDLE BEFORE RELEASE THE POOL!
Thread* Get ();
private:
/// Only called by Thread
void Put (Thread* _Thread);
private:
Lock mKeeper;
std::list<Thread*> mIdleThreads;
std::list<Thread*> mBusyThreads;
};
#endif
/////////////////////實現 Thread.cpp///////////////////////////////////////
#include "Thread.h"
Lock::Lock()
{
InitializeCriticalSection (&mSection);
}
Lock::~Lock()
{
DeleteCriticalSection (&mSection);
}
void
Lock::Enter()
{
EnterCriticalSection (&mSection);
}
void
Lock::Leave()
{
LeaveCriticalSection (&mSection);
}
#undef _CLASS_
#define _CLASS_ "Signal"
Signal::Signal()
{
mHandle = CreateSemaphore (NULL, 0, 1, NULL);
if (!mHandle) {
throw ThreadException ("CreateSemaphore Failed");
}
}
Signal::~Signal()
{
CloseHandle (mHandle);
}
bool
Signal::Wait (eolas_uint Timeout)
{
if (WAIT_OBJECT_0 != WaitForSingleObject(mHandle, Timeout)) {
return false;
}
return true;
}
void
Signal::WakeUp ()
{
if (!ReleaseSemaphore(mHandle, 1, NULL)) {
throw ThreadException ("ReleaseSemaphore Failed");
}
}
#undef _CLASS_
#define _CLASS_ "Thread"
Thread::Thread(ThreadPool& Pool)
:mPool (Pool),
mThreadID (0),
mCurrJob (NULL),
mIsDie (false)
{
mHandle = CreateThread (
NULL,
0,
Routine,
this,
0,
&mThreadID
);
if (NULL == mHandle) {
throw ThreadException ("CreateThread Failed");
}
}
Thread::~Thread()
{
}
void
Thread::Attach (Job* _Job)
{
LockGuide Guide (mLock);
mCurrJob = _Job;
mSignal.WakeUp();
}
void
Thread::Die()
{
mLock.Enter();
mIsDie = true;
mSignal.WakeUp();
mLock.Leave();
mDieSignal.Wait();
}
DWORD
Thread::Routine (LPVOID Parameter)
{
Thread* _Thread = static_cast <Thread*> (Parameter);
while (true) {
_Thread->mSignal.Wait();
/// 檢查線程是否需要退出
_Thread->mLock.Enter();
if (_Thread->mIsDie) {
_Thread->mLock.Leave();
break;
}
_Thread->mLock.Leave();
/// 干活
_Thread->mCurrJob->Do();
/// 干完活,回到IDLE狀態
_Thread->mLock.Enter();
_Thread->mCurrJob = NULL;
_Thread->mPool.Put (_Thread);
_Thread->mLock.Leave();
}
_Thread->mDieSignal.WakeUp();
return 0;
}
#undef _CLASS_
#define _CLASS_ "ThreadPool"
ThreadPool::ThreadPool()
{
}
ThreadPool::~ThreadPool()
{
Release();
}
bool
ThreadPool::Alloc (unsigned int ThreadNum)
{
LockGuide Guide(mKeeper);
try {
for (unsigned int N = 0; N < ThreadNum; ++N) {
mIdleThreads.push_back(new Thread (*this));
}
} catch (const ThreadException& e) {
return false;
}
return true;
}
void
ThreadPool::Release()
{
LockGuide Guide(mKeeper);
/// 編程上的要求:
/// 釋放線程池之前必須先讓所有Thread進入Idle狀態
/// 這樣才不用強制Kill掉線程
assert(mBusyThreads.empty());
while (!mIdleThreads.empty()) {
Thread* _Thread = mIdleThreads.front();
_Thread->Die();
delete _Thread;
mIdleThreads.pop_front();
}
}
Thread*
ThreadPool::Get()
{
LockGuide Guide (mKeeper);
if (!mIdleThreads.empty()) {
Thread* _Thread = mIdleThreads.front();
mIdleThreads.pop_front();
mBusyThreads.push_back(_Thread);
return _Thread;
}
return NULL;
}
void
ThreadPool::Put (Thread* _Thread)
{
LockGuide Guide (mKeeper);
mBusyThreads.remove(_Thread);
mIdleThreads.push_back(_Thread);
}
bool
ThreadPool::IsBusy()
{
LockGuide Guide (mKeeper);
return !mBusyThreads.empty();
}
摘自 最大的敵人是自己