一个简单的线程池

来源:互联网 发布:淘宝买家秀裸露店铺 编辑:程序博客网 时间:2024/05/02 15:57

昨天晚上写了一个线程池管理,记录下来吧:


//@author: tigermei//@data: 2012/03/20//thread base#ifndef THREADBASE_H_#define THREADBASE_H_////macro that is used to prevet copy and assign the object#define DISALLOW_COPY_AND_ASSIGN(ClassName)      \ClassName(const ClassName&);                    \void operator=(const ClassName&)class CThreadBase{public:CThreadBase();virtual ~CThreadBase();////start the the threadBOOL Start();////wait the thread the times of dwElapseTime until the thread is destroyed//@dwElapseTime the times that is needed to waitBOOL Wait(DWORD dwElapseTime = INFINITE);////get the handle of the threadHANDLE GetHandle(){ return m_hThreadHandle; }protected:////the function that is needed to be extended//it is pure virtual functin, the work thread will call itvirtual int Run() = 0;private:////the start of the work threadstatic unsigned int __stdcall start_address(void * param);DISALLOW_COPY_AND_ASSIGN(CThreadBase);private:////handle of the new work threadHANDLE m_hThreadHandle;////the id of the new work threadDWORD m_dwThreadId;};#endif



//@author: tigermei//@data: 2012/03/20//thread base#include "stdafx.h"#include "ThreadBase.h"#include <assert.h>#include <process.h>CThreadBase::CThreadBase(): m_hThreadHandle(INVALID_HANDLE_VALUE), m_dwThreadId(0){}CThreadBase::~CThreadBase(){if(m_hThreadHandle != INVALID_HANDLE_VALUE)::CloseHandle(m_hThreadHandle);}BOOL CThreadBase::Start(){if(m_hThreadHandle != INVALID_HANDLE_VALUE){assert(false);return FALSE;}////start a new work threadm_hThreadHandle = (HANDLE)_beginthreadex(0, 0,start_address, (void *)this, 0, (unsigned int *)&m_dwThreadId);return m_hThreadHandle != INVALID_HANDLE_VALUE;}unsigned int __stdcall CThreadBase::start_address( void * param){CThreadBase *pThread = (CThreadBase *)param;if(pThread){return pThread->Run();}return 0;}BOOL CThreadBase::Wait(DWORD dwElapseTime){DWORD dwWaitResult = ::WaitForSingleObject(m_hThreadHandle, dwElapseTime);if(dwWaitResult == WAIT_OBJECT_0)return TRUE;elsereturn FALSE;return FALSE;}



//@author: tigermei//@data: 2012/03/20//Worker thread#ifndef TASK_H#define TASK_H_#include "ThreadBase.h"#include "Lock.h"#include <queue>#include <vector>#define EVENT_NUM 2class Request;class CWorkersMgr;extern const int NumberOfThreads;////the class CWorker is used to pack the work thread//class CWorker : public CThreadBase{public:////@param pWorkerMgr we need some variables frome the //object of CWorkersMgrCWorker(CWorkersMgr *pWorkerMgr);virtual ~CWorker();////when we need stop the current thread ,call the function stopBOOL Stop();protected:////this function will be called in the worker threadvirtual int Run();private:////do the real workvoid WorkerThread();private:CWorkersMgr *m_pWorkerMgr;////m_hHanleEvent[0] quit event, when we need stop the thread, we signal the event//m_hHanleEvent[1] the same as the member of m_hRequestSemaphore in CWorkersMgrHANDLE m_hHanleEvent[EVENT_NUM];};////class CWorkersMgr manage the request queue//and manage the work threads//class CWorkersMgr{public:CWorkersMgr();~CWorkersMgr();////Get the request from the queue, we need lock here//@return the request in the queue, when we return the request//we also need remove it from the queue//Request *GetNextRequest();////if there is some requestes, we push it into the queue//@param pRequest the pointor of the request//void PushRequest(Request *pRequest);////tell if the request queue is empty//BOOL IsRequestQueueEmpty();////create work thread//void CreateWorkers();//wait until the work has been completed//void WaitUntilWorkComplete();////destroy the work thread and some member variables//void DestroyWorkers();private:void Uninit();public://m_hRequestSemaphore is used to resume the work thread to process the requestHANDLE m_hRequestSemaphore;//when the request has be completed, m_hRequestComplete will be signaledHANDLE m_hRequestComplete;//Synchronous different threads to process the task queueCLock m_csQueueAccess;private://Request queuestd::queue<Request *> m_queueRequest;//work threadstd::vector<CWorker *> m_arrayWorkers;};#endif



