Windows C++ 线程池

        Windows 平台C++ 没什么比较好的官方的线程池,boost里倒是有很方便的线程池,可是为了一个线程池,使用庞大的boost显然不太合适,为此,我在网上找了个demo,然后用C++模板做了些改造,基本上实现了类似boost的threadpool的功能。

首先需要解释的是,以何种方式将线程函数加入队列(我这里用的队列是CList),可以利用类模板和函数模板以及函数指针创建包含该函数的对象,执行时,只需要调用对象中的函数指针即可,这里说明下,因为函数模板在实例化之前是没有任何函数的,因此,自然就不存在指向函数模板的指针。但是可以以另一种方式创建函数模板的指针,即引入类模板。因为类模板实例化之后,其中的函数模板就有意义了。但是,这也出现了个问题,就是类模板中的函数模板无法作为函数指针在类外调用,例如在该头文件对应的cpp文件中调用。因此,不得已需要直接在头文件中定义函数体。

#pragma once

#include "Task.h"
#include <typeinfo>
class ParamTem
{
protected:
	ParamTem(){};
};


template <class ReturnType,class P0=ParamTem,class P1=ParamTem,
class P2=ParamTem,class P3=ParamTem, class P4=ParamTem,
class P5=ParamTem,class P6=ParamTem, class P7=ParamTem>
class CMyTask: public CTask,public ParamTem
{
private:
	typedef ReturnType (*FuncTem)();
	typedef ReturnType (*FuncTem0)(P0 p0);
	typedef ReturnType (*FuncTem1)(P0 p0, P1 p1);
	typedef ReturnType (*FuncTem2)(P0 p0, P1 p1, P2 p2);
	typedef ReturnType (*FuncTem3)(P0 p0, P1 p1, P2 p2,P3 p3);
	typedef ReturnType (*FuncTem4)(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4);
	typedef ReturnType (*FuncTem5)(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5);
	typedef ReturnType (*FuncTem6)(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6);
	typedef ReturnType (*FuncTem7)(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6, P7 p7);
	FuncTem ft;
	FuncTem0 ft0;
	FuncTem1 ft1;
	FuncTem2 ft2;
	FuncTem3 ft3;
	FuncTem4 ft4;
	FuncTem5 ft5;
	FuncTem6 ft6;
	FuncTem7 ft7;
	P0 p0;
	P1 p1;
	P2 p2;
	P3 p3;
	P4 p4;
	P5 p5;
	P6 p6;
	P7 p7;
public:
	CMyTask(FuncTem ft)
	{
		this->ft = ft;
	}
	CMyTask(FuncTem0 ft,P0 p0)
	{
		this->ft0 = ft;
		this->p0 = p0;
	}
	CMyTask(FuncTem1 ft,P0 p0, P1 p1)
	{
		this->ft1 = ft;
		this->p0 = p0;
		this->p1 = p1;
	}
	CMyTask(FuncTem2 ft,P0 p0, P1 p1, P2 p2)
	{
		this->ft2 = ft;
		this->p0 = p0;
		this->p1 = p1;
		this->p2 = p2;
	}
	CMyTask(FuncTem3 ft,P0 p0, P1 p1, P2 p2, P3 p3)
	{
		this->ft3 = ft;
		this->p0 = p0;
		this->p1 = p1;
		this->p2 = p2;
		this->p3 = p3;
	}
	CMyTask(FuncTem4 ft,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4)
	{
		this->ft4 = ft;
		this->p0 = p0;
		this->p1 = p1;
		this->p2 = p2;
		this->p3 = p3;
		this->p4 = p4;
	}
	CMyTask(FuncTem5 ft,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5)
	{
		this->ft5 = ft;
		this->p0 = p0;
		this->p1 = p1;
		this->p2 = p2;
		this->p3 = p3;
		this->p4 = p4;
		this->p5 = p5;
	}
	CMyTask(FuncTem6 ft,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6)
	{
		this->ft6 = ft;
		this->p0 = p0;
		this->p1 = p1;
		this->p2 = p2;
		this->p3 = p3;
		this->p4 = p4;
		this->p5 = p5;
		this->p6 = p6;
	}
	CMyTask(FuncTem7 ft,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6, P7 p7)
	{
		this->ft7 = ft;
		this->p0 = p0;
		this->p1 = p1;
		this->p2 = p2;
		this->p3 = p3;
		this->p4 = p4;
		this->p5 = p5;
		this->p6 = p6;
		this->p7 = p7;
	}
	virtual void Run()
	{
		if(!strcmp(typeid(P0).name(),"class ParamTem"))
		{
			this->ft();
		}
		else if(!strcmp(typeid(P1).name(),"class ParamTem"))
		{
			this->ft0(this->p0);
		}
		else if(!strcmp(typeid(P2).name(),"class ParamTem"))
		{
			this->ft1(this->p0,this->p1);
		}
		else if(!strcmp(typeid(P3).name(),"class ParamTem"))
		{
			this->ft2(this->p0,this->p1,this->p2);
		}
		else if(!strcmp(typeid(P4).name(),"class ParamTem"))
		{
			this->ft3(this->p0,this->p1,this->p2,this->p3);
		}
		else if(!strcmp(typeid(P5).name(),"class ParamTem"))
		{
			this->ft4(this->p0,this->p1,this->p2,this->p3,this->p4);
		}
		else if(!strcmp(typeid(P6).name(),"class ParamTem"))
		{
			this->ft5(this->p0,this->p1,this->p2,this->p3,this->p4,this->p5);
		}
		else if(!strcmp(typeid(P7).name(),"class ParamTem"))
		{
			this->ft6(this->p0,this->p1,this->p2,this->p3,this->p4,this->p5\
				,this->p6);
		}
		else if(strcmp(typeid(P7).name(),"class ParamTem"))
		{
			this->ft7(this->p0,this->p1,this->p2,this->p3,this->p4,this->p5\
				,this->p6,this->p7);
		}
	}
};
如上只定义了到含8个参数的函数模板,如果你们需要执行的函数的参数可能更多,只需要依葫芦画瓢,添加相应的函数模板即可。

