#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <list>
#include <cstdio>
#include <exception>
#include <pthread.h>
#include "locker.h"
//线程池类:模板参数为任务对象
template< typename T >
class threadpool
{
public:
threadpool(int thread_number = 8, int max_requests = 10000);
~threadpool();
bool append(T* request);//主线程向任务队列中添加任务
private:
//注意:(当把线程函数封装在类中,this指针会作为默认的参数被传进函数中,从而和线程函数参数(void*)不能匹配。
//解决: 线程函数作为静态函数,因为在C++中静态函数没有this指针)
static void* worker(void* arg); //工程线程运行函数:调用run函数,从工作队列中取出任务,进而调用任务对象的处理函数进程任务处理
void run();
private:
int m_thread_number; //线程池中的线程数
int m_max_requests;//最大请求数量
pthread_t* m_threads;//线程数组
std::list< T* > m_workqueue;//请求队列
locker m_queuelocker;//请求队列的互斥锁
sem m_queuestat;//信号量:是否有任务需要处理
bool m_stop; //是否需要结束线程
};
template< typename T >
threadpool< T >::threadpool(int thread_number, int max_requests) :
m_thread_number(thread_number), m_max_requests(max_requests), m_stop(false), m_threads(NULL)
{
if ((thread_number <= 0) || (max_requests <= 0))
{
throw std::exception();
}
m_threads = new pthread_t[m_thread_number];
if (!m_threads)
{
throw std::exception();
}
for (int i = 0; i < thread_number; ++i)
{
printf("create the %dth thread\n", i);
if (pthread_create(m_threads + i, NULL, worker, this) != 0)//创建线程(注意线程函数为静态成员函数,且将this指针作为参数,以访问进程池的成员变量)
{
delete[] m_threads;
throw std::exception();
}
if (pthread_detach(m_threads[i])) //将工作线程设置为脱离线程(当脱离线程退出时,系统会自动回收该线程的资源),否则需要其他线程来回收该线程的资源
{
delete[] m_threads;
throw std::exception();
}
}
}
template< typename T >
threadpool< T >::~threadpool()
{
delete[] m_threads;
m_stop = true;
}
//主线程将新任务加入任务队列
template< typename T >
bool threadpool< T >::append(T* request)
{
m_queuelocker.lock();//由于任务队列被所有线程共享,因此需要先加锁
if (m_workqueue.size() > m_max_requests)
{
m_queuelocker.unlock();
return false;
}
m_workqueue.push_back(request);
m_queuelocker.unlock();
m_queuestat.post();//将信号量+1,如果大于0,则唤醒等待该信号量的工作线程
return true;
}
//线程函数
template< typename T >
void* threadpool< T >::worker(void* arg)
{
threadpool* pool = (threadpool*)arg;
pool->run();
return pool;
}
//工作线程的处理函数:从任务队列中取出任务对象,然后调用任务对象的逻辑处理函数完成客户请求任务
template< typename T >
void threadpool< T >::run()
{
while (!m_stop)
{
m_queuestat.wait();//等待信号量大于0
m_queuelocker.lock();//锁住任务队列
if (m_workqueue.empty())
{
m_queuelocker.unlock();
continue;
}
T* request = m_workqueue.front();//取出任务对象
m_workqueue.pop_front();
m_queuelocker.unlock();
if (!request)
{
continue;
}
request->process();//处理客户任务
}
}
#endif