ThreadPool.h
/*++
Copyright (C) 1996 - 2000. Linkage Corporation. All rights reserved.
Module Name
ThreadPool.h
Abstract
Declare class CThreadPool.
Created by
HanZhiQian, Network Management Product Department, ID Card No.824
at 3/25/2004 11:05
Modified
who when why
HanZhiQian 6/2/2004 to add more useful functions
HanZhiQian 6/21/2004 to add function 'WaitForIdleState'
PLEASE KEEP THE COMMENT ABOVE. THANK YOU!
--*/
#ifndef _THREAD_POOL_H
#define _THREAD_POOL_H
#include
#include
#include
#include
#include
#ifndef ENTER_HP_UX
using namespace std;
#endif
typedef int (*RequestRoutine)(void* arg);
class CThreadPool;
class CRequest {
public:
CRequest(RequestRoutine cbrr, void *arg);
CRequest();
virtual ~CRequest();
protected:
void* m_arg;
int m_ret;
RequestRoutine m_cbrr;
friend class CThreadPool;
};
typedef list
class CThreadPool
{
public:
CThreadPool(int size);
virtual ~CThreadPool();
public:
enum WORKER_STATUS {
WS_IDLE,
WS_BUSY
}; // worker thread status
protected:
int m_nSize; // worker thread count
REQUEST_LIST m_lstRequests; // request queue
pthread_t* m_ptList; // thread id list of work thread
WORKER_STATUS* m_wsList; // status list of worker thread
sem_t m_sem; // semaphore
pthread_mutex_t m_lock; // request queue read-write lock
bool m_bStopping; // setting this flag true will
// prevent any new request from being pushed into the queue
private:
static void* worker_proc(void* arg); // worker thread callback routine
// added at 6/2/2004, by hanzq
void SetWorkerStatus(pthread_t tid, WORKER_STATUS ws); // this routine sets a worker's status
public:
// added at 6/2/2004, by hanzq
int IsIdle();
int QueueRequest(RequestRoutine cbrr, void* arg); // put a request in the back of the
// request queue
int PriorRequest(RequestRoutine cbrr, void* arg); // put a request in the front of the
// request queue
int Start(); // this routine creates all worker threads by
// internal parameters and sets their initial status
void Stop(); // this routine stops all worker threads at once, clears request queue
// and workers' status
// added at 6/2/2004, by hanzq
void SafeStop(); // this routine emits a terminating signal and waits until
// all requests are handled and all workers finish their current job.
//返回线程等待队列大小
int getRequests_size();
//返回线程正在处理的队列大小
int getWorkProc_size();
#ifdef HP
// Solaris does not support the following characteristics
// added at 6/2/2004, by hanzq
void Suspend(); // this routine suspends all worker threads
// added at 6/2/2004, by hanzq
void Resume(); // this routine resumes all worker threads
#endif // HP
// added at 6/21/2004, by hanzq
void WaitForIdleState(); // to wait until all worker threads are idle
};
#endif // _THREAD_POOL_H
ThreadPool.cpp
/*++
Copyright (C) 1996 - 2000. Linkage Corporation. All rights reserved.
Module Name
ThreadPool.h
Abstract
Implements class CThreadPool.
Created by
HanZhiQian, Network Management Product Department, ID Card No.824
at 3/25/2004 11:05
Modified
who when why
PLEASE KEEP THE COMMENT ABOVE. THANK YOU!
--*/
#include "ThreadPool.h"
#ifndef ENTER_HP_UX
#include
using namespace std;
#endif
CRequest::CRequest(RequestRoutine cbrr, void *arg)
{
m_cbrr = cbrr;
m_arg = arg;
m_ret = 0;
}
CRequest::CRequest()
{
m_cbrr = NULL;
m_arg = 0;
m_ret = 0;
}
CRequest::~CRequest()
{
}
CThreadPool::CThreadPool(int size)
{
m_nSize = size;
m_ptList = new pthread_t[m_nSize];
m_wsList = new WORKER_STATUS[m_nSize];
}
CThreadPool::~CThreadPool()
{
Stop();
if (m_ptList!=NULL) {
delete[] m_ptList;
m_ptList = NULL;
}
if (m_wsList!=NULL) {
delete[] m_wsList;
m_wsList = NULL;
}
}
int CThreadPool::QueueRequest(RequestRoutine cbrr, void* arg)
{
if (m_bStopping)
return -1;
pthread_mutex_lock(&m_lock);
m_lstRequests.push_back(CRequest(cbrr, arg));
pthread_mutex_unlock(&m_lock);
sem_post(&m_sem);
IsIdle();
return 0;
}
int CThreadPool::PriorRequest(RequestRoutine cbrr, void* arg)
{
if (m_bStopping)
return -1;
pthread_mutex_lock(&m_lock);
m_lstRequests.push_front(CRequest(cbrr, arg));
pthread_mutex_unlock(&m_lock);
sem_post(&m_sem);
return 0;
}
int CThreadPool::Start()
{
sem_init(&m_sem, 0, 0);
pthread_mutex_init(&m_lock, NULL);
for (int i=0; i
pthread_attr_t thread_attr;
size_t stack_size;
int status;
stack_size = 1024*1024*4;
status = pthread_attr_init (&thread_attr);
status = pthread_attr_setstacksize(&thread_attr, stack_size);
for (int i=0; i
if (pthread_create(&m_ptList[i], &thread_attr, worker_proc, (void *)this)!=0)
return -1;
}
m_bStopping = false;
return 0;
}
void CThreadPool::Stop()
{
if (m_ptList==NULL)
return;
for (int i=0;i
if (m_ptList[i]!=0) {
pthread_cancel(m_ptList[i]);
m_ptList[i] = 0;
}
}
sem_destroy(&m_sem);
pthread_mutex_destroy(&m_lock);
//REQUEST_LIST::iterator rli;
//for (rli=m_lstRequests.begin();rli!=m_lstRequests.end();rli++)
//{
// CRequest *rq = (*rli);
// if (rq!=NULL)
// delete rq;
//}
m_lstRequests.clear();
}
void CThreadPool::SafeStop()
{
m_bStopping = true;
while (1) {
if (IsIdle()==0 // all workers are idle
&& m_lstRequests.size()==0) // all requests are handled
break;
sleep(1); // sleep for 1s
}
// call Stop()
Stop();
}
void* CThreadPool::worker_proc(void* arg)
{
CThreadPool *pThis = (CThreadPool *)arg;
if (pThis==NULL)
return 0;
while (1) {
sem_wait(&pThis->m_sem);
pthread_mutex_lock(&pThis->m_lock); // wait until the request queue
// can be read
CRequest rq;
if (pThis->m_lstRequests.size()>0) {
rq = pThis->m_lstRequests.front();
pThis->m_lstRequests.pop_front();
}
pthread_mutex_unlock(&pThis->m_lock);
if (rq.m_cbrr!=NULL) {
pThis->SetWorkerStatus(pthread_self(), CThreadPool::WS_BUSY);
rq.m_ret = rq.m_cbrr(rq.m_arg);
pThis->SetWorkerStatus(pthread_self(), CThreadPool::WS_IDLE);
}
// sleep for a instant
struct timeval tvTime;
tvTime.tv_sec = 0;
tvTime.tv_usec = 10000;
select(0,NULL,NULL,NULL,&tvTime);
}
return 0;
}
void CThreadPool::SetWorkerStatus(pthread_t tid, WORKER_STATUS ws)
{
// find and set
for (int i=0;i
m_wsList[i] = ws;
break;
}
}
}
int CThreadPool::IsIdle()
{
#ifdef _DEBUG
int busy = 0, idle = 0;
for (int i=0;i
busy ++;
else
idle ++;
#endif
for (int imm=0;imm
return 1;
return 0;
}
#ifdef HP
void CThreadPool::Resume()
{
for (int i=0;i
}
void CThreadPool::Suspend()
{
for (int i=0;i
}
#endif // HP
void CThreadPool::WaitForIdleState()
{
//const int TIMEOUT = 5*60;
//for (int i=0;i
{
if (IsIdle()==0 // all workers are idle
&& m_lstRequests.size()==0) // all requests are handled
{
break;
}
//cout<<"m_lstRequests.size()="<
}
}
/* BEGIN: Added by 69937, 2013/5/14 问题单号:打印线程等待的队列 */
int CThreadPool::getRequests_size()
{
int size = m_lstRequests.size();
return size;
}
/* END: Added by 69937, 2013/5/14 */
/* BEGIN: Added by 69937, 2013/5/23 问题单号:打印线程正在处理的队列 */
int CThreadPool::getWorkProc_size()
{
int busy = 0;
for (int i=0;i
busy ++;
return busy;
}
/* END: Added by 69937, 2013/5/23 */
调用
CThreadPool * ThreadPool = new CThreadPool(ThreadNum);
ThreadPool->Start();
(gatherThread调用的函数名,DeviceList入参)
ThreadPool->QueueRequest((int (*)(void*))gatherThread, DeviceList);