另外定义这个类模板是因为在将函数加入队列貌似不太好办,我也不确定办不了,但是我是没搞出来,所以需要借助对象来保存函数。
这里说明两个地方,首先为什么要定义一个父类,而且,父类的构造函数是protected权限的,这个为了避免其他地方调用这个类生成对象,因为它是MyTask的默认模板参数,默认模板参数则是为了避免参数较少时依然要填满所以的模板参数声明。


#include "StdAfx.h"
#include "MyThreadPool.h"

CMyThreadPool::CMyThreadPool(int nThreadCount/* =5 */)
{
	this->m_nThreadCount=nThreadCount; 
	m_bthreadflag = TRUE;
	m_hsemaphore = CreateSemaphore(NULL, 0, 5000, NULL);
	InitializeCriticalSection(&m_csThreadQueue);
	InitializeCriticalSection(&m_csTaskQueue);
	m_pThreadItemList=new std::list<ThreadItem*>;
	m_pTaskList=new std::list<CTask*>;
	EnterCriticalSection(&m_csThreadQueue);
	for (int i=0;i<m_nThreadCount;i++)
	{
		ThreadItem* pItem=new ThreadItem();
		if (pItem)
		{
			pItem->pThreadPool=this;
			pItem->bThreadFlag=TRUE;
			pItem->hThreadHandle= (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (LPVOID)pItem, 0, &pItem->dwThreadID);
			printf("创建线程 threadid:%d\n",pItem->dwThreadID);
			m_pThreadItemList->push_back(pItem);
		}
	}
	LeaveCriticalSection(&m_csThreadQueue);
}

UINT WINAPI CMyThreadPool::ThreadFunc(LPVOID lpParameter /* = NULL */)
{
	//CMyThreadPool* pmyThreadPool = (CMyThreadPool*) lpParameter;
	ThreadItem *pItem = (ThreadItem*) lpParameter;
	CTask * m_pTask = NULL;
	while(pItem->bThreadFlag)
	{
		WaitForSingleObject(pItem->pThreadPool->m_hsemaphore, INFINITE);
		EnterCriticalSection(&pItem->pThreadPool->m_csTaskQueue);
		m_pTask = pItem->pThreadPool->m_pTaskList->front();
		if(m_pTask)
		{
			pItem->pThreadPool->m_pTaskList->pop_front();
		}
		LeaveCriticalSection(&pItem->pThreadPool->m_csTaskQueue);
		m_pTask->Run();
		delete m_pTask;
	}
	return NULL;
}