//@author: tigermei//@data: 2012/03/20//Worker thread#include "stdafx.h"#include <assert.h>#include "Work.h"#include "ThreadBase.h"extern const int NumberOfThreads;extern Request * GetRequest() throw();extern void ProcessRequest(Request * request) throw();#define TRY_WAIT_TIMES 3CWorker::CWorker(CWorkersMgr *pWorkerMgr){m_pWorkerMgr = pWorkerMgr;m_hHanleEvent[0] = CreateEvent(NULL, FALSE, FALSE, NULL);if(m_pWorkerMgr){m_hHanleEvent[1] = m_pWorkerMgr->m_hRequestSemaphore;}}CWorker::~CWorker(){if(m_hHanleEvent[0])::CloseHandle(m_hHanleEvent[0]);if(m_hHanleEvent[1])m_hHanleEvent[1] = NULL;}int CWorker::Run(){WorkerThread();return 0;}void CWorker::WorkerThread(){//loop herefor(;;){////we wait two events here//one is the request event, the other is quit eventDWORD dwRet = WaitForMultipleObjects(EVENT_NUM, m_hHanleEvent, FALSE, INFINITE);if(dwRet == WAIT_OBJECT_0){////the quit event has been signaledbreak;}else if(dwRet == WAIT_OBJECT_0 +1){////there are request that needed be processedRequest *request = m_pWorkerMgr->GetNextRequest();ProcessRequest(request);delete request;////check if there are more request//if there is no requestes in the queue,we need signal the complete eventif(m_pWorkerMgr->IsRequestQueueEmpty()){::SetEvent(m_pWorkerMgr->m_hRequestComplete);}}else{assert(false);break;}}}BOOL CWorker::Stop(){////signal the quit event so that the worker thread can jump out frome the loop::SetEvent(m_hHanleEvent[0]);return Wait(20);}/////////////////////////////////////////CWorkersMgr//////////////////////////////CWorkersMgr::CWorkersMgr(){m_hRequestSemaphore = INVALID_HANDLE_VALUE;m_hRequestComplete = INVALID_HANDLE_VALUE;}CWorkersMgr::~CWorkersMgr(){m_hRequestSemaphore = INVALID_HANDLE_VALUE;m_hRequestComplete = INVALID_HANDLE_VALUE;}void CWorkersMgr::CreateWorkers(){m_hRequestSemaphore = ::CreateSemaphore(NULL, 0, 0xff, NULL);m_hRequestComplete = ::CreateEvent(NULL, FALSE, TRUE, NULL);CWorker *pWorkersArray = new CWorker(this);for(int i = 0; i < NumberOfThreads ; ++i){CWorker *pWorkers = new CWorker(this);m_arrayWorkers.push_back(pWorkers);////we need start the thread, if there are no request//the work thread will wait the request eventpWorkers->Start();}}void CWorkersMgr::WaitUntilWorkComplete(){WaitForSingleObject(m_hRequestComplete, INFINITE);}void CWorkersMgr::DestroyWorkers(){int nWorkers = m_arrayWorkers.size();for(int i = 0 ; i < nWorkers ; ++i){////stop the worker threadBOOL bStop = m_arrayWorkers[i]->Stop();if(!bStop){////if not stop, we TRY_WAIT_TIMES times to wait//500ms every timefor(int j = 0;  j < TRY_WAIT_TIMES; ++j){bStop = m_arrayWorkers[i]->Wait(500);if(bStop) break;}////After TRY_WAIT_TIMES times try//the thread still doesn't stop ,we terminate itif(!bStop){::TerminateThread(m_arrayWorkers[i]->GetHandle(), 0);}}}////uninit other variablesUninit();}void CWorkersMgr::Uninit(){::CloseHandle(m_hRequestSemaphore);::CloseHandle(m_hRequestComplete);int nWorkers = m_arrayWorkers.size();for(int i = 0 ; i < nWorkers ; ++i){CWorker *pWorker = m_arrayWorkers[i];delete pWorker;}while(!m_queueRequest.empty()){Request *request = m_queueRequest.front();m_queueRequest.pop();delete request;}}Request *CWorkersMgr::GetNextRequest(){CAutoLock autoLock(&m_csQueueAccess);Request *request = m_queueRequest.front();m_queueRequest.pop();return request;}void CWorkersMgr::PushRequest(Request *pRequest){if(pRequest){////the request queue is shared by main thread and worker threadsCAutoLock autoLock(&m_csQueueAccess);m_queueRequest.push(pRequest);////when there are requestes, we must set the complete event no signal::ResetEvent(m_hRequestComplete);////add the request semaphoreReleaseSemaphore(m_hRequestSemaphore, 1, NULL);}}BOOL CWorkersMgr::IsRequestQueueEmpty(){CAutoLock autoLock(&m_csQueueAccess);return m_queueRequest.empty();}



//@author: tigermei//@data: 2012/03/20//Lock#ifndef LOCK_H_#define LOCK_H_class CAutoLock;class CLock{public:CLock();~CLock();void Enter();void Leave();private:CRITICAL_SECTION m_CritSect;};//// use example://// CLock lock;// {// CAutoLock autoLock(&lock);// }//class CAutoLock{public:CAutoLock(CLock *pLock);~CAutoLock();private:CLock *m_pLock;};#endif



//@author: tigermei//@data: 2012/03/20//Lock#include "stdafx.h"#include "Lock.h"CLock::CLock(){::InitializeCriticalSection(&m_CritSect);}CLock::~CLock(){::DeleteCriticalSection(&m_CritSect);}void CLock::Enter(){::EnterCriticalSection(&m_CritSect);}void CLock::Leave(){::LeaveCriticalSection(&m_CritSect);}CAutoLock::CAutoLock(CLock *pLock){m_pLock = pLock;////Enter the lockif(m_pLock)m_pLock->Enter();}CAutoLock::~CAutoLock(){////Leave the lockif(m_pLock)m_pLock->Leave();m_pLock = NULL;}


// request.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "Work.h"class Request{};//Returns NULL if you want to complete //the process, or a pointer to the memoryRequest * GetRequest() throw(){return NULL;}//Process the request, but does not remove the memoryvoid ProcessRequest(Request * request) throw(){return;}const int NumberOfThreads = 2;int _tmain(int argc, _TCHAR* argv[]){CWorkersMgr workersMgr;////create work threadsworkersMgr.CreateWorkers();// get the request and put it into the queue in workers managerRequest *request = GetRequest();while(request){workersMgr.PushRequest(request);request = GetRequest();}////wait until the Request has been processedworkersMgr.WaitUntilWorkComplete();////destroy the work threadsworkersMgr.DestroyWorkers();return 0;}