不到300行的简单线程池C++实现

来源:互联网 发布:免费医药进销存软件 编辑:程序博客网 时间:2024/06/05 07:55

///////////////// 头文件 Thread.h//////////////////////////////

/**************Multi-threading-related Classes2011-11-03 Add By AYASupport Windows platform only **************/#ifndef THREAD_H_2011_11_03#define THREAD_H_2011_11_03#include <list>#include <string>#ifdef WIN32#include <windows.h>#endifclass 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 ThreadPoolvoid Die ();private:static DWORD WINAPI Routine (LPVOID Parameter);private:DWORDmThreadID;HANDLEmHandle;LockmLock;SignalmSignal;SignalmDieSignal;Job*mCurrJob;ThreadPool&mPool;boolmIsDie;};///////////////// 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 Threadvoid 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);}voidLock::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;}voidSignal::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();}