void CMyThreadPool::StopAllThread()
{
	EnterCriticalSection(&m_csThreadQueue);
	while (!m_pThreadItemList->empty())
	{		
		ThreadItem* pThreadItem=m_pThreadItemList->front();
		if (pThreadItem)
		{
			//TRACE("结束线程 %d\n",pThreadItem->dwThreadID);
			printf("结束线程 %d\n",pThreadItem->dwThreadID);
			pThreadItem->bThreadFlag=FALSE;
			WaitForSingleObject(pThreadItem->hThreadHandle,INFINITE);
			m_pThreadItemList->pop_front();
			delete(pThreadItem);			
		}		
	}
	LeaveCriticalSection(&m_csThreadQueue);
}


void CMyThreadPool::schedule(CTask* pTask)
{	
	EnterCriticalSection(&m_csTaskQueue);
	if (m_pTaskList)
	{
		m_pTaskList->push_back(pTask);
	}
	ReleaseSemaphore(this->m_hsemaphore,1,NULL);
	LeaveCriticalSection(&m_csTaskQueue);
}

CMyThreadPool::~CMyThreadPool()
{
	StopAllThread();
	DeleteCriticalSection(&m_csThreadQueue);
	DeleteCriticalSection(&m_csTaskQueue);
	delete m_pTaskList;
	delete m_pThreadItemList;
}
这是线程池源码,当然正如我在上面所说道的函数模板的问题,在此,其定义的另一个schedule函数需要在头文件中直接定义。
#pragma once
#include "MyTask.h"
#include <list>
#include <process.h>
class CMyThreadPool;
struct ThreadItem
{
	HANDLE hThreadHandle;       //线程句柄
	UINT  dwThreadID;          //线程ID
	BOOL   bThreadFlag;         //线程运行标识
	CMyThreadPool* pThreadPool;   //属于哪个线程池
	ThreadItem()
	{
		hThreadHandle=NULL;
		dwThreadID=0;
		bThreadFlag=FALSE;
		pThreadPool=NULL;
	}
};

class CMyThreadPool
{
public:
	//CMyThreadPool();
	CMyThreadPool(int nThreadCount=5);
	virtual ~CMyThreadPool();
	static UINT WINAPI ThreadFunc(LPVOID lpParameter = NULL);
public:
	void schedule(CTask* pTask);
	std::list<ThreadItem*>* GetThreadItemList() {return m_pThreadItemList;};
	std::list<CTask*>*      GetTaskList() {return m_pTaskList;};
	void               StopAllThread();
	void               AdjustSize(int nThreadCount);  //动态调整线程池规模
protected:
	//static 
private:
	BOOL m_bthreadflag;   
	int m_nThreadCount;    //线程池中线程的个数
	HANDLE m_hsemaphore;
	std::list<ThreadItem*>*  m_pThreadItemList;
	std::list<CTask*>*       m_pTaskList;
	CRITICAL_SECTION    m_csThreadQueue;
	CRITICAL_SECTION    m_csTaskQueue;

	//Schedule 函数定义

public:
	template<typename ReturnType>
	void schedule(ReturnType Func())
	{
		CTask * pTask = new CMyTask<ReturnType>(Func);
		EnterCriticalSection(&m_csTaskQueue);
		if (m_pTaskList)
		{
			m_pTaskList->push_back(pTask);
		}
		ReleaseSemaphore(this->m_hsemaphore,1,NULL);
		LeaveCriticalSection(&m_csTaskQueue);
	}
public:
	template <typename ReturnType, typename P0>
	void schedule(ReturnType Func(P0 p0),P0 p0)
	{
		CTask * pTask = new CMyTask<ReturnType,P0>(Func, p0);
		EnterCriticalSection(&m_csTaskQueue);
		if (m_pTaskList)
		{
			m_pTaskList->push_back(pTask);
		}
		ReleaseSemaphore(this->m_hsemaphore,1,NULL);
		LeaveCriticalSection(&m_csTaskQueue);
	}
	template <typename ReturnType, typename P0, typename P1>
	void schedule(ReturnType Func(P0 p0, P1 p1),P0 p0, P1 p1)
	{
		CTask * pTask = new CMyTask<ReturnType,P0,P1>(Func, p0, p1);
		EnterCriticalSection(&m_csTaskQueue);
		if (m_pTaskList)
		{
			m_pTaskList->push_back(pTask);
		}
		ReleaseSemaphore(this->m_hsemaphore,1,NULL);
		LeaveCriticalSection(&m_csTaskQueue);
	}
	template <typename ReturnType, typename P0, typename P1,typename P2>
	void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2),P0 p0, P1 p1, P2 p2)
	{
		CTask * pTask = new CMyTask<ReturnType,P0,P1,P2>(Func, p0, p1, p2);
		EnterCriticalSection(&m_csTaskQueue);
		if (m_pTaskList)
		{
			m_pTaskList->push_back(pTask);
		}
		ReleaseSemaphore(this->m_hsemaphore,1,NULL);
		LeaveCriticalSection(&m_csTaskQueue);
	}
	template <typename ReturnType, typename P0, typename P1,typename P2, typename P3>
	void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3),P0 p0, P1 p1, P2 p2, P3 p3)
	{
		CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3>(Func, p0, p1, p2, p3);
		EnterCriticalSection(&m_csTaskQueue);
		if (m_pTaskList)
		{
			m_pTaskList->push_back(pTask);
		}
		ReleaseSemaphore(this->m_hsemaphore,1,NULL);
		LeaveCriticalSection(&m_csTaskQueue);
	}
	template <typename ReturnType, typename P0, typename P1,typename P2, typename P3\
	,typename P4>
	void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4)\
	,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4)
	{
		CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3,P4>(Func, p0, p1, p2, p3, p4);
		EnterCriticalSection(&m_csTaskQueue);
		if (m_pTaskList)
		{
			m_pTaskList->push_back(pTask);
		}
		ReleaseSemaphore(this->m_hsemaphore,1,NULL);
		LeaveCriticalSection(&m_csTaskQueue);
	}
	template <typename ReturnType, typename P0, typename P1,typename P2, typename P3\
		,typename P4, typename P5>
	void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5)\
	,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5)
	{
		CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3,P4,P5>(Func, p0, p1, p2, p3, p4, p5);
		EnterCriticalSection(&m_csTaskQueue);
		if (m_pTaskList)
		{
			m_pTaskList->push_back(pTask);
		}
		ReleaseSemaphore(this->m_hsemaphore,1,NULL);
		LeaveCriticalSection(&m_csTaskQueue);
	}
	template <typename ReturnType, typename P0, typename P1,typename P2, typename P3\
	,typename P4, typename P5, typename P6>
	void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6),\
	P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6)
	{
		CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3,P4,P5,P6>(Func, p0, p1, p2, p3, p4, p5, p6);
		EnterCriticalSection(&m_csTaskQueue);
		if (m_pTaskList)
		{
			m_pTaskList->push_back(pTask);
		}
		ReleaseSemaphore(this->m_hsemaphore,1,NULL);
		LeaveCriticalSection(&m_csTaskQueue);
	}
	template <typename ReturnType, typename P0, typename P1,typename P2, typename P3\
	,typename P4, typename P5, typename P6,typename P7>
	void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6, P7 p7),\
	P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6, P7 p7)
	{
		CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3,P4,P5,P6,P7>(Func, p0, p1, p2, p3, p4, p5, p6,p7);
		EnterCriticalSection(&m_csTaskQueue);
		if (m_pTaskList)
		{
			m_pTaskList->push_back(pTask);
		}
		ReleaseSemaphore(this->m_hsemaphore,1,NULL);
		LeaveCriticalSection(&m_csTaskQueue);
	}
};

这里我用到了一个信号量和一个临界区来保证线程安全,信号量的作用是每有一个执行的对象加入队列,就+1,反之就-1,然后利用WaitforSingleObject来让所有线程等待。临界区就不用说了,这是为了保证MyTask对象的队列的线程安全的。

最后附上线程池源码下载地址http://download.csdn.net/detail/yuguanquan1990/8109379


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值